Coverage for adrs/installer.py: 0%

57 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-08-29 04:01 +0800

1import os 

2import sys 

3import platform 

4import importlib 

5import ensurepip 

6import subprocess 

7from pathlib import Path 

8 

9 

10def ensure_one(pkg: str, version: str): 

11 if _is_installed(pkg): 

12 return 

13 

14 wheel_path = resolve_wheel(pkg, version) 

15 print(f"Installing {pkg}=={version}") 

16 install_wheel(wheel_path) 

17 print(f"Installed {pkg}=={version}") 

18 

19 

20def _is_installed(pkg: str) -> bool: 

21 try: 

22 importlib.import_module(pkg) 

23 return True 

24 except ImportError: 

25 return False 

26 

27 

28def resolve_wheel(pkg: str, version: str) -> Path: 

29 """ 

30 Attempts to find a matching wheel by iterating over all 

31 compatible sys_tags. This gives reliable fallback behavior. 

32 """ 

33 for wheel_filename in derive_possible_wheels(pkg, version): 

34 wheel_path = download_wheel(pkg, version, wheel_filename) 

35 if wheel_path is not None: 

36 return wheel_path 

37 

38 raise RuntimeError( 

39 f"No compatible wheel found for {pkg}={version}. " 

40 "Check that your platform and python version is supported." 

41 ) 

42 

43 

44def derive_possible_wheels(pkg: str, version: str) -> list[str]: 

45 """ 

46 Derives a packaging tag for the current system. 

47 """ 

48 system = platform.system().lower() 

49 arch = platform.machine().lower() 

50 pyver = f"cp{sys.version_info.major}{sys.version_info.minor}" 

51 

52 wheels = [] 

53 match system: 

54 case "linux": 

55 wheels = [ 

56 f"{pkg}-{version}-{pyver}-{pyver}-manylinux_2_17_{arch}.manylinux2014_{arch}.whl" 

57 ] 

58 case "darwin": 

59 wheels = [ 

60 f"{pkg}-{version}-{pyver}-{pyver}-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl" 

61 ] 

62 case "windows": 

63 wheels = [f"{pkg}-{version}-{pyver}-{pyver}-win_{arch}.whl"] 

64 

65 return wheels 

66 

67 

68def download_wheel(pkg: str, version: str, filename: str) -> Path | None: 

69 """ """ 

70 WHEEL_DIR = Path(__file__).parent / "wheels" 

71 os.makedirs(WHEEL_DIR, exist_ok=True) 

72 

73 wheel_path = WHEEL_DIR / filename 

74 if wheel_path.exists(): 

75 return wheel_path 

76 

77 return None 

78 

79 

80def install_wheel(wheel_path: Path): 

81 """ 

82 Install a wheel from a local file, ensuring pip is available. 

83 """ 

84 try: 

85 # Try pip first 

86 subprocess.run( 

87 [ 

88 sys.executable, 

89 "-m", 

90 "pip", 

91 "install", 

92 "--no-deps", 

93 str(wheel_path), 

94 ], 

95 check=True, 

96 capture_output=True, 

97 text=True, 

98 ) 

99 except subprocess.CalledProcessError as e: 

100 if "No module named pip" in e.stderr: 

101 print("[adrs] pip not found, bootstrapping pip...") 

102 ensurepip.bootstrap() 

103 subprocess.check_call( 

104 [ 

105 sys.executable, 

106 "-m", 

107 "pip", 

108 "install", 

109 "--no-deps", 

110 str(wheel_path), 

111 ] 

112 ) 

113 else: 

114 raise RuntimeError(f"Failed to install {wheel_path}: {e}") from e 

115 except Exception as e: 

116 raise RuntimeError(f"Failed to install {wheel_path}: {e}") from e