diff --git a/pipenv/cli.py b/pipenv/cli.py index 400ada6e..6f1b7557 100644 --- a/pipenv/cli.py +++ b/pipenv/cli.py @@ -21,16 +21,12 @@ from blindspin import spinner from requests.packages.urllib3.exceptions import InsecureRequestWarning from .project import Project -from .utils import convert_deps_from_pip, convert_deps_to_pip, is_required_version +from .utils import (convert_deps_from_pip, convert_deps_to_pip, is_required_version, + proper_case, pep426_name) from .__version__ import __version__ from . import pep508checker from .environments import PIPENV_COLORBLIND, PIPENV_NOSPIN, PIPENV_SHELL_COMPAT, PIPENV_VENV_IN_PROJECT -try: - from HTMLParser import HTMLParser -except ImportError: - from html.parser import HTMLParser - # Backport required for earlier versions of Python. if sys.version_info < (3, 3): from backports.shutil_get_terminal_size import get_terminal_size @@ -294,6 +290,8 @@ def parse_install_output(output): name = lines[0].split('(')[0] # Strip version specification. e.g. package; python-version=2.6 name = name.split(';')[0] + # Standardize name to pep426. + name = pep426_name(name.strip()) for line in lines: r = parse.parse('Saved {file}', line.strip()) @@ -306,7 +304,7 @@ def parse_install_output(output): # Unencode percent-encoded values like ``!`` in version number. fname = requests.compat.unquote(fname) - names.append((fname, name.strip())) + names.append((fname, name)) break return names @@ -585,33 +583,6 @@ def which_pip(allow_global=False): return which('pip') -def proper_case(package_name): - - # Capture tag contents here. - collected = [] - - class SimpleHTMLParser(HTMLParser): - def handle_data(self, data): - # Remove extra blank data from https://pypi.org/simple - data = data.strip() - if len(data) > 2: - collected.append(data) - - # Hit the simple API. - r = requests.get('https://pypi.org/simple/{0}'.format(package_name)) - if not r.ok: - raise IOError('Unable to find package {0} in PyPI repository.'.format(crayons.green(package_name))) - - # Parse the HTML. - parser = SimpleHTMLParser() - parser.feed(r.text) - - r = parse.parse('Links for {name}', collected[1]) - good_name = r['name'] - - return good_name - - def format_help(help): """Formats the help string.""" help = help.replace(' check', str(crayons.green(' check'))) diff --git a/pipenv/project.py b/pipenv/project.py index 965b3403..ed7716ba 100644 --- a/pipenv/project.py +++ b/pipenv/project.py @@ -11,8 +11,8 @@ import toml import delegator from requests.compat import OrderedDict -from .utils import format_toml, mkdir_p -from .utils import convert_deps_from_pip +from .utils import (format_toml, mkdir_p, convert_deps_from_pip, + proper_case, pep426_name, VCS_LIST) from .environments import PIPENV_MAX_DEPTH, PIPENV_VENV_IN_PROJECT diff --git a/pipenv/utils.py b/pipenv/utils.py index 8c50a107..cc163223 100644 --- a/pipenv/utils.py +++ b/pipenv/utils.py @@ -2,8 +2,17 @@ import os import tempfile +import parse +import requests import requirements +try: + from HTMLParser import HTMLParser +except ImportError: + from html.parser import HTMLParser + +# List of version control systems we support. +VCS_LIST = ('git', 'svn', 'hg', 'bzr') def format_toml(data): """Pretty-formats a given toml string.""" @@ -85,7 +94,7 @@ def convert_deps_to_pip(deps, r=True): version = deps[dep]['version'] # Support for version control - maybe_vcs = [vcs for vcs in ('git', 'svn', 'hg', 'bzr') if vcs in deps[dep]] + maybe_vcs = [vcs for vcs in VCS_LIST if vcs in deps[dep]] vcs = maybe_vcs[0] if maybe_vcs else None if vcs: @@ -144,3 +153,35 @@ def is_required_version(version, specified_version): if specified_version.startswith('=='): return version.strip() == specified_version.split('==')[1].strip() return True + + +def pep426_name(name): + """Normalize package name to pep426 style standard.""" + return name.lower().replace('_','-') + + +def proper_case(package_name): + """Properly case project name from pypi.org""" + # Capture tag contents here. + collected = [] + + class SimpleHTMLParser(HTMLParser): + def handle_data(self, data): + # Remove extra blank data from https://pypi.org/simple + data = data.strip() + if len(data) > 2: + collected.append(data) + + # Hit the simple API. + r = requests.get('https://pypi.org/simple/{0}'.format(package_name)) + if not r.ok: + raise IOError('Unable to find package {0} in PyPI repository.'.format(crayons.green(package_name))) + + # Parse the HTML. + parser = SimpleHTMLParser() + parser.feed(r.text) + + r = parse.parse('Links for {name}', collected[1]) + good_name = r['name'] + + return good_name