Add redbot-update command for updating Red (#6734)

This commit is contained in:
Jakub Kuczys
2026-05-14 00:14:43 +02:00
committed by GitHub
parent 899f24ceca
commit 7e2a74b276
22 changed files with 3016 additions and 76 deletions
+119
View File
@@ -0,0 +1,119 @@
import enum
import dataclasses
import json
import os
import sys
from pathlib import Path
from typing import Any, ClassVar, Dict, Iterable, NoReturn, Optional, Tuple, Union
from . import cmd, common
_RUNNER_DIR = Path(os.environ.get(common.RUNNER_DIR_ENV_VAR, ""))
class RequestType(enum.Enum):
exec = "exec"
spawn_command = "spawn_command"
@dataclasses.dataclass(frozen=True)
class RequestInput:
request_type: ClassVar[RequestType]
request_new_python_exe: str
request_new_start_args: Tuple[str, ...]
request_set_env_vars: Dict[str, Optional[str]]
@dataclasses.dataclass(frozen=True)
class RequestOutput:
request_type: RequestType
@dataclasses.dataclass(frozen=True)
class ExecRequestInput(RequestInput):
request_type: ClassVar = RequestType.exec
@dataclasses.dataclass(frozen=True)
class ExecRequestOutput(RequestOutput):
pass
@dataclasses.dataclass(frozen=True)
class SpawnProcessRequestInput(RequestInput):
request_type: ClassVar = RequestType.spawn_command
command: str
args: Tuple[str, ...]
env: Optional[Dict[str, str]]
@dataclasses.dataclass(frozen=True)
class SpawnProcessRequestOutput(RequestOutput):
exit_code: int
exited: bool
pid: int
sys: Any
sys_usage: Dict[str, Any]
system_time: int
user_time: int
def make_request(request: RequestInput) -> NoReturn:
with open(_RUNNER_DIR / "request_input.json", "w", encoding="utf-8") as fp:
data = dataclasses.asdict(request)
data["request_type"] = request.request_type.value
json.dump(data, fp)
raise SystemExit(3)
def get_request_output() -> Union[ExecRequestOutput, SpawnProcessRequestOutput]:
with open(_RUNNER_DIR / "request_output.json", encoding="utf-8") as fp:
data = json.load(fp)
request_type = RequestType(data.pop("request_type"))
if request_type == RequestType.exec:
return ExecRequestOutput(request_type=request_type)
elif request_type == RequestType.spawn_command:
return SpawnProcessRequestOutput(request_type=request_type, **data)
raise RuntimeError("unreachable code")
def make_spawn_process_request(
command: str,
*args: str,
env: Optional[Dict[str, str]] = None,
new_start_args: Iterable[str],
new_python_exe: str = sys.executable,
set_env_vars: Optional[Dict[str, Optional[str]]] = None,
) -> NoReturn:
if set_env_vars is None:
set_env_vars = {}
debug_args = (cmd.arg_names.DEBUG,) * common.get_log_cli_level()
request = SpawnProcessRequestInput(
request_new_python_exe=new_python_exe,
request_new_start_args=("-m", "redbot._update.internal", *debug_args, *new_start_args),
request_set_env_vars=set_env_vars,
command=command,
args=args,
env=env,
)
make_request(request)
def make_exec_request(
new_python_exe: str,
*new_start_args: str,
set_env_vars: Optional[Dict[str, Optional[str]]] = None,
) -> NoReturn:
if set_env_vars is None:
set_env_vars = {}
debug_args = (cmd.arg_names.DEBUG,) * common.get_log_cli_level()
request = ExecRequestInput(
request_new_python_exe=new_python_exe,
request_new_start_args=("-m", "redbot._update.internal", *debug_args, *new_start_args),
request_set_env_vars=set_env_vars,
)
make_request(request)
def get_wrapper_executable() -> Path:
return Path(os.environ[common.RUNNER_WRAPPER_EXE_ENV_VAR])