| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- #!/usr/bin/env python
- # ruff: noqa: E402
- """This script allows you to develop Ray Python code without needing to compile
- Ray.
- See https://docs.ray.io/en/master/development.html#building-ray-python-only"""
- import os
- import sys
- # types.py can conflict with stdlib's types.py in some python versions,
- # see https://github.com/python/cpython/issues/101210.
- # To avoid import errors, we move the current working dir to the end of sys.path.
- this_dir = os.path.dirname(__file__)
- if this_dir in sys.path:
- sys.path.remove(this_dir)
- sys.path.append(this_dir)
- import argparse
- import shutil
- import subprocess
- import click
- import ray
- def do_link(package, force=False, skip_list=None, allow_list=None, local_path=None):
- if skip_list and package in skip_list:
- print(f"Skip creating symbolic link for {package}")
- return
- if allow_list is not None and package not in allow_list:
- print(f"Skip creating symbolic link for {package} (not in allow list)")
- return
- package_home = os.path.abspath(os.path.join(ray.__file__, f"../{package}"))
- # Infer local_path automatically.
- if local_path is None:
- local_path = f"../{package}"
- local_home = os.path.abspath(os.path.join(__file__, local_path))
- # If installed package dir does not exist, continue either way. We'll
- # remove it/create a link from there anyways.
- if not os.path.isdir(package_home) and not os.path.isfile(package_home):
- print(f"{package_home} does not exist. Continuing to link.")
- # Make sure the path we are linking to does exist.
- assert os.path.exists(local_home), local_home
- # Confirm with user.
- if not force and not click.confirm(
- f"This will replace:\n {package_home}\nwith " f"a symlink to:\n {local_home}",
- default=True,
- ):
- return
- # Windows: Create directory junction.
- if os.name == "nt":
- try:
- shutil.rmtree(package_home)
- except FileNotFoundError:
- pass
- except OSError:
- os.remove(package_home)
- # create symlink for directory or file
- if os.path.isdir(local_home):
- subprocess.check_call(
- ["mklink", "/J", package_home, local_home], shell=True
- )
- elif os.path.isfile(local_home):
- subprocess.check_call(
- ["mklink", "/H", package_home, local_home], shell=True
- )
- else:
- print(f"{local_home} is neither directory nor file. Link failed.")
- # Posix: Use `ln -s` to create softlink.
- else:
- sudo = []
- if not os.access(os.path.dirname(package_home), os.W_OK):
- print("You don't have write permission " f"to {package_home}, using sudo:")
- sudo = ["sudo"]
- print(f"Creating symbolic link from \n {local_home} to \n {package_home}")
- # Preserve ray/serve/generated
- serve_temp_dir = "/tmp/ray/_serve/"
- if package == "serve":
- # Copy generated folder to a temp dir
- generated_folder = os.path.join(package_home, "generated")
- if not os.path.exists(serve_temp_dir):
- os.makedirs(serve_temp_dir)
- subprocess.check_call(["mv", generated_folder, serve_temp_dir])
- # Create backup of the old directory if it exists
- if os.path.exists(package_home):
- backup_dir = f"{package_home}.bak"
- print(f"Creating backup of {package_home} to {backup_dir}")
- subprocess.check_call(sudo + ["cp", "-r", package_home, backup_dir])
- subprocess.check_call(sudo + ["rm", "-rf", package_home])
- subprocess.check_call(sudo + ["ln", "-s", local_home, package_home])
- # Move generated folder to local_home
- if package == "serve":
- tmp_generated_folder = os.path.join(serve_temp_dir, "generated")
- package_generated_folder = os.path.join(package_home, "generated")
- if not os.path.exists(package_generated_folder):
- subprocess.check_call(
- ["mv", tmp_generated_folder, package_generated_folder]
- )
- if __name__ == "__main__":
- parser = argparse.ArgumentParser(
- formatter_class=argparse.RawDescriptionHelpFormatter, description="Setup dev."
- )
- parser.add_argument(
- "--yes", "-y", action="store_true", help="Don't ask for confirmation."
- )
- parser.add_argument(
- "--skip",
- "-s",
- nargs="*",
- help="List of folders to skip linking to facilitate workspace dev",
- required=False,
- )
- parser.add_argument(
- "--allow",
- "-a",
- nargs="*",
- help="List of folders to link (only these will be linked)",
- required=False,
- )
- parser.add_argument(
- "--extras",
- "-e",
- nargs="*",
- help="List of extra folders to link to facilitate workspace dev",
- required=False,
- )
- args = parser.parse_args()
- if args.skip and args.allow:
- print("Error: --skip and --allow cannot be used together.")
- sys.exit(1)
- if not args.yes:
- print("NOTE: Use '-y' to override all python files without confirmation.")
- # Dictionary of packages to link, with optional local_path
- packages_to_link = {
- "llm": None,
- "serve/llm": None,
- "data/llm.py": None,
- "rllib": "../../../rllib",
- "air": None,
- "tune": None,
- "train": None,
- "autoscaler": None,
- "cloudpickle": None,
- "data": None,
- "scripts": None,
- "internal": None,
- "tests": None,
- "experimental": None,
- "util": None,
- "workflow": None,
- "serve": None,
- "dag": None,
- "widgets": None,
- "cluster_utils.py": None,
- "_private": None,
- "_common": None,
- "dashboard": None,
- }
- # Link all packages using a for loop
- for package, local_path in packages_to_link.items():
- do_link(
- package,
- force=args.yes,
- skip_list=args.skip,
- allow_list=args.allow,
- local_path=local_path,
- )
- if args.extras is not None:
- for package in args.extras:
- do_link(package, force=args.yes, skip_list=args.skip, allow_list=args.allow)
- print(
- "Created links.\n\nIf you run into issues initializing Ray, please "
- "ensure that your local repo and the installed Ray are in sync "
- "(pip install -U the latest wheels at "
- "https://docs.ray.io/en/master/installation.html, "
- "and ensure you are up-to-date on the master branch on git).\n\n"
- "Note that you may need to delete the package symlinks when pip "
- "installing new Ray versions to prevent pip from overwriting files "
- "in your git repo."
- )
|