binproviders.py 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  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.LIB_PIP_DIR / 'venv'
  34. SYS_PIP_BINPROVIDER = SystemPipBinProvider()
  35. PIPX_PIP_BINPROVIDER = SystemPipxBinProvider()
  36. VENV_PIP_BINPROVIDER = VenvPipBinProvider()
  37. LIB_PIP_BINPROVIDER = LibPipBinProvider()
  38. pip = LIB_PIP_BINPROVIDER
  39. # ensure python libraries are importable from these locations (if archivebox wasnt executed from one of these then they wont already be in sys.path)
  40. assert VENV_PIP_BINPROVIDER.pip_venv is not None
  41. assert LIB_PIP_BINPROVIDER.pip_venv is not None
  42. major, minor, patch = sys.version_info[:3]
  43. site_packages_dir = f'lib/python{major}.{minor}/site-packages'
  44. LIB_SITE_PACKAGES = (LIB_PIP_BINPROVIDER.pip_venv / site_packages_dir,)
  45. VENV_SITE_PACKAGES = (VENV_PIP_BINPROVIDER.pip_venv / site_packages_dir,)
  46. USER_SITE_PACKAGES = site.getusersitepackages()
  47. SYS_SITE_PACKAGES = site.getsitepackages()
  48. ALL_SITE_PACKAGES = (
  49. *LIB_SITE_PACKAGES,
  50. *VENV_SITE_PACKAGES,
  51. *USER_SITE_PACKAGES,
  52. *SYS_SITE_PACKAGES,
  53. )
  54. for site_packages_dir in ALL_SITE_PACKAGES:
  55. if site_packages_dir not in sys.path:
  56. sys.path.append(str(site_packages_dir))