From d49c35de78661b19ced7c428ded1a5e33403bc12 Mon Sep 17 00:00:00 2001 From: gzagatti Date: Thu, 2 Aug 2018 11:59:42 -0400 Subject: [PATCH 01/23] Improves message when dependencies could not be resolved. --- pipenv/utils.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pipenv/utils.py b/pipenv/utils.py index 1f0f4ef4..f16d9a16 100644 --- a/pipenv/utils.py +++ b/pipenv/utils.py @@ -310,11 +310,13 @@ def actually_resolve_deps( click_echo( "{0}: Your dependencies could not be resolved. You likely have a " "mismatch in your sub-dependencies.\n " - "You can use {1} to bypass this mechanism, then run {2} to inspect " - "the situation.\n " - "Hint: try {3} if it is a pre-release dependency." + "First try clearing your dependency cache with {1} and trying again.\n " + "Alternatively, you can use {2} to bypass this mechanism, then run " + "{3} to inspect the situation.\n " + "Hint: try {4} if it is a pre-release dependency." "".format( crayons.red("Warning", bold=True), + crayons.red("$ pipenv lock --clear"), crayons.red("$ pipenv install --skip-lock"), crayons.red("$ pipenv graph"), crayons.red("$ pipenv lock --pre"), From 42de3d15edce3211b5e3ffed6ff391b6ca3b7d70 Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Thu, 2 Aug 2018 00:56:09 -0700 Subject: [PATCH 02/23] 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 9070a6b92d7bc1fdcae8d7ac02d369a2ffacfec1 Mon Sep 17 00:00:00 2001 From: Jeremy Spencer Date: Fri, 3 Aug 2018 11:14:58 -0400 Subject: [PATCH 03/23] Added an example to README.md for installing from git --- README.md | 9 +++++++++ news/2685.doc | 1 + 2 files changed, 10 insertions(+) create mode 100644 news/2685.doc diff --git a/README.md b/README.md index 9c2f00b3..b552925a 100644 --- a/README.md +++ b/README.md @@ -216,6 +216,15 @@ Install packages: To activate this project's virtualenv, run the following: $ pipenv shell +Install from git: + + $ pipenv install -e git+https://github.com/requests/requests.git@v2.19.1#egg=requests + Installing -e git+https://github.com/requests/requests.git@v2.19.1#egg=requests… + ... + Adding -e git+https://github.com/requests/requests.git@v2.19.1#egg=requests to Pipfile's [packages]... + +You can also change the tag/ref (or exclude to get the latest version) by adding @version-or-tag before #egg=project_name + Install a dev dependency: $ pipenv install pytest --dev diff --git a/news/2685.doc b/news/2685.doc new file mode 100644 index 00000000..6f2a0aff --- /dev/null +++ b/news/2685.doc @@ -0,0 +1 @@ +Added simple example to README.md for installing from git. From 484340b8294fdb9a8a5a39f01832b463281572e7 Mon Sep 17 00:00:00 2001 From: gzagatti Date: Fri, 3 Aug 2018 12:08:57 -0400 Subject: [PATCH 04/23] Fixes grammar. --- pipenv/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pipenv/utils.py b/pipenv/utils.py index f16d9a16..2187ea68 100644 --- a/pipenv/utils.py +++ b/pipenv/utils.py @@ -310,7 +310,7 @@ def actually_resolve_deps( click_echo( "{0}: Your dependencies could not be resolved. You likely have a " "mismatch in your sub-dependencies.\n " - "First try clearing your dependency cache with {1} and trying again.\n " + "First try clearing your dependency cache with {1}, then try the original command again.\n " "Alternatively, you can use {2} to bypass this mechanism, then run " "{3} to inspect the situation.\n " "Hint: try {4} if it is a pre-release dependency." From fed71c78cf4fc3b6fa9ec7fed9f5b8b2cde21bcc Mon Sep 17 00:00:00 2001 From: Dan Ryan Date: Sat, 4 Aug 2018 19:33:26 -0400 Subject: [PATCH 05/23] 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 06/23] 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 07/23] 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 08/23] 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 09/23] 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 10/23] 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 11/23] 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 12/23] 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 a3162945be79182d0a4b4a7c140970dc340788fb Mon Sep 17 00:00:00 2001 From: Jeremy Spencer Date: Sun, 12 Aug 2018 16:15:17 -0400 Subject: [PATCH 13/23] mend --- README.md | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index b552925a..b6ef6e56 100644 --- a/README.md +++ b/README.md @@ -216,14 +216,30 @@ Install packages: To activate this project's virtualenv, run the following: $ pipenv shell -Install from git: +Installing from git: - $ pipenv install -e git+https://github.com/requests/requests.git@v2.19.1#egg=requests - Installing -e git+https://github.com/requests/requests.git@v2.19.1#egg=requests… - ... +You can install packages with pipenv from git and other version control systems using URLs formatted according to the following rule: + +``` + +:////@# +``` + +The only optional section is the `@` section. When using git over SSH, you may use the shorthand vcs and scheme alias `git+git@:/@#`. Note that this is translated to `git+ssh://git@` when parsed. + +Valid values for `` include `git`, `bzr`, `svn`, and `hg`. Valid values for `` include `http,`, `https`, `ssh`, and `file`. In specific cases you also have access to other schemes: `svn` may be combined with `svn` as a scheme, and `bzr` can be combined with `sftp` and `lp`. + +Note that it is **strongly recommended** that you install any version-controlled dependencies in editable mode in order to ensure that dependency resolution can be performed with an up to date copy of the repository each time it is performed, and that it includes all known dependencies. + +Below is an example usage which installs the git repository located at `https://github.com/requests/requests.git` from tag `v2.19.1` as package name `requests`: + +```console + $ pipenv install -e git+https://github.com/requests/requests.git@v2.19#egg=requests + Creating a Pipfile for this project... + Installing -e git+https://github.com/requests/requests.git@v2.19.1#egg=requests... + [...snipped...] Adding -e git+https://github.com/requests/requests.git@v2.19.1#egg=requests to Pipfile's [packages]... - -You can also change the tag/ref (or exclude to get the latest version) by adding @version-or-tag before #egg=project_name + [...] +``` Install a dev dependency: From 1188a3de34159b54cb747b346b5770e36e44e6d5 Mon Sep 17 00:00:00 2001 From: Jeremy Spencer Date: Mon, 13 Aug 2018 08:51:39 -0400 Subject: [PATCH 14/23] Updated for PR #2702. Added in request from user @uranusjr for pip documentation on vcs support and @slhck request for more consistent formatting of code blocks and more explict instructions for editable mode when installing from vcs --- README.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index b6ef6e56..16b72034 100644 --- a/README.md +++ b/README.md @@ -220,26 +220,24 @@ Installing from git: You can install packages with pipenv from git and other version control systems using URLs formatted according to the following rule: -``` +:////@# -``` The only optional section is the `@` section. When using git over SSH, you may use the shorthand vcs and scheme alias `git+git@:/@#`. Note that this is translated to `git+ssh://git@` when parsed. Valid values for `` include `git`, `bzr`, `svn`, and `hg`. Valid values for `` include `http,`, `https`, `ssh`, and `file`. In specific cases you also have access to other schemes: `svn` may be combined with `svn` as a scheme, and `bzr` can be combined with `sftp` and `lp`. -Note that it is **strongly recommended** that you install any version-controlled dependencies in editable mode in order to ensure that dependency resolution can be performed with an up to date copy of the repository each time it is performed, and that it includes all known dependencies. +Note that it is **strongly recommended** that you install any version-controlled dependencies in editable mode, using `pipenv install -e`, in order to ensure that dependency resolution can be performed with an up to date copy of the repository each time it is performed, and that it includes all known dependencies. Below is an example usage which installs the git repository located at `https://github.com/requests/requests.git` from tag `v2.19.1` as package name `requests`: -```console $ pipenv install -e git+https://github.com/requests/requests.git@v2.19#egg=requests Creating a Pipfile for this project... Installing -e git+https://github.com/requests/requests.git@v2.19.1#egg=requests... [...snipped...] Adding -e git+https://github.com/requests/requests.git@v2.19.1#egg=requests to Pipfile's [packages]... [...] -``` + +You can read more about [pip's implementation of vcs support here](https://pip.pypa.io/en/stable/reference/pip_install/#vcs-support). Install a dev dependency: From 438fc6039777e23f4918882d1dbc74ec45f52784 Mon Sep 17 00:00:00 2001 From: Oliver Newman Date: Wed, 15 Aug 2018 16:22:45 -0700 Subject: [PATCH 15/23] Move misformatted comments Black moved a couple comments to some funky places; this moves them back to the lines to which they refer. --- pipenv/progress.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/pipenv/progress.py b/pipenv/progress.py index 4cea195c..c126fe73 100644 --- a/pipenv/progress.py +++ b/pipenv/progress.py @@ -113,9 +113,10 @@ class Bar(object): self.etadisp = self.format_time(self.eta) x = int(self.width * progress / self.expected_size) if not self.hide: - if (progress % self.every) == 0 or ( # True every "every" updates - progress == self.expected_size - ): # And when we're done + if ( + progress % self.every == 0 # True every "every" updates + or progress == self.expected_size # And when we're done + ): STREAM.write( BAR_TEMPLATE % ( @@ -208,9 +209,10 @@ def mill(it, label="", hide=None, expected_size=None, every=1): def _show(_i): if not hide: - if (_i % every) == 0 or ( - _i == count - ): # True every "every" updates # And when we're done + if ( + _i % every == 0 # True every "every" updates + or _i == count # And when we're done + ): STREAM.write(MILL_TEMPLATE % (label, _mill_char(_i), _i, count)) STREAM.flush() From a4ad13e52b8f0e4499196d1e8bc17fcd8be9b868 Mon Sep 17 00:00:00 2001 From: Dan Ryan Date: Fri, 17 Aug 2018 16:34:28 -0400 Subject: [PATCH 16/23] Update readme images, port readme add news Signed-off-by: Dan Ryan --- README.md | 6 +++--- docs/basics.rst | 23 ++++++++++++++++++----- news/2696.trivial | 1 + 3 files changed, 22 insertions(+), 8 deletions(-) create mode 100644 news/2696.trivial diff --git a/README.md b/README.md index 16b72034..5a5d4ca5 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ Pipenv: Python Development Workflow for Humans ============================================== -[![image](https://img.shields.io/pypi/v/pipenv.svg)](https://pypi.python.org/pypi/pipenv) -[![image](https://img.shields.io/pypi/l/pipenv.svg)](https://pypi.python.org/pypi/pipenv) +[![image](https://img.shields.io/pypi/v/pipenv.svg)](https://python.org/pypi/pipenv) +[![image](https://img.shields.io/pypi/l/pipenv.svg)](https://python.org/pypi/pipenv) [![image](https://badge.buildkite.com/79c7eccf056b17c3151f3c4d0e4c4b8b724539d84f1e037b9b.svg?branch=master)](https://code.kennethreitz.org/source/pipenv/) -[![image](https://img.shields.io/pypi/pyversions/pipenv.svg)](https://pypi.python.org/pypi/pipenv) +[![image](https://img.shields.io/pypi/pyversions/pipenv.svg)](https://python.org/pypi/pipenv) [![image](https://img.shields.io/badge/Say%20Thanks-!-1EAEDB.svg)](https://saythanks.io/to/kennethreitz) ------------------------------------------------------------------------ diff --git a/docs/basics.rst b/docs/basics.rst index a38d3403..e6afea3f 100644 --- a/docs/basics.rst +++ b/docs/basics.rst @@ -334,17 +334,30 @@ If you experience issues with ``$ pipenv shell``, just check the ``PIPENV_SHELL` ☤ A Note about VCS Dependencies ------------------------------- -Pipenv will resolve the sub–dependencies of VCS dependencies, but only if they are installed in editable mode:: +You can install packages with pipenv from git and other version control systems using URLs formatted according to the following rule:: - $ pipenv install -e git+https://github.com/requests/requests.git#egg=requests + +:////@# + +The only optional section is the ``@`` section. When using git over SSH, you may use the shorthand vcs and scheme alias ``git+git@:/@#``. Note that this is translated to ``git+ssh://git@`` when parsed. + +Note that it is **strongly recommended** that you install any version-controlled dependencies in editable mode, using ``pipenv install -e``, in order to ensure that dependency resolution can be performed with an up to date copy of the repository each time it is performed, and that it includes all known dependencies. + +Below is an example usage which installs the git repository located at ``https://github.com/requests/requests.git`` from tag ``v2.19.1`` as package name ``requests``:: + + $ pipenv install -e git+https://github.com/requests/requests.git@v2.19#egg=requests + Creating a Pipfile for this project... + Installing -e git+https://github.com/requests/requests.git@v2.19.1#egg=requests... + [...snipped...] + Adding -e git+https://github.com/requests/requests.git@v2.19.1#egg=requests to Pipfile's [packages]... + [...] $ cat Pipfile [packages] - requests = {git = "https://github.com/requests/requests.git", editable=true} + requests = {git = "https://github.com/requests/requests.git", editable = true, ref = "2.19.1"} -If editable is not true, sub–dependencies will not be resolved. +Valid values for ```` include ``git``, ``bzr``, ``svn``, and ``hg``. Valid values for ```` include ``http``, ``https``, ``ssh``, and ``file``. In specific cases you also have access to other schemes: ``svn`` may be combined with ``svn`` as a scheme, and ``bzr`` can be combined with ``sftp`` and ``lp``. -For more information about other options available when specifying VCS dependencies, please check the `Pipfile spec `__. +You can read more about pip's implementation of VCS support `here `_. For more information about other options available when specifying VCS dependencies, please check the `Pipfile spec `_. ☤ Pipfile.lock Security Features diff --git a/news/2696.trivial b/news/2696.trivial new file mode 100644 index 00000000..dc68eca0 --- /dev/null +++ b/news/2696.trivial @@ -0,0 +1 @@ +Added additional information to error messaging during failed resolution. From e934ccc73ccf8f1c75a9cb8e5b4414493b06d227 Mon Sep 17 00:00:00 2001 From: Dan Ryan Date: Wed, 22 Aug 2018 02:24:51 -0400 Subject: [PATCH 17/23] 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 18/23] 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 19/23] 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 20/23] 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 21/23] 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 22/23] 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 23/23] 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 @@ - +