| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 |
- #! /usr/bin/env python3
- """
- Create symlinks to homebrewed python-installations that can be used alongside
- pyenv.
- After running this script, you can use e.g. homebrew's python@3.12 via
- ```
- pyenv shell 3.12
- ```
- - You can still install pyenv versions
- - you can still create virtualenvironments based on the homebrew versions
- """
- import subprocess
- from pathlib import Path
- from dataclasses import dataclass
- import logging
- logging.basicConfig(
- level=logging.INFO,
- format="{%(pathname)s:%(lineno)d} %(levelname)s - %(message)s",
- )
- @dataclass
- class Binary:
- executable: str
- links: list[str]
- BINARIES_TO_LINK = [
- Binary(executable="python{version}", links=["python3", "python"]),
- Binary(executable="pip{version}", links=["pip3", "pip"]),
- Binary(executable="idle{version}", links=["idle3", "idle"]),
- Binary(executable="pydoc{version}", links=["pydoc3", "pydoc"]),
- Binary(executable="wheel{version}", links=["wheel3", "wheel"]),
- Binary(
- executable="python{version}-config",
- links=["python3-config", "python-config"],
- ),
- ]
- DIRS_TO_LINK = ["include", "lib", "share"]
- installed_brew_packages = subprocess.getoutput("brew list").split()
- brew_prefix = Path(subprocess.getoutput("brew --prefix")) / "opt"
- installed_versions = [
- p for p in installed_brew_packages if "python@" in p or "python-tk@" in p
- ]
- logging.info(f"Will link following installed versions: {installed_versions}")
- homedir = Path.home()
- pyenv_dir = Path(subprocess.getoutput("pyenv root")) / "versions"
- logging.info(f"Will add all necessary links to {pyenv_dir}")
- for pyversion in installed_versions:
- logging.info(f"Check dir for {pyversion}")
- _, version = pyversion.split("@")
- if "-tk" in pyversion:
- link_dir = pyenv_dir / f"{version}-tk"
- else:
- link_dir = pyenv_dir / version
- link_dir.mkdir(exist_ok=True)
- for binary in BINARIES_TO_LINK:
- (link_dir / "bin").mkdir(exist_ok=True)
- target = (
- brew_prefix / pyversion / "bin" / binary.executable.format(version=version)
- )
- source = link_dir / "bin" / binary.executable.format(version=version)
- if source.is_file():
- if source.resolve() != target.resolve():
- logging.warning(
- f"{source} is different from {target}, skipping {pyversion}"
- )
- continue
- source.symlink_to(target)
- for link in binary.links:
- source = link_dir / "bin" / link
- target = brew_prefix / pyversion / "libexec/bin" / link
- if source.is_symlink():
- logging.warning(f"Link {target} -> {source} already exists. Skipping.")
- continue
- source.symlink_to(target)
- for dir_ in DIRS_TO_LINK:
- target = brew_prefix / pyversion / dir_
- source = link_dir / dir_
- if source.is_dir():
- if source.resolve() != target.resolve():
- logging.warning(
- f"{source} is a proper directory, skipping. "
- f"Linking for {pyversion} might be broken now."
- )
- continue
- if not source.is_symlink():
- source.symlink_to(target, target_is_directory=True)
- logging.info("Rehashing pyenv")
- subprocess.call(["pyenv", "rehash"])
|