Repository: pre-commit/pre-commit

Issue:
C:\python3\python.exe does not exist while running pre-commit on Windows
Hi,

I'm trying to run the pre-commit commands of the [ESSS/barril](https://github.com/ESSS/barril) repository on my Windows machine, but I'm getting this error:

```
 λ tox -e linting
linting installed: aspy.yaml==1.1.1,cfgv==1.4.0,identify==1.1.8,importlib-metadata==0.8,importlib-resources==1.0.2,nodeenv==1.3.3,pre-commit==1.14.0,PyYAML==3.13,six==1.12.0,toml==0.10.0,virtualenv==16.2.0,zipp==0.3.3
linting run-test-pre: PYTHONHASHSEED='554'
linting runtests: commands[0] | pre-commit run --all-files --show-diff-on-failure
[INFO] Installing environment for https://github.com/ambv/black.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
An unexpected error has occurred: CalledProcessError: Command: ('w:\\projects\\barril\\.tox\\linting\\scripts\\python.exe', '-mvirtualenv', 'C:\\Users\\darci\\.cache\\pre-commit\\repoufam_s8_\\py_env-python3', '-p', 'C:\\python3\\python.exe')
Return code: 3
Expected return code: 0
Output:
    The path C:\python3\python.exe (from --python=C:\python3\python.exe) does not exist

Errors: (none)

Check the log at C:\Users\darci/.cache\pre-commit\pre-commit.log
```

The `C:\python3` path does not exist on my machine, I'm using `conda` and `virtualenv` to create a Python 3.6 virtual environment, from which I execute `tox -e linting`.

Here's the contents of the `pre-commit-config.yaml`:

```yaml
repos:
-   repo: https://github.com/ambv/black
    rev: 18.6b4
    hooks:
    -   id: black
        args: [--safe, --quiet]
        language_version: python3
-   repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v1.3.0
    hooks:
    -   id: trailing-whitespace
    -   id: end-of-file-fixer
    -   id: check-yaml
    -   id: debug-statements
    -   id: flake8
-   repo: local
    hooks:
    -   id: rst
        name: rst
        entry: rst-lint --encoding utf-8
        files: ^(CHANGELOG.rst|HOWTORELEASE.rst|README.rst)$
        language: python
        additional_dependencies: [pygments, restructuredtext_lint]
```

Any hints of what the problem might be?

cc @nicoddemus 

Discussion:

Patch:
diff --git a/pre_commit/languages/python.py b/pre_commit/languages/python.py
index 46aa059..86f5368 100644
--- a/pre_commit/languages/python.py
+++ b/pre_commit/languages/python.py
@@ -89,8 +89,26 @@ def get_default_version():
         return get_default_version()
 
 
+def _sys_executable_matches(version):
+    if version == 'python':
+        return True
+    elif not version.startswith('python'):
+        return False
+
+    try:
+        info = tuple(int(p) for p in version[len('python'):].split('.'))
+    except ValueError:
+        return False
+
+    return sys.version_info[:len(info)] == info
+
+
 def norm_version(version):
     if os.name == 'nt':  # pragma: no cover (windows)
+        # first see if our current executable is appropriate
+        if _sys_executable_matches(version):
+            return sys.executable
+
         # Try looking up by name
         version_exec = find_executable(version)
         if version_exec and version_exec != version:


Test patch:
diff --git a/tests/languages/python_test.py b/tests/languages/python_test.py
index 366c010..426d3ec 100644
--- a/tests/languages/python_test.py
+++ b/tests/languages/python_test.py
@@ -2,6 +2,10 @@ from __future__ import absolute_import
 from __future__ import unicode_literals
 
 import os.path
+import sys
+
+import mock
+import pytest
 
 from pre_commit.languages import python
 
@@ -16,3 +20,15 @@ def test_norm_version_expanduser():
         expected_path = home + '/.pyenv/versions/3.4.3/bin/python'
     result = python.norm_version(path)
     assert result == expected_path
+
+
+@pytest.mark.parametrize('v', ('python3.6', 'python3', 'python'))
+def test_sys_executable_matches(v):
+    with mock.patch.object(sys, 'version_info', (3, 6, 7)):
+        assert python._sys_executable_matches(v)
+
+
+@pytest.mark.parametrize('v', ('notpython', 'python3.x'))
+def test_sys_executable_matches_does_not_match(v):
+    with mock.patch.object(sys, 'version_info', (3, 6, 7)):
+        assert not python._sys_executable_matches(v)