binproviders.py 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. __package__ = 'plugins_pkg.pip'
  2. import os
  3. import sys
  4. import site
  5. from pathlib import Path
  6. from typing import Optional
  7. from pydantic_pkgr import PipProvider, BinName, BinProviderName
  8. from archivebox.config import CONSTANTS
  9. from abx.archivebox.base_binary import BaseBinProvider
  10. ###################### Config ##########################
  11. class SystemPipBinProvider(PipProvider, BaseBinProvider):
  12. name: BinProviderName = "sys_pip"
  13. INSTALLER_BIN: BinName = "pip"
  14. pip_venv: Optional[Path] = None # global pip scope
  15. def on_install(self, bin_name: str, **kwargs):
  16. # never modify system pip packages
  17. return 'refusing to install packages globally with system pip, use a venv instead'
  18. class SystemPipxBinProvider(PipProvider, BaseBinProvider):
  19. name: BinProviderName = "pipx"
  20. INSTALLER_BIN: BinName = "pipx"
  21. pip_venv: Optional[Path] = None # global pipx scope
  22. IS_INSIDE_VENV = sys.prefix != sys.base_prefix
  23. class VenvPipBinProvider(PipProvider, BaseBinProvider):
  24. name: BinProviderName = "venv_pip"
  25. INSTALLER_BIN: BinName = "pip"
  26. pip_venv: Optional[Path] = Path(sys.prefix if IS_INSIDE_VENV else os.environ.get("VIRTUAL_ENV", '/tmp/NotInsideAVenv/lib'))
  27. def setup(self):
  28. """never attempt to create a venv here, this is just used to detect if we are inside an existing one"""
  29. return None
  30. class LibPipBinProvider(PipProvider, BaseBinProvider):
  31. name: BinProviderName = "lib_pip"
  32. INSTALLER_BIN: BinName = "pip"
  33. pip_venv: Optional[Path] = CONSTANTS.DEFAULT_LIB_DIR / 'pip' / 'venv'
  34. def setup(self) -> None:
  35. # update paths from config if they arent the default
  36. from archivebox.config.common import STORAGE_CONFIG
  37. if STORAGE_CONFIG.LIB_DIR != CONSTANTS.DEFAULT_LIB_DIR:
  38. self.pip_venv = STORAGE_CONFIG.LIB_DIR / 'pip' / 'venv'
  39. super().setup()
  40. SYS_PIP_BINPROVIDER = SystemPipBinProvider()
  41. PIPX_PIP_BINPROVIDER = SystemPipxBinProvider()
  42. VENV_PIP_BINPROVIDER = VenvPipBinProvider()
  43. LIB_PIP_BINPROVIDER = LibPipBinProvider()
  44. pip = LIB_PIP_BINPROVIDER
  45. # ensure python libraries are importable from these locations (if archivebox wasnt executed from one of these then they wont already be in sys.path)
  46. assert VENV_PIP_BINPROVIDER.pip_venv is not None
  47. assert LIB_PIP_BINPROVIDER.pip_venv is not None
  48. major, minor, patch = sys.version_info[:3]
  49. site_packages_dir = f'lib/python{major}.{minor}/site-packages'
  50. LIB_SITE_PACKAGES = (LIB_PIP_BINPROVIDER.pip_venv / site_packages_dir,)
  51. VENV_SITE_PACKAGES = (VENV_PIP_BINPROVIDER.pip_venv / site_packages_dir,)
  52. USER_SITE_PACKAGES = site.getusersitepackages()
  53. SYS_SITE_PACKAGES = site.getsitepackages()
  54. ALL_SITE_PACKAGES = (
  55. *LIB_SITE_PACKAGES,
  56. *VENV_SITE_PACKAGES,
  57. *USER_SITE_PACKAGES,
  58. *SYS_SITE_PACKAGES,
  59. )
  60. for site_packages_dir in ALL_SITE_PACKAGES:
  61. if site_packages_dir not in sys.path:
  62. sys.path.append(str(site_packages_dir))