* Add PEP 723 metadata for various `bin` scripts * Use a subprocess to install chromium * Regenerate image * Update shebangs Co-Authored-By: Henry Schreiner <HenrySchreinerIII@gmail.com> * Add cibuildwheel local dependency for some scripts Co-Authored-By: Henry Schreiner <HenrySchreinerIII@gmail.com> * Remove `bin` dependency group fully * Add CSS for styling the diagram Co-Authored-By: Joe Rickerby <1244307+joerick@users.noreply.github.com> * Restore image to original * Install `uv` for PyLint to find it * Drop setup-python too in favour of setup-uv * Revert "Drop setup-python too in favour of setup-uv" This reverts commit 663db5c253f18bd09229ea5dbf92f7f6aa8ebf1c. * Make `uv` venv backend for nox optional again --------- Co-authored-by: Henry Schreiner <HenrySchreinerIII@gmail.com> Co-authored-by: Joe Rickerby <1244307+joerick@users.noreply.github.com>
156 lines
4.7 KiB
Python
Executable File
156 lines
4.7 KiB
Python
Executable File
#!/usr/bin/env -S uv run --script
|
|
|
|
# /// script
|
|
# dependencies = [
|
|
# "click",
|
|
# "packaging",
|
|
# "requests",
|
|
# "rich",
|
|
# ]
|
|
# ///
|
|
|
|
|
|
import dataclasses
|
|
import difflib
|
|
import logging
|
|
import tomllib
|
|
from pathlib import Path
|
|
from typing import Final
|
|
|
|
import click
|
|
import packaging.specifiers
|
|
import requests
|
|
import rich
|
|
from packaging.version import InvalidVersion, Version
|
|
from rich.logging import RichHandler
|
|
from rich.syntax import Syntax
|
|
|
|
log = logging.getLogger("cibw")
|
|
|
|
# Looking up the dir instead of using utils.resources_dir
|
|
# since we want to write to it.
|
|
DIR: Final[Path] = Path(__file__).parent.parent.resolve()
|
|
RESOURCES_DIR: Final[Path] = DIR / "cibuildwheel/resources"
|
|
|
|
NODEJS_DIST: Final[str] = "https://nodejs.org/dist/"
|
|
NODEJS_INDEX: Final[str] = f"{NODEJS_DIST}index.json"
|
|
|
|
|
|
@dataclasses.dataclass(frozen=True, order=True)
|
|
class VersionTuple:
|
|
version: Version
|
|
version_string: str
|
|
|
|
|
|
def parse_nodejs_index() -> list[VersionTuple]:
|
|
versions: list[VersionTuple] = []
|
|
response = requests.get(NODEJS_INDEX)
|
|
response.raise_for_status()
|
|
versions_info = response.json()
|
|
for version_info in versions_info:
|
|
version_string = version_info.get("version", "???")
|
|
if not version_info.get("lts", False):
|
|
log.debug("Ignoring non LTS release %r", version_string)
|
|
continue
|
|
if "linux-x64" not in version_info.get("files", []):
|
|
log.warning(
|
|
"Ignoring release %r which does not include a linux-x64 binary", version_string
|
|
)
|
|
continue
|
|
try:
|
|
version = Version(version_string)
|
|
if version.is_devrelease:
|
|
log.info("Ignoring development release %r", str(version))
|
|
continue
|
|
if version.is_prerelease:
|
|
log.info("Ignoring pre-release %r", str(version))
|
|
continue
|
|
versions.append(VersionTuple(version, version_string))
|
|
except InvalidVersion:
|
|
log.warning("Ignoring release %r", version_string)
|
|
versions.sort(reverse=True)
|
|
return versions
|
|
|
|
|
|
@click.command()
|
|
@click.option("--force", is_flag=True)
|
|
@click.option(
|
|
"--level", default="INFO", type=click.Choice(["WARNING", "INFO", "DEBUG"], case_sensitive=False)
|
|
)
|
|
def update_nodejs(force: bool, level: str) -> None:
|
|
logging.basicConfig(
|
|
level="INFO",
|
|
format="%(message)s",
|
|
datefmt="[%X]",
|
|
handlers=[RichHandler(rich_tracebacks=True, markup=True)],
|
|
)
|
|
log.setLevel(level)
|
|
|
|
toml_file_path = RESOURCES_DIR / "nodejs.toml"
|
|
|
|
original_toml = toml_file_path.read_text()
|
|
with toml_file_path.open("rb") as f:
|
|
nodejs_data = tomllib.load(f)
|
|
|
|
nodejs_data.pop("url")
|
|
|
|
major_versions = [VersionTuple(Version(key), key) for key in nodejs_data]
|
|
major_versions.sort(reverse=True)
|
|
|
|
versions = parse_nodejs_index()
|
|
|
|
# update existing versions, 1 per LTS
|
|
for major_version in major_versions:
|
|
current = Version(nodejs_data[major_version.version_string])
|
|
specifier = packaging.specifiers.SpecifierSet(
|
|
specifiers=f"=={major_version.version.major}.*"
|
|
)
|
|
for version in versions:
|
|
if specifier.contains(version.version) and version.version > current:
|
|
nodejs_data[major_version.version_string] = version.version_string
|
|
break
|
|
|
|
# check for a new major LTS to insert
|
|
if versions and versions[0].version.major > major_versions[0].version.major:
|
|
major_versions.insert(
|
|
0,
|
|
VersionTuple(Version(str(versions[0].version.major)), f"v{versions[0].version.major}"),
|
|
)
|
|
nodejs_data[major_versions[0].version_string] = versions[0].version_string
|
|
|
|
versions_toml = "\n".join(
|
|
f'{major_version.version_string} = "{nodejs_data[major_version.version_string]}"'
|
|
for major_version in major_versions
|
|
)
|
|
result_toml = f'url = "{NODEJS_DIST}"\n{versions_toml}\n'
|
|
|
|
rich.print() # spacer
|
|
|
|
if original_toml == result_toml:
|
|
rich.print("[green]Check complete, nodejs version unchanged.")
|
|
return
|
|
|
|
rich.print("nodejs version updated.")
|
|
rich.print("Changes:")
|
|
rich.print()
|
|
|
|
toml_relpath = toml_file_path.relative_to(DIR).as_posix()
|
|
diff_lines = difflib.unified_diff(
|
|
original_toml.splitlines(keepends=True),
|
|
result_toml.splitlines(keepends=True),
|
|
fromfile=toml_relpath,
|
|
tofile=toml_relpath,
|
|
)
|
|
rich.print(Syntax("".join(diff_lines), "diff", theme="ansi_light"))
|
|
rich.print()
|
|
|
|
if force:
|
|
toml_file_path.write_text(result_toml)
|
|
rich.print("[green]TOML file updated.")
|
|
else:
|
|
rich.print("[yellow]File left unchanged. Use --force flag to update.")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
update_nodejs()
|