mirror of https://github.com/pyodide/pyodide.git
160 lines
5.1 KiB
Python
160 lines
5.1 KiB
Python
|
import pydantic
|
||
|
from packaging.version import Version
|
||
|
from pydantic import BaseModel
|
||
|
|
||
|
|
||
|
class CrossBuildEnvReleaseSpec(BaseModel):
|
||
|
# The version of the Pyodide
|
||
|
version: str
|
||
|
# The URL to the cross-build environment tarball
|
||
|
url: str
|
||
|
# The SHA256 hash of the cross-build environment tarball
|
||
|
sha256: str | None = None
|
||
|
# The version of the Python interpreter
|
||
|
python_version: str
|
||
|
# The version of the Emscripten SDK
|
||
|
emscripten_version: str
|
||
|
# Minimum and maximum pyodide-build versions that is compatible with this release
|
||
|
min_pyodide_build_version: str | None = None
|
||
|
max_pyodide_build_version: str | None = None
|
||
|
|
||
|
class Config:
|
||
|
extra = pydantic.Extra.forbid
|
||
|
title = "CrossBuildEnvReleasesSpec"
|
||
|
|
||
|
@property
|
||
|
def python_version_tuple(self) -> tuple[int, int, int]:
|
||
|
v = Version(self.python_version)
|
||
|
return (v.major, v.minor, v.micro)
|
||
|
|
||
|
@property
|
||
|
def emscripten_version_tuple(self) -> tuple[int, int, int]:
|
||
|
v = Version(self.emscripten_version)
|
||
|
return (v.major, v.minor, v.micro)
|
||
|
|
||
|
def is_compatible(
|
||
|
self,
|
||
|
python_version: str | None = None,
|
||
|
emscripten_version: str | None = None,
|
||
|
pyodide_build_version: str | None = None,
|
||
|
) -> bool:
|
||
|
"""
|
||
|
Check if the release is compatible with the given params
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
python_version
|
||
|
The version of the Python interpreter. If None, it is not checked
|
||
|
emscripten_version
|
||
|
The version of the Emscripten SDK. If None, it is not checked
|
||
|
pyodide_build_version
|
||
|
The version of the pyodide-build. If None, it is not checked
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
bool
|
||
|
True if the release is compatible with the given params, False otherwise
|
||
|
"""
|
||
|
if python_version is not None:
|
||
|
major, minor, _ = self.python_version_tuple
|
||
|
v = Version(python_version)
|
||
|
if major != v.major or minor != v.minor:
|
||
|
return False
|
||
|
|
||
|
if (
|
||
|
emscripten_version is not None
|
||
|
and self.emscripten_version != emscripten_version
|
||
|
):
|
||
|
# TODO: relax the emscripten version check
|
||
|
return False
|
||
|
|
||
|
if pyodide_build_version is not None:
|
||
|
if self.min_pyodide_build_version is not None:
|
||
|
if Version(pyodide_build_version) < Version(
|
||
|
self.min_pyodide_build_version
|
||
|
):
|
||
|
return False
|
||
|
if self.max_pyodide_build_version is not None:
|
||
|
if Version(pyodide_build_version) > Version(
|
||
|
self.max_pyodide_build_version
|
||
|
):
|
||
|
return False
|
||
|
|
||
|
return True
|
||
|
|
||
|
|
||
|
class CrossBuildEnvMetaSpec(BaseModel):
|
||
|
releases: dict[str, CrossBuildEnvReleaseSpec]
|
||
|
|
||
|
class Config:
|
||
|
extra = pydantic.Extra.forbid
|
||
|
title = "CrossBuildEnvMetaSpec"
|
||
|
description = (
|
||
|
"The specification for the Pyodide cross-build environment metadata"
|
||
|
)
|
||
|
|
||
|
def list_compatible_releases(
|
||
|
self,
|
||
|
python_version: str | None = None,
|
||
|
emscripten_version: str | None = None,
|
||
|
pyodide_build_version: str | None = None,
|
||
|
) -> list[CrossBuildEnvReleaseSpec]:
|
||
|
"""
|
||
|
Get the list of compatible releases
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
python_version
|
||
|
The version of the Python interpreter. If None, it is not checked
|
||
|
emscripten_version
|
||
|
The version of the Emscripten SDK. If None, it is not checked
|
||
|
pyodide_build_version
|
||
|
The version of the pyodide-build. If None, it is not checked
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
The list of compatible releases, sorted by version number in descending order (latest first)
|
||
|
"""
|
||
|
|
||
|
return sorted(
|
||
|
[
|
||
|
release
|
||
|
for release in self.releases.values()
|
||
|
if release.is_compatible(
|
||
|
python_version, emscripten_version, pyodide_build_version
|
||
|
)
|
||
|
],
|
||
|
key=lambda r: Version(r.version),
|
||
|
reverse=True,
|
||
|
)
|
||
|
|
||
|
def get_latest_compatible_release(
|
||
|
self,
|
||
|
python_version: str | None = None,
|
||
|
emscripten_version: str | None = None,
|
||
|
pyodide_build_version: str | None = None,
|
||
|
) -> CrossBuildEnvReleaseSpec | None:
|
||
|
"""
|
||
|
Get the latest compatible release
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
python_version
|
||
|
The version of the Python interpreter. If None, it is not checked
|
||
|
emscripten_version
|
||
|
The version of the Emscripten SDK. If None, it is not checked
|
||
|
pyodide_build_version
|
||
|
The version of the pyodide-build. If None, it is not checked
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
The latest compatible release, or None if no compatible release is found
|
||
|
"""
|
||
|
compatible_releases = self.list_compatible_releases(
|
||
|
python_version, emscripten_version, pyodide_build_version
|
||
|
)
|
||
|
if not compatible_releases:
|
||
|
return None
|
||
|
|
||
|
return compatible_releases[0]
|