Repository: kennethreitz/pipenv
Pull request #175 (2017-02-01 01:55:16)

Improve dashed version parsing
Hi! Hope you don't mind that I wrote some quick code for this. It was breaking on the dash in version 3.2.3-2 of functools32, which is preventing me from sharing some pipenv code with colleagues.

With this PR, instead of truncating the ends of versions containing dashes, it will keep them intact. Also I added some tests for the parse_download_fname function.


Patch:
diff --git a/pipenv/cli.py b/pipenv/cli.py
index d280f357..d726a7e0 100644
--- a/pipenv/cli.py
+++ b/pipenv/cli.py
@@ -2,6 +2,7 @@
 import codecs
 import json
 import os
+import re
 import sys
 import distutils.spawn
 import shutil
@@ -327,22 +328,29 @@ def do_create_virtualenv(three=None, python=None):
     do_where(virtualenv=True, bare=False)
 
 
-def parse_download_fname(fname):
-
-    # Use Parse to attempt to parse filenames for metadata.
-    r = parse.search('{name}-{version}.tar', fname)
-    if not r:
-        r = parse.search('{name}-{version}.zip', fname)
-    if not r:
-        r = parse.parse('{name}-{version}-{extra}.{ext}', fname)
+def is_version(text):
+    return re.match('^[\d]+\.[\d]+.*', text) or False
 
-    version = r['version']
 
-    # Support for requirements-parser-0.1.0.tar.gz
-    # TODO: Some versions might actually have dashes, will need to figure that out.
-    # Will likely have to check of '-' comes at beginning or end of version.
-    if '-' in version:
-        version = version.split('-')[-1]
+def parse_download_fname(fname):
+    version = ''
+    have_found_version_start = False
+    fname, fextension = os.path.splitext(fname)
+
+    if fextension == '.whl':
+        fname = '-'.join(fname.split('-')[:-3])
+
+    if fextension == '.gz' and fname.endswith('.tar'):
+        fname, _ = os.path.splitext(fname)
+
+    fname_components = fname.split('-')
+    for fname_component in fname_components:
+        if is_version(fname_component):
+            have_found_version_start = True
+        if have_found_version_start:
+            if len(version) > 0:
+                version += '-'
+            version += fname_component
 
     return version
 


Test patch:
diff --git a/test_pipenv.py b/test_pipenv.py
index 60dab302..ea8cbb42 100644
--- a/test_pipenv.py
+++ b/test_pipenv.py
@@ -1,8 +1,36 @@
 import pytest
 
+from pipenv.cli import parse_download_fname
 import pipenv.utils
 
 
+def test_parse_download_fname():
+
+    fname = 'functools32-3.2.3-2.zip'
+    version = parse_download_fname(fname)
+    assert version == '3.2.3-2'
+
+    fname = 'functools32-3.2.3-blah.zip'
+    version = parse_download_fname(fname)
+    assert version == '3.2.3-blah'
+
+    fname = 'functools32-3.2.3.zip'
+    version = parse_download_fname(fname)
+    assert version == '3.2.3'
+
+    fname = 'colorama-0.3.7-py2.py3-none-any.whl'
+    version = parse_download_fname(fname)
+    assert version == '0.3.7'
+
+    fname = 'colorama-0.3.7-2-py2.py3-none-any.whl'
+    version = parse_download_fname(fname)
+    assert version == '0.3.7-2'
+
+    fname = 'click-completion-0.2.1.tar.gz'
+    version = parse_download_fname(fname)
+    assert version == '0.2.1'
+
+
 def test_convert_deps_to_pip():
 
     # requests = '*'