chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 13:17:40 +08:00
commit f1825c8ceb
10096 changed files with 2364182 additions and 0 deletions
+230
View File
@@ -0,0 +1,230 @@
import abc
import functools
import inspect
import logging
import os
import socket
from typing import (
Any,
Callable,
ContextManager,
Dict,
List,
Optional,
Tuple,
TypeVar,
Union,
)
import ray
from ray._common.network_utils import find_free_port, is_ipv6
from ray.actor import ActorHandle
from ray.air._internal.util import (
StartTraceback,
StartTracebackWithWorkerRank,
)
from ray.exceptions import RayActorError
from ray.types import ObjectRef
T = TypeVar("T")
logger = logging.getLogger(__name__)
def check_for_failure(
remote_values: List[ObjectRef],
) -> Tuple[bool, Optional[Exception]]:
"""Check for actor failure when retrieving the remote values.
Args:
remote_values: List of object references from Ray actor methods.
Returns:
A tuple of (bool, Exception). The bool is
True if evaluating all object references is successful, False otherwise.
"""
unfinished = remote_values.copy()
while len(unfinished) > 0:
finished, unfinished = ray.wait(unfinished)
# If a failure occurs the ObjectRef will be marked as finished.
# Calling ray.get will expose the failure as a RayActorError.
for object_ref in finished:
# Everything in finished has either failed or completed
# successfully.
try:
ray.get(object_ref)
except RayActorError as exc:
failed_actor_rank = remote_values.index(object_ref)
logger.info(f"Worker {failed_actor_rank} has failed.")
return False, exc
except Exception as exc:
# Other (e.g. training) errors should be directly raised
failed_worker_rank = remote_values.index(object_ref)
raise StartTracebackWithWorkerRank(
worker_rank=failed_worker_rank
) from exc
return True, None
def get_address_and_port() -> Tuple[str, int]:
"""Returns the IP address and a free port on this node."""
addr = ray.util.get_node_ip_address()
port = find_free_port(socket.AF_INET6 if is_ipv6(addr) else socket.AF_INET)
return addr, port
def update_env_vars(env_vars: Dict[str, Any]):
"""Updates the environment variables on this worker process.
Args:
env_vars: Environment variables to set.
"""
sanitized = {k: str(v) for k, v in env_vars.items()}
os.environ.update(sanitized)
def count_required_parameters(fn: Callable) -> int:
"""Counts the number of required parameters of a function.
NOTE: *args counts as 1 required parameter.
Args:
fn: The function whose required parameters should be counted.
Returns:
The number of required parameters of ``fn``.
Examples:
>>> def fn(a, b, /, c, *args, d=1, e=2, **kwargs):
... pass
>>> count_required_parameters(fn)
4
>>> fn = lambda: 1
>>> count_required_parameters(fn)
0
>>> def fn(config, a, b=1, c=2):
... pass
>>> from functools import partial
>>> count_required_parameters(partial(fn, a=0))
1
"""
params = inspect.signature(fn).parameters.values()
positional_param_kinds = {
inspect.Parameter.POSITIONAL_ONLY,
inspect.Parameter.POSITIONAL_OR_KEYWORD,
inspect.Parameter.VAR_POSITIONAL,
}
return len(
[
p
for p in params
if p.default == inspect.Parameter.empty and p.kind in positional_param_kinds
]
)
def construct_train_func(
train_func: Union[Callable[[], T], Callable[[Dict[str, Any]], T]],
config: Optional[Dict[str, Any]],
train_func_context: ContextManager,
fn_arg_name: Optional[str] = "train_func",
discard_returns: bool = False,
) -> Callable[[], T]:
"""Validates and constructs the training function to execute.
Args:
train_func: The training function to execute.
This can either take in no arguments or a ``config`` dict.
config: Configurations to pass into ``train_func``. If None then an empty
Dict will be created.
train_func_context: Context manager for user's `train_func`, which executes
backend-specific logic before and after the training function.
fn_arg_name: The name of training function to use for error messages.
discard_returns: Whether to discard any returns from train_func or not.
Returns:
A valid training function.
Raises:
ValueError: if the input ``train_func`` is invalid.
"""
num_required_params = count_required_parameters(train_func)
if discard_returns:
# Discard any returns from the function so that
# BackendExecutor doesn't try to deserialize them.
# Those returns are inaccesible with AIR anyway.
@functools.wraps(train_func)
def discard_return_wrapper(*args, **kwargs):
try:
train_func(*args, **kwargs)
except Exception as e:
raise StartTraceback from e
wrapped_train_func = discard_return_wrapper
else:
wrapped_train_func = train_func
if num_required_params > 1:
err_msg = (
f"{fn_arg_name} should take in 0 or 1 required arguments, but it accepts "
f"{num_required_params} required arguments instead."
)
raise ValueError(err_msg)
elif num_required_params == 1:
config = {} if config is None else config
@functools.wraps(wrapped_train_func)
def train_fn():
try:
with train_func_context():
return wrapped_train_func(config)
except Exception as e:
raise StartTraceback from e
else: # num_params == 0
@functools.wraps(wrapped_train_func)
def train_fn():
try:
with train_func_context():
return wrapped_train_func()
except Exception as e:
raise StartTraceback from e
return train_fn
class Singleton(abc.ABCMeta):
"""Singleton Abstract Base Class
https://stackoverflow.com/questions/33364070/implementing
-singleton-as-metaclass-but-for-abstract-classes
"""
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]
class ActorWrapper:
"""Wraps an actor to provide same API as using the base class directly."""
def __init__(self, actor: ActorHandle):
self.actor = actor
def __getattr__(self, item):
# The below will fail if trying to access an attribute (not a method) from the
# actor.
actor_method = getattr(self.actor, item)
return lambda *args, **kwargs: ray.get(actor_method.remote(*args, **kwargs))