From bad0846246b8522e4cd3d563822b45a41c6e1d8f Mon Sep 17 00:00:00 2001 From: Frost Ming Date: Thu, 28 May 2020 21:50:26 +0800 Subject: [PATCH 1/8] Don't check against root directory --- pipenv/core.py | 8 -------- pipenv/project.py | 4 ++-- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/pipenv/core.py b/pipenv/core.py index 1938e7f5..10508044 100644 --- a/pipenv/core.py +++ b/pipenv/core.py @@ -568,14 +568,6 @@ def ensure_project( system = True if not project.pipfile_exists and deploy: raise exceptions.PipfileNotFound - # Fail if working under / - if not project.name: - click.echo( - "{0}: Pipenv is not intended to work under the root directory, " - "please choose another path.".format(crayons.red("ERROR")), - err=True - ) - sys.exit(1) # Skip virtualenv creation when --system was used. if not system: ensure_virtualenv( diff --git a/pipenv/project.py b/pipenv/project.py index 40b6b263..54d51a65 100644 --- a/pipenv/project.py +++ b/pipenv/project.py @@ -685,8 +685,8 @@ class Project(object): from .vendor.pip_shims.shims import ( ConfigOptionParser, make_option_group, index_group ) - - config_parser = ConfigOptionParser(name=self.name) + # Inherit the pip's index configuration of install command. + config_parser = ConfigOptionParser(name="install") config_parser.add_option_group(make_option_group(index_group, config_parser)) install = config_parser.option_groups[0] indexes = ( From f6567bb328a5da780706338a9ca517e5a8658611 Mon Sep 17 00:00:00 2001 From: Frost Ming Date: Thu, 28 May 2020 21:54:33 +0800 Subject: [PATCH 2/8] add news entry --- news/4273.bugfix.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 news/4273.bugfix.rst diff --git a/news/4273.bugfix.rst b/news/4273.bugfix.rst new file mode 100644 index 00000000..a6140178 --- /dev/null +++ b/news/4273.bugfix.rst @@ -0,0 +1 @@ +Fix a bug that Pipenv rejects to work under the root directory. From 3f4abadac255d527f94c8fa60590e1472acd814b Mon Sep 17 00:00:00 2001 From: frostming Date: Fri, 29 May 2020 11:02:33 +0800 Subject: [PATCH 3/8] Use InstallCommand to fetch options --- pipenv/project.py | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/pipenv/project.py b/pipenv/project.py index 54d51a65..3d88c897 100644 --- a/pipenv/project.py +++ b/pipenv/project.py @@ -682,18 +682,10 @@ class Project(object): def create_pipfile(self, python=None): """Creates the Pipfile, filled with juicy defaults.""" - from .vendor.pip_shims.shims import ( - ConfigOptionParser, make_option_group, index_group - ) + from .vendor.pip_shims.shims import InstallCommand # Inherit the pip's index configuration of install command. - config_parser = ConfigOptionParser(name="install") - config_parser.add_option_group(make_option_group(index_group, config_parser)) - install = config_parser.option_groups[0] - indexes = ( - " ".join(install.get_option("--extra-index-url").default) - .lstrip("\n") - .split("\n") - ) + command = InstallCommand() + indexes = command.cmd_opts.get_option("--extra-index-url").default sources = [DEFAULT_SOURCE] for i, index in enumerate(indexes): if not index: From ac0e152a80103e3fe88d79af68193df93e11c82d Mon Sep 17 00:00:00 2001 From: frostming Date: Fri, 29 May 2020 13:01:53 +0800 Subject: [PATCH 4/8] Ignore errors removing user cache dir --- pipenv/core.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pipenv/core.py b/pipenv/core.py index 10508044..ed968383 100644 --- a/pipenv/core.py +++ b/pipenv/core.py @@ -126,9 +126,6 @@ def do_clear(): try: vistir.path.rmtree(PIPENV_CACHE_DIR, onerror=vistir.path.handle_remove_readonly) - vistir.path.rmtree( - locations.USER_CACHE_DIR, onerror=vistir.path.handle_remove_readonly - ) except OSError as e: # Ignore FileNotFoundError. This is needed for Python 2.7. import errno @@ -136,6 +133,8 @@ def do_clear(): if e.errno == errno.ENOENT: pass raise + # Other processes may be writing into this directory simultaneously. + vistir.path.rmtree(locations.USER_CACHE_DIR, ignore_errors=True) def load_dot_env(): From af649b2b865db90e3c6eed91a6523a343ca3bf03 Mon Sep 17 00:00:00 2001 From: frostming Date: Fri, 29 May 2020 13:35:56 +0800 Subject: [PATCH 5/8] Fix incorrect environment when inside venv --- news/4276.bgufix.rst | 1 + pipenv/project.py | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 news/4276.bgufix.rst diff --git a/news/4276.bgufix.rst b/news/4276.bgufix.rst new file mode 100644 index 00000000..960ab08b --- /dev/null +++ b/news/4276.bgufix.rst @@ -0,0 +1 @@ +Fix a bug that system-wide packages will be considered when inside a venv. diff --git a/pipenv/project.py b/pipenv/project.py index 40b6b263..16bc715d 100644 --- a/pipenv/project.py +++ b/pipenv/project.py @@ -330,11 +330,11 @@ class Project(object): def get_environment(self, allow_global=False): # type: (bool) -> Environment - if allow_global: + is_venv = is_in_virtualenv() + if allow_global and not is_venv: prefix = sys.prefix else: prefix = self.virtualenv_location - is_venv = is_in_virtualenv() sources = self.sources if self.sources else [DEFAULT_SOURCE] environment = Environment( prefix=prefix, is_venv=is_venv, sources=sources, pipfile=self.parsed_pipfile, From 08ec79d5db261b88c5b74caab17d765181fcd29f Mon Sep 17 00:00:00 2001 From: frostming Date: Fri, 29 May 2020 13:40:50 +0800 Subject: [PATCH 6/8] fix filename --- news/{4276.bgufix.rst => 4276.bugfix.rst} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename news/{4276.bgufix.rst => 4276.bugfix.rst} (100%) diff --git a/news/4276.bgufix.rst b/news/4276.bugfix.rst similarity index 100% rename from news/4276.bgufix.rst rename to news/4276.bugfix.rst From fc50e6dbe7f365b7cc15790baede6ad7720a25d4 Mon Sep 17 00:00:00 2001 From: Dan Ryan Date: Fri, 29 May 2020 01:53:47 -0400 Subject: [PATCH 7/8] Improve virtualenv and venv detection - Virtualenv and venv detection depends on more than just an envvar - Add improved detection mechanisms to `is_in_virtualenv()` function Signed-off-by: Dan Ryan --- news/4276.feature.rst | 1 + pipenv/core.py | 4 +++- pipenv/environment.py | 5 ++++- pipenv/environments.py | 20 +++++++++++++++++--- 4 files changed, 25 insertions(+), 5 deletions(-) create mode 100644 news/4276.feature.rst diff --git a/news/4276.feature.rst b/news/4276.feature.rst new file mode 100644 index 00000000..c1851a02 --- /dev/null +++ b/news/4276.feature.rst @@ -0,0 +1 @@ +Pipenv will now detect existing ``venv`` and ``virtualenv`` based virtual environments more robustly. diff --git a/pipenv/core.py b/pipenv/core.py index 1938e7f5..59c7572b 100644 --- a/pipenv/core.py +++ b/pipenv/core.py @@ -993,8 +993,10 @@ def do_create_virtualenv(python=None, site_packages=None, pypi_mirror=None): f.write(vistir.misc.fs_str(project.project_directory)) from .environment import Environment sources = project.pipfile_sources + # project.get_location_for_virtualenv is only for if we are creating a new virtualenv + # whereas virtualenv_location is for the current path to the runtime project._environment = Environment( - prefix=project.get_location_for_virtualenv(), + prefix=project.virtualenv_location, is_venv=True, sources=sources, pipfile=project.parsed_pipfile, diff --git a/pipenv/environment.py b/pipenv/environment.py index 09ea73a3..d47b2037 100644 --- a/pipenv/environment.py +++ b/pipenv/environment.py @@ -25,6 +25,9 @@ from .vendor import vistir from .utils import normalize_path, make_posix +if False: + from typing import Optional + BASE_WORKING_SET = pkg_resources.WorkingSet(sys.path) # TODO: Unittests for this class @@ -469,7 +472,7 @@ class Environment(object): ), None) if pip is not None: return parse_version(pip.version) - return parse_version("19.3") + return parse_version("20.2") def expand_egg_links(self): """ diff --git a/pipenv/environments.py b/pipenv/environments.py index 88752231..b9d89806 100644 --- a/pipenv/environments.py +++ b/pipenv/environments.py @@ -81,7 +81,7 @@ PIPENV_IS_CI = bool("CI" in os.environ or "TF_BUILD" in os.environ) # HACK: Prevent invalid shebangs with Homebrew-installed Python: # https://bugs.python.org/issue22490 -os.environ.pop("__PYVENV_LAUNCHER__", None) +_OSX_VENV = os.environ.pop("__PYVENV_LAUNCHER__", None) # Load patched pip instead of system pip os.environ["PIP_SHIMS_BASE_MODULE"] = fs_str("pipenv.patched.notpip") @@ -326,7 +326,7 @@ PIPENV_TEST_INDEX = os.environ.get("PIPENV_TEST_INDEX") PIPENV_USE_SYSTEM = False PIPENV_VIRTUALENV = None if "PIPENV_ACTIVE" not in os.environ and not PIPENV_IGNORE_VIRTUALENVS: - PIPENV_VIRTUALENV = os.environ.get("VIRTUAL_ENV") + PIPENV_VIRTUALENV = os.environ.get("VIRTUAL_ENV") or _OSX_VENV PIPENV_USE_SYSTEM = bool(PIPENV_VIRTUALENV) # Internal, tells Pipenv to skip case-checking (slow internet connections). @@ -371,6 +371,18 @@ def is_quiet(threshold=-1): return PIPENV_VERBOSITY <= threshold +def _is_using_venv(): + # type: () -> bool + """Check for venv-based virtual environment which sets sys.base_prefix""" + return _OSX_VENV is not None or sys.prefix != getattr(sys, "base_prefix", sys.prefix) + + +def _is_using_virtualenv(): + # type: () -> bool + """Check for virtualenv-based environment which sets sys.real_prefix""" + return getattr(sys, "real_prefix", None) is not None + + def is_in_virtualenv(): """ Check virtualenv membership dynamically @@ -385,7 +397,9 @@ def is_in_virtualenv(): ignore_virtualenvs = bool(os.environ.get("PIPENV_IGNORE_VIRTUALENVS", False)) if not pipenv_active and not ignore_virtualenvs: - virtual_env = os.environ.get("VIRTUAL_ENV") + virtual_env = any([ + _is_using_virtualenv(), _is_using_venv(), os.environ.get("VIRTUAL_ENV") + ]) use_system = bool(virtual_env) return (use_system or virtual_env) and not (pipenv_active or ignore_virtualenvs) From dffcac123352249a7b5e40158a94663e9f1c1342 Mon Sep 17 00:00:00 2001 From: frostming Date: Fri, 29 May 2020 14:18:13 +0800 Subject: [PATCH 8/8] Only ignore errors for CI builds --- pipenv/core.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pipenv/core.py b/pipenv/core.py index ed968383..a90afa60 100644 --- a/pipenv/core.py +++ b/pipenv/core.py @@ -126,6 +126,12 @@ def do_clear(): try: vistir.path.rmtree(PIPENV_CACHE_DIR, onerror=vistir.path.handle_remove_readonly) + # Other processes may be writing into this directory simultaneously. + vistir.path.rmtree( + locations.USER_CACHE_DIR, + ignore_errors=environments.PIPENV_IS_CI, + onerror=vistir.path.handle_remove_readonly + ) except OSError as e: # Ignore FileNotFoundError. This is needed for Python 2.7. import errno @@ -133,8 +139,6 @@ def do_clear(): if e.errno == errno.ENOENT: pass raise - # Other processes may be writing into this directory simultaneously. - vistir.path.rmtree(locations.USER_CACHE_DIR, ignore_errors=True) def load_dot_env():