From 72e2ef70c5b2d2b5820f5e7af1dc401e3da15cfb Mon Sep 17 00:00:00 2001 From: Dan Ryan Date: Tue, 13 Nov 2018 14:56:26 -0500 Subject: [PATCH] Derive source names from URLs when not supplied - Fixes #3216 Signed-off-by: Dan Ryan --- news/3216.bugfix.rst | 1 + pipenv/environment.py | 15 ++++++++++++--- pipenv/project.py | 3 ++- pipenv/utils.py | 13 +++++++++++++ 4 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 news/3216.bugfix.rst diff --git a/news/3216.bugfix.rst b/news/3216.bugfix.rst new file mode 100644 index 00000000..1d600bb8 --- /dev/null +++ b/news/3216.bugfix.rst @@ -0,0 +1 @@ +When sources are missing names, names will now be derived from the supplied URL. diff --git a/pipenv/environment.py b/pipenv/environment.py index 8e96f2c8..7a7fd2ea 100644 --- a/pipenv/environment.py +++ b/pipenv/environment.py @@ -18,6 +18,8 @@ from cached_property import cached_property import vistir import pipenv +from .utils import normalize_path + BASE_WORKING_SET = pkg_resources.WorkingSet(sys.path) @@ -27,8 +29,8 @@ class Environment(object): super(Environment, self).__init__() self._modules = {'pkg_resources': pkg_resources, 'pipenv': pipenv} self.base_working_set = base_working_set if base_working_set else BASE_WORKING_SET - prefix = os.path.normcase(os.path.normpath(os.path.abspath(str(prefix)))) - self.is_venv = not prefix == os.path.normcase(os.path.normpath(sys.prefix)) + prefix = normalize_path(prefix) + self.is_venv = not prefix == normalize_path(sys.prefix) if not sources: sources = [] self.project = project @@ -81,7 +83,7 @@ class Environment(object): deps.add(dist) try: reqs = dist.requires() - except (AttributeError, OSError): # The METADATA file can't be found + except (AttributeError, OSError, IOError): # The METADATA file can't be found return deps for req in reqs: dist = working_set.find(req) @@ -243,6 +245,7 @@ class Environment(object): return pkg_resources.find_distributions(self.paths["PYTHONPATH"]) def find_egg(self, egg_dist): + """Find an egg by name in the given environment""" site_packages = get_python_lib() search_filename = "{0}.egg-link".format(egg_dist.project_name) try: @@ -256,11 +259,16 @@ class Environment(object): return egg def locate_dist(self, dist): + """Given a distribution, try to find a corresponding egg link first. + + If the egg - link doesn 't exist, return the supplied distribution.""" + location = self.find_egg(dist) if not location: return dist.location def dist_is_in_project(self, dist): + """Determine whether the supplied distribution is in the environment.""" from .project import _normalized prefix = _normalized(self.base_paths["prefix"]) location = self.locate_dist(dist) @@ -269,6 +277,7 @@ class Environment(object): return _normalized(location).startswith(prefix) def get_installed_packages(self): + """Returns all of the installed packages in a given environment""" workingset = self.get_working_set() packages = [pkg for pkg in workingset if self.dist_is_in_project(pkg)] return packages diff --git a/pipenv/project.py b/pipenv/project.py index 957b6827..590fafe5 100644 --- a/pipenv/project.py +++ b/pipenv/project.py @@ -29,6 +29,7 @@ from .utils import ( convert_toml_outline_tables, is_installable_file, is_valid_url, + get_url_name, normalize_drive, python_version, safe_expandvars, @@ -747,7 +748,7 @@ class Project(object): sources = [sources,] lockfile_dict["_meta"]["sources"] = [ { - "name": s["name"], + "name": s.get("name", get_url_name(s.get("url"))), "url": s["url"], "verify_ssl": ( s["verify_ssl"] if isinstance(s["verify_ssl"], bool) else ( diff --git a/pipenv/utils.py b/pipenv/utils.py index dcd67025..265c5797 100644 --- a/pipenv/utils.py +++ b/pipenv/utils.py @@ -1133,6 +1133,19 @@ def path_to_url(path): return Path(normalize_drive(os.path.abspath(path))).as_uri() +def normalize_path(path): + return os.path.expandvars(os.path.expanduser( + os.path.normcase(os.path.normpath(os.path.abspath(str(path)))) + )) + + +def get_url_name(url): + if not isinstance(url, six.string_types): + return + from urllib3.util import parse as urllib3_parse + return urllib3_parse(url).host + + def get_canonical_names(packages): """Canonicalize a list of packages and return a set of canonical names""" from .vendor.packaging.utils import canonicalize_name