From 42de3d15edce3211b5e3ffed6ff391b6ca3b7d70 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Thu, 2 Aug 2018 00:56:09 -0700 Subject: [PATCH 01/56] Properly handle pre-existing .venv files --- pipenv/project.py | 13 +++++++- tests/integration/test_dot_venv.py | 51 ++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/pipenv/project.py b/pipenv/project.py index c5f451e4..751b9c5b 100644 --- a/pipenv/project.py +++ b/pipenv/project.py @@ -267,7 +267,18 @@ class Project(object): def get_location_for_virtualenv(self): if self.is_venv_in_project(): return os.path.join(self.project_directory, ".venv") - return str(get_workon_home().joinpath(self.virtualenv_name)) + + name = self.virtualenv_name + if self.project_directory: + venv_path = os.path.join(self.project_directory, ".venv") + if os.path.isfile(venv_path): + with open(venv_path, "r") as f: + name = f.read() + # Assume file's contents is a path if it contains slashes. + if '/' in name or '\\' in name: + return name + + return str(get_workon_home().joinpath(name)) def get_installed_packages(self): from . import PIPENV_ROOT, PIPENV_VENDOR, PIPENV_PATCHED diff --git a/tests/integration/test_dot_venv.py b/tests/integration/test_dot_venv.py index e7b157f3..6a8bedd9 100644 --- a/tests/integration/test_dot_venv.py +++ b/tests/integration/test_dot_venv.py @@ -1,5 +1,6 @@ import os +from pipenv._compat import TemporaryDirectory, Path from pipenv.project import Project from pipenv.utils import temp_environ, normalize_drive, get_windows_path from pipenv.vendor import delegator @@ -39,3 +40,53 @@ def test_reuse_previous_venv(PipenvInstance, pypi): c = p.pipenv('install requests') assert c.return_code == 0 assert normalize_drive(p.path) in p.pipenv('--venv').out + +@pytest.mark.dotvenv +def test_venv_file_with_name(PipenvInstance, pypi): + with PipenvInstance(chdir=True, pypi=pypi) as p: + file_path = os.path.join(p.path, ".venv") + venv_name = "test-project" + with open(file_path, "w") as f: + f.write(venv_name) + + with temp_environ(), TemporaryDirectory( + prefix="pipenv-", suffix="temp_workon_home" + ) as workon_home: + os.environ["WORKON_HOME"] = workon_home.name + if "PIPENV_VENV_IN_PROJECT" in os.environ: + del os.environ["PIPENV_VENV_IN_PROJECT"] + + c = p.pipenv("install requests") + assert c.return_code == 0 + + venv_loc = None + for line in c.err.splitlines(): + if line.startswith("Virtualenv location:"): + venv_loc = Path(line.split(":", 1)[-1].strip()) + assert venv_loc is not None + assert venv_loc.joinpath(".project").exists() + assert Path(venv_loc.name) == Path(venv_name) + +@pytest.mark.dotvenv +def test_venv_file_with_path(PipenvInstance, pypi): + with temp_environ(), PipenvInstance(chdir=True, pypi=pypi) as p: + with TemporaryDirectory( + prefix='pipenv-', suffix="-test_venv" + ) as venv_path: + if "PIPENV_VENV_IN_PROJECT" in os.environ: + del os.environ["PIPENV_VENV_IN_PROJECT"] + + file_path = os.path.join(p.path, ".venv") + with open(file_path, "w") as f: + f.write(venv_path.name) + + c = p.pipenv("install requests") + assert c.return_code == 0 + + venv_loc = None + for line in c.err.splitlines(): + if line.startswith("Virtualenv location:"): + venv_loc = Path(line.split(":", 1)[-1].strip()) + assert venv_loc is not None + assert venv_loc.joinpath(".project").exists() + assert venv_loc == Path(venv_path.name) From fed71c78cf4fc3b6fa9ec7fed9f5b8b2cde21bcc Mon Sep 17 00:00:00 2001 From: Dan Ryan Date: Sat, 4 Aug 2018 19:33:26 -0400 Subject: [PATCH 02/56] Remove old test line --- tests/integration/test_dot_venv.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/integration/test_dot_venv.py b/tests/integration/test_dot_venv.py index 6c9b31e4..70c683d5 100644 --- a/tests/integration/test_dot_venv.py +++ b/tests/integration/test_dot_venv.py @@ -49,7 +49,7 @@ def test_venv_file_exists(PipenvInstance, pypi): with PipenvInstance(pypi=pypi, chdir=True) as p: file_path = os.path.join(p.path, '.venv') with open(file_path, 'w') as f: - f.write('') + f.write('test-project') with temp_environ(), TemporaryDirectory( prefix='pipenv-', suffix='temp_workon_home' @@ -67,7 +67,6 @@ def test_venv_file_exists(PipenvInstance, pypi): venv_loc = Path(line.split(":", 1)[-1].strip()) assert venv_loc is not None assert venv_loc.joinpath(".project").exists() - assert Path(venv_loc.name) == Path(venv_name) @pytest.mark.dotvenv @@ -92,4 +91,4 @@ def test_venv_file_with_path(PipenvInstance, pypi): venv_loc = Path(line.split(":", 1)[-1].strip()) assert venv_loc is not None assert venv_loc.joinpath(".project").exists() - assert venv_loc == Path(venv_path.name) \ No newline at end of file + assert venv_loc == Path(venv_path.name) From 610f83bb7666ba5d0b3545fd75f076dd507e09a4 Mon Sep 17 00:00:00 2001 From: Dan Ryan Date: Sat, 4 Aug 2018 20:13:20 -0400 Subject: [PATCH 03/56] fix inclusion of project name in wrong test --- tests/integration/test_dot_venv.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration/test_dot_venv.py b/tests/integration/test_dot_venv.py index 70c683d5..26be39da 100644 --- a/tests/integration/test_dot_venv.py +++ b/tests/integration/test_dot_venv.py @@ -41,7 +41,7 @@ def test_reuse_previous_venv(PipenvInstance, pypi): assert c.return_code == 0 assert normalize_drive(p.path) in p.pipenv('--venv').out - + def test_venv_file_exists(PipenvInstance, pypi): """Tests virtualenv creation & package installation when a .venv file exists at the project root. @@ -49,7 +49,7 @@ def test_venv_file_exists(PipenvInstance, pypi): with PipenvInstance(pypi=pypi, chdir=True) as p: file_path = os.path.join(p.path, '.venv') with open(file_path, 'w') as f: - f.write('test-project') + f.write('') with temp_environ(), TemporaryDirectory( prefix='pipenv-', suffix='temp_workon_home' From bab6429bd94031452e540598a9f6093505557cb5 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Mon, 6 Aug 2018 12:29:34 -0700 Subject: [PATCH 04/56] switch test_venv_file_exists back to test_venv_file_with_name --- tests/integration/test_dot_venv.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/integration/test_dot_venv.py b/tests/integration/test_dot_venv.py index 26be39da..d547601d 100644 --- a/tests/integration/test_dot_venv.py +++ b/tests/integration/test_dot_venv.py @@ -42,14 +42,15 @@ def test_reuse_previous_venv(PipenvInstance, pypi): assert normalize_drive(p.path) in p.pipenv('--venv').out -def test_venv_file_exists(PipenvInstance, pypi): +def test_venv_file_with_name(PipenvInstance, pypi): """Tests virtualenv creation & package installation when a .venv file exists at the project root. """ with PipenvInstance(pypi=pypi, chdir=True) as p: file_path = os.path.join(p.path, '.venv') + venv_name = 'test-project' with open(file_path, 'w') as f: - f.write('') + f.write(venv_name) with temp_environ(), TemporaryDirectory( prefix='pipenv-', suffix='temp_workon_home' @@ -67,6 +68,7 @@ def test_venv_file_exists(PipenvInstance, pypi): venv_loc = Path(line.split(":", 1)[-1].strip()) assert venv_loc is not None assert venv_loc.joinpath(".project").exists() + assert Path(venv_loc.name) == Path(venv_name) @pytest.mark.dotvenv From 93d158b556a1f8aa5088f943894338fd34ebd95d Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Mon, 6 Aug 2018 12:30:42 -0700 Subject: [PATCH 05/56] simplify venv location retrieval in tests --- tests/integration/test_dot_venv.py | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/tests/integration/test_dot_venv.py b/tests/integration/test_dot_venv.py index d547601d..a122a9bc 100644 --- a/tests/integration/test_dot_venv.py +++ b/tests/integration/test_dot_venv.py @@ -62,11 +62,7 @@ def test_venv_file_with_name(PipenvInstance, pypi): c = p.pipenv('install requests') assert c.return_code == 0 - venv_loc = None - for line in c.err.splitlines(): - if line.startswith("Virtualenv location:"): - venv_loc = Path(line.split(":", 1)[-1].strip()) - assert venv_loc is not None + venv_loc = Path(p.pipenv('--venv').out.strip()) assert venv_loc.joinpath(".project").exists() assert Path(venv_loc.name) == Path(venv_name) @@ -87,10 +83,6 @@ def test_venv_file_with_path(PipenvInstance, pypi): c = p.pipenv("install requests") assert c.return_code == 0 - venv_loc = None - for line in c.err.splitlines(): - if line.startswith("Virtualenv location:"): - venv_loc = Path(line.split(":", 1)[-1].strip()) - assert venv_loc is not None + venv_loc = Path(p.pipenv('--venv').out.strip()) assert venv_loc.joinpath(".project").exists() assert venv_loc == Path(venv_path.name) From 4844a0b7a1ceffb2bdfc99128a4adc906111eced Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Mon, 6 Aug 2018 12:31:38 -0700 Subject: [PATCH 06/56] remove requests package install in tests We're only interested in testing if the virtual environment can be successfully created. --- tests/integration/test_dot_venv.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration/test_dot_venv.py b/tests/integration/test_dot_venv.py index a122a9bc..66550309 100644 --- a/tests/integration/test_dot_venv.py +++ b/tests/integration/test_dot_venv.py @@ -59,7 +59,7 @@ def test_venv_file_with_name(PipenvInstance, pypi): if 'PIPENV_VENV_IN_PROJECT' in os.environ: del os.environ['PIPENV_VENV_IN_PROJECT'] - c = p.pipenv('install requests') + c = p.pipenv('install') assert c.return_code == 0 venv_loc = Path(p.pipenv('--venv').out.strip()) @@ -80,7 +80,7 @@ def test_venv_file_with_path(PipenvInstance, pypi): with open(file_path, "w") as f: f.write(venv_path.name) - c = p.pipenv("install requests") + c = p.pipenv("install") assert c.return_code == 0 venv_loc = Path(p.pipenv('--venv').out.strip()) From 1fa14eaffdc1ae2d82df4a12e526c318e75de3ff Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Mon, 6 Aug 2018 12:31:58 -0700 Subject: [PATCH 07/56] add missing decorator for test_venv_file_with_name --- tests/integration/test_dot_venv.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/integration/test_dot_venv.py b/tests/integration/test_dot_venv.py index 66550309..14d8d359 100644 --- a/tests/integration/test_dot_venv.py +++ b/tests/integration/test_dot_venv.py @@ -42,6 +42,7 @@ def test_reuse_previous_venv(PipenvInstance, pypi): assert normalize_drive(p.path) in p.pipenv('--venv').out +@pytest.mark.dotvenv def test_venv_file_with_name(PipenvInstance, pypi): """Tests virtualenv creation & package installation when a .venv file exists at the project root. From e4a845fb31e27ebff07b56d170e9e86e272b4fc4 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Mon, 6 Aug 2018 12:32:54 -0700 Subject: [PATCH 08/56] update docstrings for tests --- tests/integration/test_dot_venv.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/tests/integration/test_dot_venv.py b/tests/integration/test_dot_venv.py index 14d8d359..c7ab1bd4 100644 --- a/tests/integration/test_dot_venv.py +++ b/tests/integration/test_dot_venv.py @@ -44,8 +44,8 @@ def test_reuse_previous_venv(PipenvInstance, pypi): @pytest.mark.dotvenv def test_venv_file_with_name(PipenvInstance, pypi): - """Tests virtualenv creation & package installation when a .venv file exists - at the project root. + """Tests virtualenv creation when a .venv file exists at the project root + and contains a venv name. """ with PipenvInstance(pypi=pypi, chdir=True) as p: file_path = os.path.join(p.path, '.venv') @@ -64,26 +64,29 @@ def test_venv_file_with_name(PipenvInstance, pypi): assert c.return_code == 0 venv_loc = Path(p.pipenv('--venv').out.strip()) - assert venv_loc.joinpath(".project").exists() + assert venv_loc.joinpath('.project').exists() assert Path(venv_loc.name) == Path(venv_name) @pytest.mark.dotvenv def test_venv_file_with_path(PipenvInstance, pypi): + """Tests virtualenv creation when a .venv file exists at the project root + and contains an absolute path. + """ with temp_environ(), PipenvInstance(chdir=True, pypi=pypi) as p: with TemporaryDirectory( - prefix='pipenv-', suffix="-test_venv" + prefix='pipenv-', suffix='-test_venv' ) as venv_path: - if "PIPENV_VENV_IN_PROJECT" in os.environ: - del os.environ["PIPENV_VENV_IN_PROJECT"] + if 'PIPENV_VENV_IN_PROJECT' in os.environ: + del os.environ['PIPENV_VENV_IN_PROJECT'] - file_path = os.path.join(p.path, ".venv") - with open(file_path, "w") as f: + file_path = os.path.join(p.path, '.venv') + with open(file_path, 'w') as f: f.write(venv_path.name) - c = p.pipenv("install") + c = p.pipenv('install') assert c.return_code == 0 venv_loc = Path(p.pipenv('--venv').out.strip()) - assert venv_loc.joinpath(".project").exists() + assert venv_loc.joinpath('.project').exists() assert venv_loc == Path(venv_path.name) From 86f9f4fccc6af40826f3f29eaf5cc9b90dc1b5b2 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Mon, 6 Aug 2018 12:36:40 -0700 Subject: [PATCH 09/56] add test for venv file with a relative path --- tests/integration/test_dot_venv.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/integration/test_dot_venv.py b/tests/integration/test_dot_venv.py index c7ab1bd4..259a78cd 100644 --- a/tests/integration/test_dot_venv.py +++ b/tests/integration/test_dot_venv.py @@ -90,3 +90,25 @@ def test_venv_file_with_path(PipenvInstance, pypi): venv_loc = Path(p.pipenv('--venv').out.strip()) assert venv_loc.joinpath('.project').exists() assert venv_loc == Path(venv_path.name) + + +@pytest.mark.dotvenv +def test_venv_file_with_relative_path(PipenvInstance, pypi): + """Tests virtualenv creation when a .venv file exists at the project root + and contains a relative path. + """ + with temp_environ(), PipenvInstance(chdir=True, pypi=pypi) as p: + if 'PIPENV_VENV_IN_PROJECT' in os.environ: + del os.environ['PIPENV_VENV_IN_PROJECT'] + + file_path = os.path.join(p.path, '.venv') + venv_path = 'foo/test-venv' + with open(file_path, 'w') as f: + f.write(venv_path) + + c = p.pipenv('install') + assert c.return_code == 0 + + venv_loc = Path(p.pipenv('--venv').out.strip()).resolve() + assert venv_loc.joinpath(".project").exists() + assert venv_loc == Path(venv_path).resolve() From 559903f00ebd1a90948c8bb10d9ee7268aa52149 Mon Sep 17 00:00:00 2001 From: Tzu-ping Chung Date: Fri, 10 Aug 2018 13:03:34 +0800 Subject: [PATCH 10/56] Improve "run" behavior on Windows Some Windows users are used to launch files without specifying a command, e.g.:: > my-script.py This works in the shell because Windows will automatically choose an command based on file association, and with newer Python versions, the Py Launcher (py.exe) automatically chooses the correct Python based on shebang-parsing. A similar syntax, unfortunately, does not currently work in Pipenv:: > pipenv run my-script.py Since my-script.py will be treated as a real application by the subprocess module. This patch catch Windows error 193 during subprocess initialization, and fall back to use COMSPEC (shell=True) when it happens, to provide better support for this use case. --- news/2718.behavior | 1 + pipenv/core.py | 25 ++++++++++++++++++++----- 2 files changed, 21 insertions(+), 5 deletions(-) create mode 100644 news/2718.behavior diff --git a/news/2718.behavior b/news/2718.behavior new file mode 100644 index 00000000..c00b1d46 --- /dev/null +++ b/news/2718.behavior @@ -0,0 +1 @@ +Fallback to shell mode if `run` fails with Windows error 193 to handle non-executable commands. This should improve usability on Windows, where some users run non-executable files without specifying a command, relying on Windows file association to choose the current command. diff --git a/pipenv/core.py b/pipenv/core.py index db60ee94..9a74bd9a 100644 --- a/pipenv/core.py +++ b/pipenv/core.py @@ -2087,15 +2087,30 @@ def inline_activate_virtual_environment(): os.environ["VIRTUAL_ENV"] = root -def do_run_nt(script): +def _launch_windows_subprocess(script): import subprocess command = system_which(script.command) options = {"universal_newlines": True} - if command: # Try to use CreateProcess directly if possible. - p = subprocess.Popen([command] + script.args, **options) - else: # Command not found, maybe this is a shell built-in? - p = subprocess.Popen(script.cmdify(), shell=True, **options) + + # Command not found, maybe this is a shell built-in? + if not command: + return subprocess.Popen(script.cmdify(), shell=True, **options) + + # Try to use CreateProcess directly if possible. + try: + return subprocess.Popen([command] + script.args, **options) + except WindowsError as e: + if e.winerror != 193: + raise + + # Windows error 193 "Command is not a valid Win32 application". + # Try shell mode to use Windows's file association for file launch. + return subprocess.Popen(script.cmdify(), shell=True, **options) + + +def do_run_nt(script): + p = _launch_windows_subprocess(script) p.communicate() sys.exit(p.returncode) From 87ab5e8a9388bf0a5dfeba3d95810a51b07eb39c Mon Sep 17 00:00:00 2001 From: Tzu-ping Chung Date: Fri, 10 Aug 2018 13:15:33 +0800 Subject: [PATCH 11/56] Better comment --- pipenv/core.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pipenv/core.py b/pipenv/core.py index 9a74bd9a..86e22711 100644 --- a/pipenv/core.py +++ b/pipenv/core.py @@ -2097,14 +2097,15 @@ def _launch_windows_subprocess(script): if not command: return subprocess.Popen(script.cmdify(), shell=True, **options) - # Try to use CreateProcess directly if possible. + # Try to use CreateProcess directly if possible. Specifically catch + # Windows error 193 "Command is not a valid Win32 application" to handle + # a "command" that is non-executable. See pypa/pipenv#2727. try: return subprocess.Popen([command] + script.args, **options) except WindowsError as e: if e.winerror != 193: raise - # Windows error 193 "Command is not a valid Win32 application". # Try shell mode to use Windows's file association for file launch. return subprocess.Popen(script.cmdify(), shell=True, **options) From e934ccc73ccf8f1c75a9cb8e5b4414493b06d227 Mon Sep 17 00:00:00 2001 From: Dan Ryan Date: Wed, 22 Aug 2018 02:24:51 -0400 Subject: [PATCH 12/56] Minor adjustments to get CI passing Signed-off-by: Dan Ryan --- pipenv/project.py | 12 +++++----- pipenv/utils.py | 5 ++++ run-tests.sh | 1 + tests/integration/conftest.py | 5 +++- tests/integration/test_dot_venv.py | 38 ++++++++++-------------------- 5 files changed, 28 insertions(+), 33 deletions(-) diff --git a/pipenv/project.py b/pipenv/project.py index 36161ecf..c6e9e4fa 100644 --- a/pipenv/project.py +++ b/pipenv/project.py @@ -34,6 +34,7 @@ from .utils import ( is_star, get_workon_home, is_virtual_environment, + looks_like_dir ) from .environments import ( PIPENV_MAX_DEPTH, @@ -271,13 +272,12 @@ class Project(object): name = self.virtualenv_name if self.project_directory: venv_path = os.path.join(self.project_directory, ".venv") - if os.path.isfile(venv_path): - with open(venv_path, "r") as f: - name = f.read() + if os.path.exists(venv_path) and not os.path.isdir(".venv"): + with io.open(venv_path, "r") as f: + name = f.read().strip() # Assume file's contents is a path if it contains slashes. - if '/' in name or '\\' in name: - return name - + if looks_like_dir(name): + return Path(name).absolute().as_posix() return str(get_workon_home().joinpath(name)) def get_installed_packages(self): diff --git a/pipenv/utils.py b/pipenv/utils.py index 21a1ec20..fa7a809b 100644 --- a/pipenv/utils.py +++ b/pipenv/utils.py @@ -1376,3 +1376,8 @@ def chdir(path): yield finally: os.chdir(prev_cwd) + + +def looks_like_dir(path): + seps = (sep for sep in (os.path.sep, os.path.altsep) if sep is not None) + return any(sep in path for sep in seps) diff --git a/run-tests.sh b/run-tests.sh index 1243e033..64d79648 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -6,6 +6,7 @@ set -eo pipefail export PYTHONIOENCODING="utf-8" export LANG=C.UTF-8 +export PIP_PROCESS_DEPENDENCY_LINKS="1" prefix() { sed "s/^/ $1: /" diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 9cb4b7b1..d8ac3686 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -15,6 +15,7 @@ if six.PY2: class ResourceWarning(Warning): pass +HAS_WARNED_GITHUB = False def check_internet(): try: @@ -40,13 +41,15 @@ def check_github_ssh(): res = True if c.return_code == 1 else False except Exception: pass - if not res: + global HAS_WARNED_GITHUB + if not res and not HAS_WARNED_GITHUB: warnings.warn( 'Cannot connect to GitHub via SSH', ResourceWarning ) warnings.warn( 'Will skip tests requiring SSH access to GitHub', ResourceWarning ) + HAS_WARNED_GITHUB = True return res diff --git a/tests/integration/test_dot_venv.py b/tests/integration/test_dot_venv.py index 259a78cd..82e39e39 100644 --- a/tests/integration/test_dot_venv.py +++ b/tests/integration/test_dot_venv.py @@ -43,13 +43,13 @@ def test_reuse_previous_venv(PipenvInstance, pypi): @pytest.mark.dotvenv -def test_venv_file_with_name(PipenvInstance, pypi): +@pytest.mark.parametrize('venv_name', ('test-venv', os.path.join('foo', 'test-venv'))) +def test_venv_file(venv_name, PipenvInstance, pypi): """Tests virtualenv creation when a .venv file exists at the project root and contains a venv name. """ with PipenvInstance(pypi=pypi, chdir=True) as p: file_path = os.path.join(p.path, '.venv') - venv_name = 'test-project' with open(file_path, 'w') as f: f.write(venv_name) @@ -63,9 +63,17 @@ def test_venv_file_with_name(PipenvInstance, pypi): c = p.pipenv('install') assert c.return_code == 0 - venv_loc = Path(p.pipenv('--venv').out.strip()) + c = p.pipenv('--venv') + assert c.return_code == 0 + venv_loc = Path(c.out.strip()).absolute() + assert venv_loc.exists() assert venv_loc.joinpath('.project').exists() - assert Path(venv_loc.name) == Path(venv_name) + venv_path = venv_loc.as_posix() + if os.path.sep in venv_name: + venv_expected_path = Path(p.path).joinpath(venv_name).absolute().as_posix() + else: + venv_expected_path = Path(workon_home.name).joinpath(venv_name).absolute().as_posix() + assert venv_path == venv_expected_path @pytest.mark.dotvenv @@ -90,25 +98,3 @@ def test_venv_file_with_path(PipenvInstance, pypi): venv_loc = Path(p.pipenv('--venv').out.strip()) assert venv_loc.joinpath('.project').exists() assert venv_loc == Path(venv_path.name) - - -@pytest.mark.dotvenv -def test_venv_file_with_relative_path(PipenvInstance, pypi): - """Tests virtualenv creation when a .venv file exists at the project root - and contains a relative path. - """ - with temp_environ(), PipenvInstance(chdir=True, pypi=pypi) as p: - if 'PIPENV_VENV_IN_PROJECT' in os.environ: - del os.environ['PIPENV_VENV_IN_PROJECT'] - - file_path = os.path.join(p.path, '.venv') - venv_path = 'foo/test-venv' - with open(file_path, 'w') as f: - f.write(venv_path) - - c = p.pipenv('install') - assert c.return_code == 0 - - venv_loc = Path(p.pipenv('--venv').out.strip()).resolve() - assert venv_loc.joinpath(".project").exists() - assert venv_loc == Path(venv_path).resolve() From b0085bbd97e353da9d859b574ea212abe8ef7e53 Mon Sep 17 00:00:00 2001 From: Dan Ryan Date: Wed, 22 Aug 2018 02:50:58 -0400 Subject: [PATCH 13/56] configure cert bundle Signed-off-by: Dan Ryan --- run-tests.sh | 1 + tests/integration/conftest.py | 3 +++ tests/integration/test_dot_venv.py | 4 +++- tests/pytest-pypi/pytest_pypi/certs.py | 2 +- 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/run-tests.sh b/run-tests.sh index 64d79648..8c8f6c58 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -7,6 +7,7 @@ set -eo pipefail export PYTHONIOENCODING="utf-8" export LANG=C.UTF-8 export PIP_PROCESS_DEPENDENCY_LINKS="1" +export REQUESTS_CA_BUNDLE=$(readlink -f ./tests/pytest-pypi/pytest_pypi/certs/cacert.pem) prefix() { sed "s/^/ $1: /" diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index d8ac3686..5f1925b1 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -10,11 +10,14 @@ from pipenv.vendor import requests from pipenv.vendor import six from pipenv.vendor import toml from pytest_pypi.app import prepare_packages as prepare_pypi_packages +from pytest_pypi.certs import where as certs_where if six.PY2: class ResourceWarning(Warning): pass +os.environ["REQUESTS_CA_BUNDLE"] = certs_where() + HAS_WARNED_GITHUB = False def check_internet(): diff --git a/tests/integration/test_dot_venv.py b/tests/integration/test_dot_venv.py index 82e39e39..53f5fb1d 100644 --- a/tests/integration/test_dot_venv.py +++ b/tests/integration/test_dot_venv.py @@ -94,7 +94,9 @@ def test_venv_file_with_path(PipenvInstance, pypi): c = p.pipenv('install') assert c.return_code == 0 + c = p.pipenv('--venv') + assert c.return_code == 0 + venv_loc = Path(c.out.strip()) - venv_loc = Path(p.pipenv('--venv').out.strip()) assert venv_loc.joinpath('.project').exists() assert venv_loc == Path(venv_path.name) diff --git a/tests/pytest-pypi/pytest_pypi/certs.py b/tests/pytest-pypi/pytest_pypi/certs.py index c099cfa2..83133ea0 100644 --- a/tests/pytest-pypi/pytest_pypi/certs.py +++ b/tests/pytest-pypi/pytest_pypi/certs.py @@ -15,7 +15,7 @@ import os.path def where(): """Return the preferred certificate bundle.""" # vendored bundle inside Requests - return os.path.join(os.path.dirname(__file__), 'certs', 'cacert.pem') + return os.path.join(os.path.abspath(os.path.dirname(__file__), 'certs', 'cacert.pem')) if __name__ == '__main__': print(where()) From e462444d157180f4024610514b07aa4c75d83c35 Mon Sep 17 00:00:00 2001 From: Dan Ryan Date: Wed, 22 Aug 2018 02:53:43 -0400 Subject: [PATCH 14/56] Export CA bundle properly Signed-off-by: Dan Ryan --- run-tests.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/run-tests.sh b/run-tests.sh index 8c8f6c58..614d5a41 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -7,7 +7,6 @@ set -eo pipefail export PYTHONIOENCODING="utf-8" export LANG=C.UTF-8 export PIP_PROCESS_DEPENDENCY_LINKS="1" -export REQUESTS_CA_BUNDLE=$(readlink -f ./tests/pytest-pypi/pytest_pypi/certs/cacert.pem) prefix() { sed "s/^/ $1: /" @@ -57,8 +56,10 @@ echo "$ pipenv run time pytest -v -n auto tests -m \"$TEST_SUITE\"" # PIPENV_PYTHON=2.7 pipenv run time pytest -v -n auto tests -m "$TEST_SUITE" | prefix 2.7 & # PIPENV_PYTHON=3.6 pipenv run time pytest -v -n auto tests -m "$TEST_SUITE" | prefix 3.6 # Better to run them sequentially. +export REQUESTS_CA_BUNDLE=$(readlink -f ./tests/pytest-pypi/pytest_pypi/certs/cacert.pem) PIPENV_PYTHON=2.7 pipenv run time pytest PIPENV_PYTHON=3.7 pipenv run time pytest +set -u REQUESTS_CA_BUNDLE # test revendoring pip3 install --upgrade invoke requests parver From 0e919dbd8986b8838546a40f2ba47801bcf62265 Mon Sep 17 00:00:00 2001 From: Dan Ryan Date: Wed, 22 Aug 2018 02:55:43 -0400 Subject: [PATCH 15/56] syntax... Signed-off-by: Dan Ryan --- tests/pytest-pypi/pytest_pypi/certs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/pytest-pypi/pytest_pypi/certs.py b/tests/pytest-pypi/pytest_pypi/certs.py index 83133ea0..f9e33870 100644 --- a/tests/pytest-pypi/pytest_pypi/certs.py +++ b/tests/pytest-pypi/pytest_pypi/certs.py @@ -15,7 +15,7 @@ import os.path def where(): """Return the preferred certificate bundle.""" # vendored bundle inside Requests - return os.path.join(os.path.abspath(os.path.dirname(__file__), 'certs', 'cacert.pem')) + return os.path.join(os.path.abspath(os.path.dirname(__file__)), 'certs', 'cacert.pem') if __name__ == '__main__': print(where()) From d5836ed3b059269aaac1f7ae7f7fd71980aa726b Mon Sep 17 00:00:00 2001 From: Dan Ryan Date: Wed, 22 Aug 2018 03:10:34 -0400 Subject: [PATCH 16/56] Just strip https from test mirror index Signed-off-by: Dan Ryan --- run-tests.sh | 2 -- tests/integration/conftest.py | 3 +-- tests/integration/test_install_basic.py | 4 ++++ 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/run-tests.sh b/run-tests.sh index 614d5a41..64d79648 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -56,10 +56,8 @@ echo "$ pipenv run time pytest -v -n auto tests -m \"$TEST_SUITE\"" # PIPENV_PYTHON=2.7 pipenv run time pytest -v -n auto tests -m "$TEST_SUITE" | prefix 2.7 & # PIPENV_PYTHON=3.6 pipenv run time pytest -v -n auto tests -m "$TEST_SUITE" | prefix 3.6 # Better to run them sequentially. -export REQUESTS_CA_BUNDLE=$(readlink -f ./tests/pytest-pypi/pytest_pypi/certs/cacert.pem) PIPENV_PYTHON=2.7 pipenv run time pytest PIPENV_PYTHON=3.7 pipenv run time pytest -set -u REQUESTS_CA_BUNDLE # test revendoring pip3 install --upgrade invoke requests parver diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 5f1925b1..76a429e0 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -10,16 +10,15 @@ from pipenv.vendor import requests from pipenv.vendor import six from pipenv.vendor import toml from pytest_pypi.app import prepare_packages as prepare_pypi_packages -from pytest_pypi.certs import where as certs_where if six.PY2: class ResourceWarning(Warning): pass -os.environ["REQUESTS_CA_BUNDLE"] = certs_where() HAS_WARNED_GITHUB = False + def check_internet(): try: # Kenneth represents the Internet LGTM. diff --git a/tests/integration/test_install_basic.py b/tests/integration/test_install_basic.py index ab6648f4..8ae644ec 100644 --- a/tests/integration/test_install_basic.py +++ b/tests/integration/test_install_basic.py @@ -51,6 +51,10 @@ def test_mirror_install(PipenvInstance, pypi): assert "pypi.org" not in mirror_url # This should sufficiently demonstrate the mirror functionality # since pypi.org is the default when PIPENV_TEST_INDEX is unset. + # we don't run the secure http-bin so we need to make sure this is not a https url + if any(host in mirror_url for host in ["localhost", "127.0.0.1"]): + if mirror_url.startswith("https://"): + mirror_url = mirror_url.replace("https://", "http://") c = p.pipenv("install requests --pypi-mirror {0}".format(mirror_url)) assert c.return_code == 0 # Ensure the --pypi-mirror parameter hasn't altered the Pipfile or Pipfile.lock sources From 5ae2433bcf0728b98101f69675b9f07169e383d8 Mon Sep 17 00:00:00 2001 From: Dan Ryan Date: Wed, 22 Aug 2018 03:18:03 -0400 Subject: [PATCH 17/56] now does it work? Signed-off-by: Dan Ryan --- tests/integration/test_install_basic.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tests/integration/test_install_basic.py b/tests/integration/test_install_basic.py index 8ae644ec..c04dc3f6 100644 --- a/tests/integration/test_install_basic.py +++ b/tests/integration/test_install_basic.py @@ -44,17 +44,13 @@ def test_basic_install(PipenvInstance, pypi): @pytest.mark.install @flaky def test_mirror_install(PipenvInstance, pypi): - with temp_environ(), PipenvInstance(chdir=True) as p: + with temp_environ(), PipenvInstance(chdir=True, pypi=pypi) as p: mirror_url = os.environ.pop( "PIPENV_TEST_INDEX", "https://pypi.python.org/simple" ) assert "pypi.org" not in mirror_url # This should sufficiently demonstrate the mirror functionality # since pypi.org is the default when PIPENV_TEST_INDEX is unset. - # we don't run the secure http-bin so we need to make sure this is not a https url - if any(host in mirror_url for host in ["localhost", "127.0.0.1"]): - if mirror_url.startswith("https://"): - mirror_url = mirror_url.replace("https://", "http://") c = p.pipenv("install requests --pypi-mirror {0}".format(mirror_url)) assert c.return_code == 0 # Ensure the --pypi-mirror parameter hasn't altered the Pipfile or Pipfile.lock sources From 952653d2b75df3c5be6382e2cf20988881736b34 Mon Sep 17 00:00:00 2001 From: David Baumgold Date: Tue, 21 Aug 2018 22:06:44 +0200 Subject: [PATCH 18/56] GitHub has a capital H --- docs/_templates/hacks.html | 2 +- pipenv/cli.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/_templates/hacks.html b/docs/_templates/hacks.html index 875abaac..0ec542fa 100644 --- a/docs/_templates/hacks.html +++ b/docs/_templates/hacks.html @@ -60,7 +60,7 @@ - +