We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
On a Windows system, in either win7 or win2012R2, performing a pre-commit reports an error
 All:
It looks like the pre-commit is using virtualenv

I used pre-commit on a Python project.  

Is there any way to solve this problem?


The following log is excerpted from pre-committee.log  
**Log**
```
An unexpected error has occurred: CalledProcessError: command: ('C:\\Users\\Administrator\\.cache\\pre-commit\\repop9_0qne0\\py_env-default\\Scripts\\pip.EXE', 'install', '.')
return code: 1
expected return code: 0
stdout:
    Looking in indexes: http://pypi.douban.com/simple
    Processing c:\users\administrator\.cache\pre-commit\repop9_0qne0
    Collecting six
      Downloading http://pypi.doubanio.com/packages/65/eb/1f97cb97bfc2390a276969c6fae16075da282f5058082d4cb10c6c5c1dba/six-1.14.0-py2.py3-none-any.whl (10 kB)
    Collecting pip-tools==3.6.1
      Downloading http://pypi.doubanio.com/packages/06/96/89872db07ae70770fba97205b0737c17ef013d0d1c790899c16bb8bac419/pip_tools-3.6.1-py2.py3-none-any.whl (35 kB)
    Collecting pip==19.1
      Downloading http://pypi.doubanio.com/packages/f9/fb/863012b13912709c13cf5cfdbfb304fa6c727659d6290438e1a88df9d848/pip-19.1-py2.py3-none-any.whl (1.4 MB)
    Collecting click>=6
      Downloading http://pypi.doubanio.com/packages/dd/c0/4d8f43a9b16e289f36478422031b8a63b54b6ac3b1ba605d602f10dd54d6/click-7.1.1-py2.py3-none-any.whl (82 kB)
    Building wheels for collected packages: pip-tools-compile
      Building wheel for pip-tools-compile (setup.py): started
      Building wheel for pip-tools-compile (setup.py): finished with status 'done'
      Created wheel for pip-tools-compile: filename=pip_tools_compile-1.0-py3-none-any.whl size=17905 sha256=30321f831b5ac147be919304dee138139d055f2bdb52a5511317bc718b29b76d
      Stored in directory: C:\Users\ADMINI~1\AppData\Local\Temp\pip-ephem-wheel-cache-b67alovp\wheels\f1\34\3c\bed42474e4aeb415aa0bfd1e28124cde97604fa12005eed65b
    Successfully built pip-tools-compile
    Installing collected packages: six, click, pip-tools, pip, pip-tools-compile
      Attempting uninstall: pip
        Found existing installation: pip 20.0.2
        Uninstalling pip-20.0.2:
          Successfully uninstalled pip-20.0.2
    
stderr:
    ERROR: Could not install packages due to an EnvironmentError: [WinError 5] 拒绝访问。: 'C:\\Users\\ADMINI~1\\AppData\\Local\\Temp\\pip-uninstall-8wsztgaa\\pip.exe'
    Consider using the `--user` option or check the permissions.
    
    
```  
  
```
Traceback (most recent call last):
  File "c:\program files\python37\lib\site-packages\pre_commit\error_handler.py", line 56, in error_handler
    yield
  File "c:\program files\python37\lib\site-packages\pre_commit\main.py", line 372, in main
    args=args.rest[1:],
  File "c:\program files\python37\lib\site-packages\pre_commit\commands\hook_impl.py", line 187, in hook_impl
    return retv | run(config, store, ns)
  File "c:\program files\python37\lib\site-packages\pre_commit\commands\run.py", line 355, in run
    install_hook_envs(hooks, store)
  File "c:\program files\python37\lib\site-packages\pre_commit\repository.py", line 200, in install_hook_envs
    _hook_install(hook)
  File "c:\program files\python37\lib\site-packages\pre_commit\repository.py", line 83, in _hook_install
    hook.prefix, hook.language_version, hook.additional_dependencies,
  File "c:\program files\python37\lib\site-packages\pre_commit\languages\python.py", line 197, in install_environment
    prefix, ('pip', 'install', '.') + additional_dependencies,
  File "c:\program files\python37\lib\site-packages\pre_commit\languages\helpers.py", line 25, in run_setup_cmd
    cmd_output_b(*cmd, cwd=prefix.prefix_dir)
  File "c:\program files\python37\lib\site-packages\pre_commit\util.py", line 156, in cmd_output_b
    raise CalledProcessError(returncode, cmd, retcode, stdout_b, stderr_b)
pre_commit.util.CalledProcessError: <unprintable CalledProcessError object>

```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pre_commit/languages/python.py`
Content:
```
1 import contextlib
2 import functools
3 import os
4 import sys
5 from typing import Callable
6 from typing import ContextManager
7 from typing import Generator
8 from typing import Optional
9 from typing import Sequence
10 from typing import Tuple
11 
12 import pre_commit.constants as C
13 from pre_commit.envcontext import envcontext
14 from pre_commit.envcontext import PatchesT
15 from pre_commit.envcontext import UNSET
16 from pre_commit.envcontext import Var
17 from pre_commit.hook import Hook
18 from pre_commit.languages import helpers
19 from pre_commit.parse_shebang import find_executable
20 from pre_commit.prefix import Prefix
21 from pre_commit.util import CalledProcessError
22 from pre_commit.util import clean_path_on_failure
23 from pre_commit.util import cmd_output
24 from pre_commit.util import cmd_output_b
25 
26 ENVIRONMENT_DIR = 'py_env'
27 
28 
29 def bin_dir(venv: str) -> str:
30     """On windows there's a different directory for the virtualenv"""
31     bin_part = 'Scripts' if os.name == 'nt' else 'bin'
32     return os.path.join(venv, bin_part)
33 
34 
35 def get_env_patch(venv: str) -> PatchesT:
36     return (
37         ('PYTHONHOME', UNSET),
38         ('VIRTUAL_ENV', venv),
39         ('PATH', (bin_dir(venv), os.pathsep, Var('PATH'))),
40     )
41 
42 
43 def _find_by_py_launcher(
44         version: str,
45 ) -> Optional[str]:  # pragma: no cover (windows only)
46     if version.startswith('python'):
47         num = version[len('python'):]
48         try:
49             cmd = ('py', f'-{num}', '-c', 'import sys; print(sys.executable)')
50             return cmd_output(*cmd)[1].strip()
51         except CalledProcessError:
52             pass
53     return None
54 
55 
56 def _find_by_sys_executable() -> Optional[str]:
57     def _norm(path: str) -> Optional[str]:
58         _, exe = os.path.split(path.lower())
59         exe, _, _ = exe.partition('.exe')
60         if exe not in {'python', 'pythonw'} and find_executable(exe):
61             return exe
62         return None
63 
64     # On linux, I see these common sys.executables:
65     #
66     # system `python`: /usr/bin/python -> python2.7
67     # system `python2`: /usr/bin/python2 -> python2.7
68     # virtualenv v: v/bin/python (will not return from this loop)
69     # virtualenv v -ppython2: v/bin/python -> python2
70     # virtualenv v -ppython2.7: v/bin/python -> python2.7
71     # virtualenv v -ppypy: v/bin/python -> v/bin/pypy
72     for path in (sys.executable, os.path.realpath(sys.executable)):
73         exe = _norm(path)
74         if exe:
75             return exe
76     return None
77 
78 
79 @functools.lru_cache(maxsize=1)
80 def get_default_version() -> str:  # pragma: no cover (platform dependent)
81     # First attempt from `sys.executable` (or the realpath)
82     exe = _find_by_sys_executable()
83     if exe:
84         return exe
85 
86     # Next try the `pythonX.X` executable
87     exe = f'python{sys.version_info[0]}.{sys.version_info[1]}'
88     if find_executable(exe):
89         return exe
90 
91     if _find_by_py_launcher(exe):
92         return exe
93 
94     # Give a best-effort try for windows
95     default_folder_name = exe.replace('.', '')
96     if os.path.exists(fr'C:\{default_folder_name}\python.exe'):
97         return exe
98 
99     # We tried!
100     return C.DEFAULT
101 
102 
103 def _sys_executable_matches(version: str) -> bool:
104     if version == 'python':
105         return True
106     elif not version.startswith('python'):
107         return False
108 
109     try:
110         info = tuple(int(p) for p in version[len('python'):].split('.'))
111     except ValueError:
112         return False
113 
114     return sys.version_info[:len(info)] == info
115 
116 
117 def norm_version(version: str) -> str:
118     # first see if our current executable is appropriate
119     if _sys_executable_matches(version):
120         return sys.executable
121 
122     if os.name == 'nt':  # pragma: no cover (windows)
123         version_exec = _find_by_py_launcher(version)
124         if version_exec:
125             return version_exec
126 
127         # Try looking up by name
128         version_exec = find_executable(version)
129         if version_exec and version_exec != version:
130             return version_exec
131 
132         # If it is in the form pythonx.x search in the default
133         # place on windows
134         if version.startswith('python'):
135             default_folder_name = version.replace('.', '')
136             return fr'C:\{default_folder_name}\python.exe'
137 
138     # Otherwise assume it is a path
139     return os.path.expanduser(version)
140 
141 
142 def py_interface(
143         _dir: str,
144         _make_venv: Callable[[str, str], None],
145 ) -> Tuple[
146     Callable[[Prefix, str], ContextManager[None]],
147     Callable[[Prefix, str], bool],
148     Callable[[Hook, Sequence[str], bool], Tuple[int, bytes]],
149     Callable[[Prefix, str, Sequence[str]], None],
150 ]:
151     @contextlib.contextmanager
152     def in_env(
153             prefix: Prefix,
154             language_version: str,
155     ) -> Generator[None, None, None]:
156         envdir = prefix.path(helpers.environment_dir(_dir, language_version))
157         with envcontext(get_env_patch(envdir)):
158             yield
159 
160     def healthy(prefix: Prefix, language_version: str) -> bool:
161         envdir = helpers.environment_dir(_dir, language_version)
162         exe_name = 'python.exe' if sys.platform == 'win32' else 'python'
163         py_exe = prefix.path(bin_dir(envdir), exe_name)
164         with in_env(prefix, language_version):
165             retcode, _, _ = cmd_output_b(
166                 py_exe, '-c', 'import ctypes, datetime, io, os, ssl, weakref',
167                 cwd='/',
168                 retcode=None,
169             )
170         return retcode == 0
171 
172     def run_hook(
173             hook: Hook,
174             file_args: Sequence[str],
175             color: bool,
176     ) -> Tuple[int, bytes]:
177         with in_env(hook.prefix, hook.language_version):
178             return helpers.run_xargs(hook, hook.cmd, file_args, color=color)
179 
180     def install_environment(
181             prefix: Prefix,
182             version: str,
183             additional_dependencies: Sequence[str],
184     ) -> None:
185         additional_dependencies = tuple(additional_dependencies)
186         directory = helpers.environment_dir(_dir, version)
187 
188         env_dir = prefix.path(directory)
189         with clean_path_on_failure(env_dir):
190             if version != C.DEFAULT:
191                 python = norm_version(version)
192             else:
193                 python = os.path.realpath(sys.executable)
194             _make_venv(env_dir, python)
195             with in_env(prefix, version):
196                 helpers.run_setup_cmd(
197                     prefix, ('pip', 'install', '.') + additional_dependencies,
198                 )
199 
200     return in_env, healthy, run_hook, install_environment
201 
202 
203 def make_venv(envdir: str, python: str) -> None:
204     env = dict(os.environ, VIRTUALENV_NO_DOWNLOAD='1')
205     cmd = (sys.executable, '-mvirtualenv', envdir, '-p', python)
206     cmd_output_b(*cmd, env=env, cwd='/')
207 
208 
209 _interface = py_interface(ENVIRONMENT_DIR, make_venv)
210 in_env, healthy, run_hook, install_environment = _interface
211
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/pre_commit/languages/python.py b/pre_commit/languages/python.py
--- a/pre_commit/languages/python.py
+++ b/pre_commit/languages/python.py
@@ -182,8 +182,8 @@
             version: str,
             additional_dependencies: Sequence[str],
     ) -> None:
-        additional_dependencies = tuple(additional_dependencies)
         directory = helpers.environment_dir(_dir, version)
+        install = ('python', '-mpip', 'install', '.', *additional_dependencies)
 
         env_dir = prefix.path(directory)
         with clean_path_on_failure(env_dir):
@@ -193,9 +193,7 @@
                 python = os.path.realpath(sys.executable)
             _make_venv(env_dir, python)
             with in_env(prefix, version):
-                helpers.run_setup_cmd(
-                    prefix, ('pip', 'install', '.') + additional_dependencies,
-                )
+                helpers.run_setup_cmd(prefix, install)
 
     return in_env, healthy, run_hook, install_environment

{"golden_diff": "diff --git a/pre_commit/languages/python.py b/pre_commit/languages/python.py\n--- a/pre_commit/languages/python.py\n+++ b/pre_commit/languages/python.py\n@@ -182,8 +182,8 @@\n             version: str,\n             additional_dependencies: Sequence[str],\n     ) -> None:\n-        additional_dependencies = tuple(additional_dependencies)\n         directory = helpers.environment_dir(_dir, version)\n+        install = ('python', '-mpip', 'install', '.', *additional_dependencies)\n \n         env_dir = prefix.path(directory)\n         with clean_path_on_failure(env_dir):\n@@ -193,9 +193,7 @@\n                 python = os.path.realpath(sys.executable)\n             _make_venv(env_dir, python)\n             with in_env(prefix, version):\n-                helpers.run_setup_cmd(\n-                    prefix, ('pip', 'install', '.') + additional_dependencies,\n-                )\n+                helpers.run_setup_cmd(prefix, install)\n \n     return in_env, healthy, run_hook, install_environment\n", "issue": "On a Windows system, in either win7 or win2012R2, performing a pre-commit reports an error\n All:\r\nIt looks like the pre-commit is using virtualenv\r\n\r\nI used pre-commit on a Python project.  \r\n\r\nIs there any way to solve this problem?\r\n\r\n\r\nThe following log is excerpted from pre-committee.log  \r\n**Log**\r\n```\r\nAn unexpected error has occurred: CalledProcessError: command: ('C:\\\\Users\\\\Administrator\\\\.cache\\\\pre-commit\\\\repop9_0qne0\\\\py_env-default\\\\Scripts\\\\pip.EXE', 'install', '.')\r\nreturn code: 1\r\nexpected return code: 0\r\nstdout:\r\n    Looking in indexes: http://pypi.douban.com/simple\r\n    Processing c:\\users\\administrator\\.cache\\pre-commit\\repop9_0qne0\r\n    Collecting six\r\n      Downloading http://pypi.doubanio.com/packages/65/eb/1f97cb97bfc2390a276969c6fae16075da282f5058082d4cb10c6c5c1dba/six-1.14.0-py2.py3-none-any.whl (10 kB)\r\n    Collecting pip-tools==3.6.1\r\n      Downloading http://pypi.doubanio.com/packages/06/96/89872db07ae70770fba97205b0737c17ef013d0d1c790899c16bb8bac419/pip_tools-3.6.1-py2.py3-none-any.whl (35 kB)\r\n    Collecting pip==19.1\r\n      Downloading http://pypi.doubanio.com/packages/f9/fb/863012b13912709c13cf5cfdbfb304fa6c727659d6290438e1a88df9d848/pip-19.1-py2.py3-none-any.whl (1.4 MB)\r\n    Collecting click>=6\r\n      Downloading http://pypi.doubanio.com/packages/dd/c0/4d8f43a9b16e289f36478422031b8a63b54b6ac3b1ba605d602f10dd54d6/click-7.1.1-py2.py3-none-any.whl (82 kB)\r\n    Building wheels for collected packages: pip-tools-compile\r\n      Building wheel for pip-tools-compile (setup.py): started\r\n      Building wheel for pip-tools-compile (setup.py): finished with status 'done'\r\n      Created wheel for pip-tools-compile: filename=pip_tools_compile-1.0-py3-none-any.whl size=17905 sha256=30321f831b5ac147be919304dee138139d055f2bdb52a5511317bc718b29b76d\r\n      Stored in directory: C:\\Users\\ADMINI~1\\AppData\\Local\\Temp\\pip-ephem-wheel-cache-b67alovp\\wheels\\f1\\34\\3c\\bed42474e4aeb415aa0bfd1e28124cde97604fa12005eed65b\r\n    Successfully built pip-tools-compile\r\n    Installing collected packages: six, click, pip-tools, pip, pip-tools-compile\r\n      Attempting uninstall: pip\r\n        Found existing installation: pip 20.0.2\r\n        Uninstalling pip-20.0.2:\r\n          Successfully uninstalled pip-20.0.2\r\n    \r\nstderr:\r\n    ERROR: Could not install packages due to an EnvironmentError: [WinError 5] \u62d2\u7edd\u8bbf\u95ee\u3002: 'C:\\\\Users\\\\ADMINI~1\\\\AppData\\\\Local\\\\Temp\\\\pip-uninstall-8wsztgaa\\\\pip.exe'\r\n    Consider using the `--user` option or check the permissions.\r\n    \r\n    \r\n```  \r\n  \r\n```\r\nTraceback (most recent call last):\r\n  File \"c:\\program files\\python37\\lib\\site-packages\\pre_commit\\error_handler.py\", line 56, in error_handler\r\n    yield\r\n  File \"c:\\program files\\python37\\lib\\site-packages\\pre_commit\\main.py\", line 372, in main\r\n    args=args.rest[1:],\r\n  File \"c:\\program files\\python37\\lib\\site-packages\\pre_commit\\commands\\hook_impl.py\", line 187, in hook_impl\r\n    return retv | run(config, store, ns)\r\n  File \"c:\\program files\\python37\\lib\\site-packages\\pre_commit\\commands\\run.py\", line 355, in run\r\n    install_hook_envs(hooks, store)\r\n  File \"c:\\program files\\python37\\lib\\site-packages\\pre_commit\\repository.py\", line 200, in install_hook_envs\r\n    _hook_install(hook)\r\n  File \"c:\\program files\\python37\\lib\\site-packages\\pre_commit\\repository.py\", line 83, in _hook_install\r\n    hook.prefix, hook.language_version, hook.additional_dependencies,\r\n  File \"c:\\program files\\python37\\lib\\site-packages\\pre_commit\\languages\\python.py\", line 197, in install_environment\r\n    prefix, ('pip', 'install', '.') + additional_dependencies,\r\n  File \"c:\\program files\\python37\\lib\\site-packages\\pre_commit\\languages\\helpers.py\", line 25, in run_setup_cmd\r\n    cmd_output_b(*cmd, cwd=prefix.prefix_dir)\r\n  File \"c:\\program files\\python37\\lib\\site-packages\\pre_commit\\util.py\", line 156, in cmd_output_b\r\n    raise CalledProcessError(returncode, cmd, retcode, stdout_b, stderr_b)\r\npre_commit.util.CalledProcessError: <unprintable CalledProcessError object>\r\n\r\n```\n", "before_files": [{"content": "import contextlib\nimport functools\nimport os\nimport sys\nfrom typing import Callable\nfrom typing import ContextManager\nfrom typing import Generator\nfrom typing import Optional\nfrom typing import Sequence\nfrom typing import Tuple\n\nimport pre_commit.constants as C\nfrom pre_commit.envcontext import envcontext\nfrom pre_commit.envcontext import PatchesT\nfrom pre_commit.envcontext import UNSET\nfrom pre_commit.envcontext import Var\nfrom pre_commit.hook import Hook\nfrom pre_commit.languages import helpers\nfrom pre_commit.parse_shebang import find_executable\nfrom pre_commit.prefix import Prefix\nfrom pre_commit.util import CalledProcessError\nfrom pre_commit.util import clean_path_on_failure\nfrom pre_commit.util import cmd_output\nfrom pre_commit.util import cmd_output_b\n\nENVIRONMENT_DIR = 'py_env'\n\n\ndef bin_dir(venv: str) -> str:\n    \"\"\"On windows there's a different directory for the virtualenv\"\"\"\n    bin_part = 'Scripts' if os.name == 'nt' else 'bin'\n    return os.path.join(venv, bin_part)\n\n\ndef get_env_patch(venv: str) -> PatchesT:\n    return (\n        ('PYTHONHOME', UNSET),\n        ('VIRTUAL_ENV', venv),\n        ('PATH', (bin_dir(venv), os.pathsep, Var('PATH'))),\n    )\n\n\ndef _find_by_py_launcher(\n        version: str,\n) -> Optional[str]:  # pragma: no cover (windows only)\n    if version.startswith('python'):\n        num = version[len('python'):]\n        try:\n            cmd = ('py', f'-{num}', '-c', 'import sys; print(sys.executable)')\n            return cmd_output(*cmd)[1].strip()\n        except CalledProcessError:\n            pass\n    return None\n\n\ndef _find_by_sys_executable() -> Optional[str]:\n    def _norm(path: str) -> Optional[str]:\n        _, exe = os.path.split(path.lower())\n        exe, _, _ = exe.partition('.exe')\n        if exe not in {'python', 'pythonw'} and find_executable(exe):\n            return exe\n        return None\n\n    # On linux, I see these common sys.executables:\n    #\n    # system `python`: /usr/bin/python -> python2.7\n    # system `python2`: /usr/bin/python2 -> python2.7\n    # virtualenv v: v/bin/python (will not return from this loop)\n    # virtualenv v -ppython2: v/bin/python -> python2\n    # virtualenv v -ppython2.7: v/bin/python -> python2.7\n    # virtualenv v -ppypy: v/bin/python -> v/bin/pypy\n    for path in (sys.executable, os.path.realpath(sys.executable)):\n        exe = _norm(path)\n        if exe:\n            return exe\n    return None\n\n\n@functools.lru_cache(maxsize=1)\ndef get_default_version() -> str:  # pragma: no cover (platform dependent)\n    # First attempt from `sys.executable` (or the realpath)\n    exe = _find_by_sys_executable()\n    if exe:\n        return exe\n\n    # Next try the `pythonX.X` executable\n    exe = f'python{sys.version_info[0]}.{sys.version_info[1]}'\n    if find_executable(exe):\n        return exe\n\n    if _find_by_py_launcher(exe):\n        return exe\n\n    # Give a best-effort try for windows\n    default_folder_name = exe.replace('.', '')\n    if os.path.exists(fr'C:\\{default_folder_name}\\python.exe'):\n        return exe\n\n    # We tried!\n    return C.DEFAULT\n\n\ndef _sys_executable_matches(version: str) -> bool:\n    if version == 'python':\n        return True\n    elif not version.startswith('python'):\n        return False\n\n    try:\n        info = tuple(int(p) for p in version[len('python'):].split('.'))\n    except ValueError:\n        return False\n\n    return sys.version_info[:len(info)] == info\n\n\ndef norm_version(version: str) -> str:\n    # first see if our current executable is appropriate\n    if _sys_executable_matches(version):\n        return sys.executable\n\n    if os.name == 'nt':  # pragma: no cover (windows)\n        version_exec = _find_by_py_launcher(version)\n        if version_exec:\n            return version_exec\n\n        # Try looking up by name\n        version_exec = find_executable(version)\n        if version_exec and version_exec != version:\n            return version_exec\n\n        # If it is in the form pythonx.x search in the default\n        # place on windows\n        if version.startswith('python'):\n            default_folder_name = version.replace('.', '')\n            return fr'C:\\{default_folder_name}\\python.exe'\n\n    # Otherwise assume it is a path\n    return os.path.expanduser(version)\n\n\ndef py_interface(\n        _dir: str,\n        _make_venv: Callable[[str, str], None],\n) -> Tuple[\n    Callable[[Prefix, str], ContextManager[None]],\n    Callable[[Prefix, str], bool],\n    Callable[[Hook, Sequence[str], bool], Tuple[int, bytes]],\n    Callable[[Prefix, str, Sequence[str]], None],\n]:\n    @contextlib.contextmanager\n    def in_env(\n            prefix: Prefix,\n            language_version: str,\n    ) -> Generator[None, None, None]:\n        envdir = prefix.path(helpers.environment_dir(_dir, language_version))\n        with envcontext(get_env_patch(envdir)):\n            yield\n\n    def healthy(prefix: Prefix, language_version: str) -> bool:\n        envdir = helpers.environment_dir(_dir, language_version)\n        exe_name = 'python.exe' if sys.platform == 'win32' else 'python'\n        py_exe = prefix.path(bin_dir(envdir), exe_name)\n        with in_env(prefix, language_version):\n            retcode, _, _ = cmd_output_b(\n                py_exe, '-c', 'import ctypes, datetime, io, os, ssl, weakref',\n                cwd='/',\n                retcode=None,\n            )\n        return retcode == 0\n\n    def run_hook(\n            hook: Hook,\n            file_args: Sequence[str],\n            color: bool,\n    ) -> Tuple[int, bytes]:\n        with in_env(hook.prefix, hook.language_version):\n            return helpers.run_xargs(hook, hook.cmd, file_args, color=color)\n\n    def install_environment(\n            prefix: Prefix,\n            version: str,\n            additional_dependencies: Sequence[str],\n    ) -> None:\n        additional_dependencies = tuple(additional_dependencies)\n        directory = helpers.environment_dir(_dir, version)\n\n        env_dir = prefix.path(directory)\n        with clean_path_on_failure(env_dir):\n            if version != C.DEFAULT:\n                python = norm_version(version)\n            else:\n                python = os.path.realpath(sys.executable)\n            _make_venv(env_dir, python)\n            with in_env(prefix, version):\n                helpers.run_setup_cmd(\n                    prefix, ('pip', 'install', '.') + additional_dependencies,\n                )\n\n    return in_env, healthy, run_hook, install_environment\n\n\ndef make_venv(envdir: str, python: str) -> None:\n    env = dict(os.environ, VIRTUALENV_NO_DOWNLOAD='1')\n    cmd = (sys.executable, '-mvirtualenv', envdir, '-p', python)\n    cmd_output_b(*cmd, env=env, cwd='/')\n\n\n_interface = py_interface(ENVIRONMENT_DIR, make_venv)\nin_env, healthy, run_hook, install_environment = _interface\n", "path": "pre_commit/languages/python.py"}], "after_files": [{"content": "import contextlib\nimport functools\nimport os\nimport sys\nfrom typing import Callable\nfrom typing import ContextManager\nfrom typing import Generator\nfrom typing import Optional\nfrom typing import Sequence\nfrom typing import Tuple\n\nimport pre_commit.constants as C\nfrom pre_commit.envcontext import envcontext\nfrom pre_commit.envcontext import PatchesT\nfrom pre_commit.envcontext import UNSET\nfrom pre_commit.envcontext import Var\nfrom pre_commit.hook import Hook\nfrom pre_commit.languages import helpers\nfrom pre_commit.parse_shebang import find_executable\nfrom pre_commit.prefix import Prefix\nfrom pre_commit.util import CalledProcessError\nfrom pre_commit.util import clean_path_on_failure\nfrom pre_commit.util import cmd_output\nfrom pre_commit.util import cmd_output_b\n\nENVIRONMENT_DIR = 'py_env'\n\n\ndef bin_dir(venv: str) -> str:\n    \"\"\"On windows there's a different directory for the virtualenv\"\"\"\n    bin_part = 'Scripts' if os.name == 'nt' else 'bin'\n    return os.path.join(venv, bin_part)\n\n\ndef get_env_patch(venv: str) -> PatchesT:\n    return (\n        ('PYTHONHOME', UNSET),\n        ('VIRTUAL_ENV', venv),\n        ('PATH', (bin_dir(venv), os.pathsep, Var('PATH'))),\n    )\n\n\ndef _find_by_py_launcher(\n        version: str,\n) -> Optional[str]:  # pragma: no cover (windows only)\n    if version.startswith('python'):\n        num = version[len('python'):]\n        try:\n            cmd = ('py', f'-{num}', '-c', 'import sys; print(sys.executable)')\n            return cmd_output(*cmd)[1].strip()\n        except CalledProcessError:\n            pass\n    return None\n\n\ndef _find_by_sys_executable() -> Optional[str]:\n    def _norm(path: str) -> Optional[str]:\n        _, exe = os.path.split(path.lower())\n        exe, _, _ = exe.partition('.exe')\n        if exe not in {'python', 'pythonw'} and find_executable(exe):\n            return exe\n        return None\n\n    # On linux, I see these common sys.executables:\n    #\n    # system `python`: /usr/bin/python -> python2.7\n    # system `python2`: /usr/bin/python2 -> python2.7\n    # virtualenv v: v/bin/python (will not return from this loop)\n    # virtualenv v -ppython2: v/bin/python -> python2\n    # virtualenv v -ppython2.7: v/bin/python -> python2.7\n    # virtualenv v -ppypy: v/bin/python -> v/bin/pypy\n    for path in (sys.executable, os.path.realpath(sys.executable)):\n        exe = _norm(path)\n        if exe:\n            return exe\n    return None\n\n\n@functools.lru_cache(maxsize=1)\ndef get_default_version() -> str:  # pragma: no cover (platform dependent)\n    # First attempt from `sys.executable` (or the realpath)\n    exe = _find_by_sys_executable()\n    if exe:\n        return exe\n\n    # Next try the `pythonX.X` executable\n    exe = f'python{sys.version_info[0]}.{sys.version_info[1]}'\n    if find_executable(exe):\n        return exe\n\n    if _find_by_py_launcher(exe):\n        return exe\n\n    # Give a best-effort try for windows\n    default_folder_name = exe.replace('.', '')\n    if os.path.exists(fr'C:\\{default_folder_name}\\python.exe'):\n        return exe\n\n    # We tried!\n    return C.DEFAULT\n\n\ndef _sys_executable_matches(version: str) -> bool:\n    if version == 'python':\n        return True\n    elif not version.startswith('python'):\n        return False\n\n    try:\n        info = tuple(int(p) for p in version[len('python'):].split('.'))\n    except ValueError:\n        return False\n\n    return sys.version_info[:len(info)] == info\n\n\ndef norm_version(version: str) -> str:\n    # first see if our current executable is appropriate\n    if _sys_executable_matches(version):\n        return sys.executable\n\n    if os.name == 'nt':  # pragma: no cover (windows)\n        version_exec = _find_by_py_launcher(version)\n        if version_exec:\n            return version_exec\n\n        # Try looking up by name\n        version_exec = find_executable(version)\n        if version_exec and version_exec != version:\n            return version_exec\n\n        # If it is in the form pythonx.x search in the default\n        # place on windows\n        if version.startswith('python'):\n            default_folder_name = version.replace('.', '')\n            return fr'C:\\{default_folder_name}\\python.exe'\n\n    # Otherwise assume it is a path\n    return os.path.expanduser(version)\n\n\ndef py_interface(\n        _dir: str,\n        _make_venv: Callable[[str, str], None],\n) -> Tuple[\n    Callable[[Prefix, str], ContextManager[None]],\n    Callable[[Prefix, str], bool],\n    Callable[[Hook, Sequence[str], bool], Tuple[int, bytes]],\n    Callable[[Prefix, str, Sequence[str]], None],\n]:\n    @contextlib.contextmanager\n    def in_env(\n            prefix: Prefix,\n            language_version: str,\n    ) -> Generator[None, None, None]:\n        envdir = prefix.path(helpers.environment_dir(_dir, language_version))\n        with envcontext(get_env_patch(envdir)):\n            yield\n\n    def healthy(prefix: Prefix, language_version: str) -> bool:\n        envdir = helpers.environment_dir(_dir, language_version)\n        exe_name = 'python.exe' if sys.platform == 'win32' else 'python'\n        py_exe = prefix.path(bin_dir(envdir), exe_name)\n        with in_env(prefix, language_version):\n            retcode, _, _ = cmd_output_b(\n                py_exe, '-c', 'import ctypes, datetime, io, os, ssl, weakref',\n                cwd='/',\n                retcode=None,\n            )\n        return retcode == 0\n\n    def run_hook(\n            hook: Hook,\n            file_args: Sequence[str],\n            color: bool,\n    ) -> Tuple[int, bytes]:\n        with in_env(hook.prefix, hook.language_version):\n            return helpers.run_xargs(hook, hook.cmd, file_args, color=color)\n\n    def install_environment(\n            prefix: Prefix,\n            version: str,\n            additional_dependencies: Sequence[str],\n    ) -> None:\n        directory = helpers.environment_dir(_dir, version)\n        install = ('python', '-mpip', 'install', '.', *additional_dependencies)\n\n        env_dir = prefix.path(directory)\n        with clean_path_on_failure(env_dir):\n            if version != C.DEFAULT:\n                python = norm_version(version)\n            else:\n                python = os.path.realpath(sys.executable)\n            _make_venv(env_dir, python)\n            with in_env(prefix, version):\n                helpers.run_setup_cmd(prefix, install)\n\n    return in_env, healthy, run_hook, install_environment\n\n\ndef make_venv(envdir: str, python: str) -> None:\n    env = dict(os.environ, VIRTUALENV_NO_DOWNLOAD='1')\n    cmd = (sys.executable, '-mvirtualenv', envdir, '-p', python)\n    cmd_output_b(*cmd, env=env, cwd='/')\n\n\n_interface = py_interface(ENVIRONMENT_DIR, make_venv)\nin_env, healthy, run_hook, install_environment = _interface\n", "path": "pre_commit/languages/python.py"}]}