1
1
import json
2
2
import shlex
3
3
import subprocess
4
+ import sys
4
5
from functools import lru_cache
6
+ from importlib .metadata import version
5
7
from importlib .resources import path as resource_path
6
8
from typing import Optional , Tuple , TypedDict , cast
7
9
10
+ import typer
8
11
from packaging .version import Version
9
12
10
13
from .utils import log_error , log_warning
@@ -34,19 +37,43 @@ def _get_env_info(python: str) -> EnvInfo:
34
37
return cast (EnvInfo , json .loads (env_info_json ))
35
38
36
39
40
+ @lru_cache
37
41
def get_pip_version (python : str ) -> Version :
38
42
pip_version = _get_env_info (python ).get ("pip_version" )
39
- # assert because we have checked the pip availability before
40
- assert pip_version , "pip is not available"
41
- return Version (pip_version )
43
+ if pip_version :
44
+ return Version ( pip_version )
45
+ return Version (version ( "pip" ) )
42
46
43
47
48
+ @lru_cache
49
+ def get_pip_command (python : str ) -> Tuple [str , ...]:
50
+ env_pip_version = _get_env_info (python ).get ("pip_version" )
51
+ if env_pip_version :
52
+ # pip is installed in the target environment, let's use it
53
+ return (python , "-m" , "pip" )
54
+ if not local_pip_compatible (python ):
55
+ log_error (
56
+ f"pip is not available to { python } , and the pip version. "
57
+ f"installed the pip-deepfreeze environment is not compatible with it. "
58
+ f"Please install pip in the target environment."
59
+ )
60
+ raise typer .Exit (1 )
61
+ return (sys .executable , "-m" , "pip" , "--python" , python )
62
+
63
+
64
+ @lru_cache
44
65
def get_python_version_info (python : str ) -> Tuple [int , ...]:
45
66
python_version = _get_env_info (python ).get ("python_version" )
46
67
assert python_version
47
68
return tuple (map (int , python_version .split ("." , 1 )))
48
69
49
70
71
+ @lru_cache
72
+ def local_pip_compatible (python : str ) -> bool :
73
+ cmd = [sys .executable , "-m" , "pip" , "--python" , python , "--version" ]
74
+ return subprocess .call (cmd ) == 0
75
+
76
+
50
77
def check_env (python : str ) -> bool :
51
78
_get_env_info .cache_clear ()
52
79
env_info = _get_env_info (python )
@@ -65,9 +92,19 @@ def check_env(python: str) -> bool:
65
92
return False
66
93
pip_version = env_info .get ("pip_version" )
67
94
if not env_info .get ("has_pkg_resources" ) and (
68
- # pip_version is None if pkg_resources is not installed for python<3.8
69
- not pip_version
70
- or Version (pip_version ) < Version ("22.2" )
95
+ (
96
+ # target pip does not have pip inspect: we need pkg_resources to
97
+ # inspect with env-info-json.py
98
+ pip_version
99
+ and Version (pip_version ) < Version ("22.2" )
100
+ )
101
+ or (
102
+ # pip not installed in target python env and local pip is not compatible
103
+ # with target python, so we'll need pkg_resources to inspect with
104
+ # env-info-json.py
105
+ not pip_version
106
+ and not local_pip_compatible (python )
107
+ )
71
108
):
72
109
setuptools_install_cmd = shlex .join (
73
110
[python , "-m" , "pip" , "install" , "setuptools" ]
@@ -84,17 +121,21 @@ def check_env(python: str) -> bool:
84
121
return False
85
122
# Testing for pip must be done after testing for pkg_resources, because
86
123
# pkg_resources is needed to obtain the pip version for python < 3.8.
87
- if not pip_version :
124
+ if not pip_version and not local_pip_compatible ( python ) :
88
125
log_error (f"pip is not available to { python } . Please install it." )
89
126
return False
90
- if Version (pip_version ) < Version ("20.1" ):
127
+ if pip_version and Version (pip_version ) < Version ("20.1" ):
91
128
pip_install_cmd = shlex .join ([python , "-m" , "pip" , "install" , "pip>=20.1" ])
92
129
log_warning (
93
130
f"pip-deepfreeze works best with pip>=20.1, "
94
131
f"in particular if you use direct URL references. "
95
132
f"You can upgrade pip it with '{ pip_install_cmd } '."
96
133
)
97
- if not env_info .get ("wheel_version" ) and Version (pip_version ) < Version ("23.1" ):
134
+ if (
135
+ not env_info .get ("wheel_version" )
136
+ and pip_version
137
+ and Version (pip_version ) < Version ("23.1" )
138
+ ):
98
139
wheel_install_cmd = shlex .join ([python , "-m" , "pip" , "install" , "wheel" ])
99
140
log_warning (
100
141
f"wheel is not available to { python } . "
0 commit comments