Fix Python version parser for 2.7.0

Fix #1893.
This commit is contained in:
Tzu-ping Chung
2018-04-05 17:29:02 +08:00
parent 7920e9cf5c
commit e46cabcb2c
2 changed files with 52 additions and 16 deletions
+32 -16
View File
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
import errno
import os
import re
import hashlib
import tempfile
import sys
@@ -175,29 +176,44 @@ def cleanup_toml(tml):
return toml
def parse_python_version(output):
"""Parse a Python version output returned by `python --version`.
Return a dict with three keys: major, minor, and micro. Each value is a
string containing a version part.
Note: The micro part would be `'0'` if it's missing from the input string.
"""
version_pattern = re.compile(r'''
^ # Beginning of line.
Python # Literally "Python".
\s # Space.
(?P<major>\d+) # Major = one or more digits.
\. # Dot.
(?P<minor>\d+) # Minor = one or more digits.
(?: # Unnamed group for dot-micro.
\. # Dot.
(?P<micro>\d+) # Micro = one or more digit.
)? # Micro is optional because pypa/pipenv#1893.
.* # Trailing garbage.
$ # End of line.
''', re.VERBOSE)
match = version_pattern.match(output)
if not match:
return None
return match.groupdict(default='0')
def python_version(path_to_python):
if not path_to_python:
return None
try:
c = delegator.run([path_to_python, '--version'], block=False)
except Exception:
return None
output = c.out.strip() or c.err.strip()
@parse.with_pattern(r'.*')
def allow_empty(text):
return text
TEMPLATE = 'Python {}.{}.{:d}{:AllowEmpty}'
parsed = parse.parse(TEMPLATE, output, dict(AllowEmpty=allow_empty))
if parsed:
parsed = parsed.fixed
else:
return None
return u"{v[0]}.{v[1]}.{v[2]}".format(v=parsed)
version = parse_python_version(c.out.strip() or c.err.strip())
return u'{major}.{minor}.{micro}'.format(**version)
def escape_grouped_arguments(s):
+20
View File
@@ -401,3 +401,23 @@ twine = "*"
)
def test_prepare_pip_source_args(self, sources, expected_args):
assert pipenv.utils.prepare_pip_source_args(sources, pip_args=None) == expected_args
@pytest.mark.utils
def test_parse_python_version(self):
ver = pipenv.utils.parse_python_version('Python 3.6.5\n')
assert ver == {'major': '3', 'minor': '6', 'micro': '5'}
@pytest.mark.utils
def test_parse_python_version_suffix(self):
ver = pipenv.utils.parse_python_version('Python 3.6.5rc1\n')
assert ver == {'major': '3', 'minor': '6', 'micro': '5'}
@pytest.mark.utils
def test_parse_python_version_270(self):
ver = pipenv.utils.parse_python_version('Python 2.7\n')
assert ver == {'major': '2', 'minor': '7', 'micro': '0'}
@pytest.mark.utils
def test_parse_python_version_270_garbage(self):
ver = pipenv.utils.parse_python_version('Python 2.7+\n')
assert ver == {'major': '2', 'minor': '7', 'micro': '0'}