FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
pre-commit/pre_commit/languages/python.py at v5-install · pre-commit/pre-commit · GitHub
pre-commit
pre-commit
Repository navigation
Code
Issues
17
(17)
Pull requests
8
(8)
Actions
Security and quality
Insights
Expand file tree
Breadcrumbs
pre-commit
/
pre_commit
/
languages
/
python.py
Copy path
More file actions
More file actions
Latest commit
History
History
History
228 lines (182 loc) · 7.15 KB
Breadcrumbs
pre-commit
/
pre_commit
/
languages
/
python.py
Copy path
File metadata and controls
228 lines (182 loc) · 7.15 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
from
__future__
import
annotations
import
contextlib
import
functools
import
os
import
sys
from
collections
.
abc
import
Generator
from
collections
.
abc
import
Sequence
import
pre_commit
.
constants
as
C
from
pre_commit
import
lang_base
from
pre_commit
.
envcontext
import
envcontext
from
pre_commit
.
envcontext
import
PatchesT
from
pre_commit
.
envcontext
import
UNSET
from
pre_commit
.
envcontext
import
Var
from
pre_commit
.
parse_shebang
import
find_executable
from
pre_commit
.
prefix
import
Prefix
from
pre_commit
.
util
import
CalledProcessError
from
pre_commit
.
util
import
cmd_output
from
pre_commit
.
util
import
cmd_output_b
from
pre_commit
.
util
import
win_exe
ENVIRONMENT_DIR
=
'py_env'
run_hook
=
lang_base
.
basic_run_hook
@
functools
.
cache
def
_version_info
(
exe
:
str
)
->
str
:
prog
=
'import sys;print(".".join(str(p) for p in sys.version_info))'
try
:
return
cmd_output
(
exe
,
'-S'
,
'-c'
,
prog
)[
1
].
strip
()
except
CalledProcessError
:
return
f'<<error retrieving version from
{
exe
}
>>'
def
_read_pyvenv_cfg
(
filename
:
str
)
->
dict
[
str
,
str
]:
ret
=
{}
with
open
(
filename
,
encoding
=
'UTF-8'
)
as
f
:
for
line
in
f
:
try
:
k
,
v
=
line
.
split
(
'='
)
except
ValueError
:
# blank line / comment / etc.
continue
else
:
ret
[
k
.
strip
()]
=
v
.
strip
()
return
ret
def
bin_dir
(
venv
:
str
)
->
str
:
"""On windows there's a different directory for the virtualenv"""
bin_part
=
'Scripts'
if
sys
.
platform
==
'win32'
else
'bin'
return
os
.
path
.
join
(
venv
,
bin_part
)
def
get_env_patch
(
venv
:
str
)
->
PatchesT
:
return
(
(
'PIP_DISABLE_PIP_VERSION_CHECK'
,
'1'
),
(
'PYTHONHOME'
,
UNSET
),
(
'VIRTUAL_ENV'
,
venv
),
(
'PATH'
, (
bin_dir
(
venv
),
os
.
pathsep
,
Var
(
'PATH'
))),
)
def
_find_by_py_launcher
(
version
:
str
,
)
->
str
|
None
:
# pragma: no cover (windows only)
if
version
.
startswith
(
'python'
):
num
=
version
.
removeprefix
(
'python'
)
cmd
=
(
'py'
,
f'-
{
num
}
'
,
'-c'
,
'import sys; print(sys.executable)'
)
env
=
dict
(
os
.
environ
,
PYTHONIOENCODING
=
'UTF-8'
)
try
:
return
cmd_output
(
*
cmd
,
env
=
env
)[
1
].
strip
()
except
CalledProcessError
:
pass
return
None
def
_impl_exe_name
()
->
str
:
if
sys
.
implementation
.
name
==
'cpython'
:
# pragma: cpython cover
return
'python'
else
:
# pragma: cpython no cover
return
sys
.
implementation
.
name
# pypy mostly
def
_find_by_sys_executable
()
->
str
|
None
:
def
_norm
(
path
:
str
)
->
str
|
None
:
_
,
exe
=
os
.
path
.
split
(
path
.
lower
())
exe
,
_
,
_
=
exe
.
partition
(
'.exe'
)
if
exe
not
in
{
'python'
,
'pythonw'
}
and
find_executable
(
exe
):
return
exe
return
None
# On linux, I see these common sys.executables:
#
# system `python`: /usr/bin/python -> python2.7
# system `python2`: /usr/bin/python2 -> python2.7
# virtualenv v: v/bin/python (will not return from this loop)
# virtualenv v -ppython2: v/bin/python -> python2
# virtualenv v -ppython2.7: v/bin/python -> python2.7
# virtualenv v -ppypy: v/bin/python -> v/bin/pypy
for
path
in
(
sys
.
executable
,
os
.
path
.
realpath
(
sys
.
executable
)):
exe
=
_norm
(
path
)
if
exe
:
return
exe
return
None
@
functools
.
lru_cache
(
maxsize
=
1
)
def
get_default_version
()
->
str
:
# pragma: no cover (platform dependent)
v_major
=
f'
{
sys
.
version_info
[
0
]
}
'
v_minor
=
f'
{
sys
.
version_info
[
0
]
}
.
{
sys
.
version_info
[
1
]
}
'
# attempt the likely implementation exe
for
potential
in
(
v_minor
,
v_major
):
exe
=
f'
{
_impl_exe_name
()
}
{
potential
}
'
if
find_executable
(
exe
):
return
exe
# next try `sys.executable` (or the realpath)
maybe_exe
=
_find_by_sys_executable
()
if
maybe_exe
:
return
maybe_exe
# maybe on windows we can find it via py launcher?
if
sys
.
platform
==
'win32'
:
# pragma: win32 cover
exe
=
f'python
{
v_minor
}
'
if
_find_by_py_launcher
(
exe
):
return
exe
# We tried!
return
C
.
DEFAULT
def
_sys_executable_matches
(
version
:
str
)
->
bool
:
if
version
==
'python'
:
return
True
elif
not
version
.
startswith
(
'python'
):
return
False
try
:
info
=
tuple
(
int
(
p
)
for
p
in
version
.
removeprefix
(
'python'
).
split
(
'.'
))
except
ValueError
:
return
False
return
sys
.
version_info
[:
len
(
info
)]
==
info
def
norm_version
(
version
:
str
)
->
str
|
None
:
if
version
==
C
.
DEFAULT
:
# use virtualenv's default
return
None
elif
_sys_executable_matches
(
version
):
# virtualenv defaults to our exe
return
None
if
sys
.
platform
==
'win32'
:
# pragma: no cover (windows)
version_exec
=
_find_by_py_launcher
(
version
)
if
version_exec
:
return
version_exec
# Try looking up by name
version_exec
=
find_executable
(
version
)
if
version_exec
and
version_exec
!=
version
:
return
version_exec
# Otherwise assume it is a path
return
os
.
path
.
expanduser
(
version
)
@
contextlib
.
contextmanager
def
in_env
(
prefix
:
Prefix
,
version
:
str
)
->
Generator
[
None
]:
envdir
=
lang_base
.
environment_dir
(
prefix
,
ENVIRONMENT_DIR
,
version
)
with
envcontext
(
get_env_patch
(
envdir
)):
yield
def
health_check
(
prefix
:
Prefix
,
version
:
str
)
->
str
|
None
:
envdir
=
lang_base
.
environment_dir
(
prefix
,
ENVIRONMENT_DIR
,
version
)
pyvenv_cfg
=
os
.
path
.
join
(
envdir
,
'pyvenv.cfg'
)
# created with "old" virtualenv
if
not
os
.
path
.
exists
(
pyvenv_cfg
):
return
'pyvenv.cfg does not exist (old virtualenv?)'
exe_name
=
win_exe
(
'python'
)
py_exe
=
prefix
.
path
(
bin_dir
(
envdir
),
exe_name
)
cfg
=
_read_pyvenv_cfg
(
pyvenv_cfg
)
if
'version_info'
not
in
cfg
:
return
"created virtualenv's pyvenv.cfg is missing `version_info`"
# always use uncached lookup here in case we replaced an unhealthy env
virtualenv_version
=
_version_info
.
__wrapped__
(
py_exe
)
if
virtualenv_version
!=
cfg
[
'version_info'
]:
return
(
f'virtualenv python version did not match created version:
\n
'
f'- actual version:
{
virtualenv_version
}
\n
'
f'- expected version:
{
cfg
[
"version_info"
]
}
\n
'
)
# made with an older version of virtualenv? skip `base-executable` check
if
'base-executable'
not
in
cfg
:
return
None
base_exe_version
=
_version_info
(
cfg
[
'base-executable'
])
if
base_exe_version
!=
cfg
[
'version_info'
]:
return
(
f'base executable python version does not match created version:
\n
'
f'- base-executable version:
{
base_exe_version
}
\n
'
f'- expected version:
{
cfg
[
"version_info"
]
}
\n
'
)
else
:
return
None
def
install_environment
(
prefix
:
Prefix
,
version
:
str
,
additional_dependencies
:
Sequence
[
str
],
)
->
None
:
envdir
=
lang_base
.
environment_dir
(
prefix
,
ENVIRONMENT_DIR
,
version
)
venv_cmd
=
[
sys
.
executable
,
'-mvirtualenv'
,
envdir
]
python
=
norm_version
(
version
)
if
python
is
not
None
:
venv_cmd
.
extend
((
'-p'
,
python
))
install_cmd
=
(
'python'
,
'-mpip'
,
'install'
,
'.'
,
*
additional_dependencies
)
cmd_output_b
(
*
venv_cmd
,
cwd
=
'/'
)
with
in_env
(
prefix
,
version
):
lang_base
.
setup_cmd
(
prefix
,
install_cmd
)
Back
|
FazBrowse Home
|
New Git URL