From 08c6739c9b28791f579c92793a7a970d1be06f19 Mon Sep 17 00:00:00 2001 From: gtalarico Date: Tue, 8 May 2018 22:33:21 -0400 Subject: [PATCH 01/14] Espace spaces on cmder shell path - Fixes #2115 --- pipenv/patched/pew/pew.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pipenv/patched/pew/pew.py b/pipenv/patched/pew/pew.py index 2d3889a0..91f313c1 100644 --- a/pipenv/patched/pew/pew.py +++ b/pipenv/patched/pew/pew.py @@ -184,7 +184,8 @@ def fork_bash(env, cwd): def fork_cmder(env, cwd): shell_cmd = ['cmd'] - cmderrc_path = r'%CMDER_ROOT%\vendor\init.bat' + escaped_cmder_root = os.environ['CMDER_ROOT'].replace(' ', '^ ') + cmderrc_path = r'{0}\vendor\init.bat'.format(escaped_cmder_root) if expandpath(cmderrc_path).exists(): shell_cmd += ['/k', cmderrc_path] if cwd: From 51a0fbf72ba29ff1380fb0d87839a74811829a7a Mon Sep 17 00:00:00 2001 From: gtalarico Date: Wed, 9 May 2018 01:00:30 -0400 Subject: [PATCH 02/14] Added vendor patch --- .../patched/pew-cmder-root-space-escape-fix.patch | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 tasks/vendoring/patches/patched/pew-cmder-root-space-escape-fix.patch diff --git a/tasks/vendoring/patches/patched/pew-cmder-root-space-escape-fix.patch b/tasks/vendoring/patches/patched/pew-cmder-root-space-escape-fix.patch new file mode 100644 index 00000000..eb0e3d82 --- /dev/null +++ b/tasks/vendoring/patches/patched/pew-cmder-root-space-escape-fix.patch @@ -0,0 +1,14 @@ +diff --git a/pipenv/patched/pew/pew.py b/pipenv/patched/pew/pew.py +index 2d3889a0..91f313c1 100644 +--- a/pipenv/patched/pew/pew.py ++++ b/pipenv/patched/pew/pew.py +@@ -184,7 +184,8 @@ def fork_bash(env, cwd): + + def fork_cmder(env, cwd): + shell_cmd = ['cmd'] +- cmderrc_path = r'%CMDER_ROOT%\vendor\init.bat' ++ escaped_cmder_root = os.environ['CMDER_ROOT'].replace(' ', '^ ') ++ cmderrc_path = r'{0}\vendor\init.bat'.format(escaped_cmder_root) + if expandpath(cmderrc_path).exists(): + shell_cmd += ['/k', cmderrc_path] + if cwd: From 7b9b19c723af6175794b9a99f37840cbbb096d63 Mon Sep 17 00:00:00 2001 From: Dan Ryan Date: Tue, 15 May 2018 18:07:19 -0400 Subject: [PATCH 03/14] Lock vcs refs properly - Still need to actually run setup.py Signed-off-by: Dan Ryan --- pipenv/_compat.py | 19 ++++++++++++ pipenv/core.py | 74 ++++++++++++++++++++++++++++++++++++++++------- pipenv/project.py | 36 +++++++++++------------ pipenv/utils.py | 7 +++++ 4 files changed, 108 insertions(+), 28 deletions(-) diff --git a/pipenv/_compat.py b/pipenv/_compat.py index 14326813..8ccf025a 100644 --- a/pipenv/_compat.py +++ b/pipenv/_compat.py @@ -5,6 +5,7 @@ Exposes a standard API that enables compatibility across python versions, operating systems, etc. """ import functools +import importlib import io import os import six @@ -50,6 +51,24 @@ if six.PY2: class ResourceWarning(Warning): pass +# -*- coding=utf-8 -*- + + +def pip_import(module_path, subimport=None, old_path=None): + internal = 'pip._internal.{0}'.format(module_path) + old_path = old_path or module_path + pip9 = 'pip.{0}'.format(old_path) + try: + _tmp = importlib.import_module(internal) + except ImportError: + _tmp = importlib.import_module(pip9) + if subimport: + return getattr(_tmp, subimport, _tmp) + return _tmp + + +vcs = pip_import('vcs', 'VcsSupport') + class TemporaryDirectory(object): """Create and return a temporary directory. This has the same diff --git a/pipenv/core.py b/pipenv/core.py index 92ae3293..dec3e103 100644 --- a/pipenv/core.py +++ b/pipenv/core.py @@ -16,6 +16,7 @@ import crayons import dotenv import delegator from .vendor import pexpect +from first import first import pipfile from blindspin import spinner from requests.packages import urllib3 @@ -46,9 +47,11 @@ from .utils import ( is_star, rmtree, split_argument, + extract_uri_from_vcs_dep, ) from ._compat import ( TemporaryDirectory, + vcs ) from .import pep508checker, progress from .environments import ( @@ -1068,18 +1071,45 @@ def do_lock( pip_freeze = delegator.run( '{0} freeze'.format(escape_grouped_arguments(which_pip(allow_global=system))) ).out + vcs_registry = vcs() if vcs_deps: + vcs_uri_map = {extract_uri_from_vcs_dep(v): k for k, v in project.vcs_dev_packages.items()} for line in pip_freeze.strip().split('\n'): # if the line doesn't match a vcs dependency in the Pipfile, # ignore it - if not any(dep in line for dep in vcs_deps): + _vcs_match = first(_uri for _uri in vcs_uri_map.keys() if _uri in line) + if not _vcs_match: continue + pipfile_name = vcs_uri_map[_vcs_match] + src_loc = os.path.join(project.virtualenv_location, pipfile_name) + pipfile_rev = project.vcs_packages[pipfile_name].get('ref', None) + _pip_uri = line.lstrip('-e ') + backend_name = str(_pip_uri.split('+', 1)[0]) + backend = vcs_registry._registry[first(b for b in vcs_registry if b == backend_name)] + __vcs = backend(url=_pip_uri) + __target_rev = __vcs.make_rev_options(pipfile_rev) + try: installed = convert_deps_from_pip(line) - name = list(installed.keys())[0] - if is_vcs(installed[name]): - lockfile['develop'].update(installed) + lock_name = first(installed.keys()) + locked_rev = None + lockfile_src_loc = os.path.join(project.virtualenv_location, lock_name) + paths = set([loc for loc in [src_loc, lockfile_src_loc] if os.path.exists(loc)]) + paths = list(paths) + if paths: + # If the pipfile rev and the installed rev don't match + if pipfile_rev != __vcs.get_url_rev()[1]: + for _p in paths: + __vcs.update(_p, __target_rev) + locked_rev = __vcs.get_revision(_p) + else: + __vcs.obtain(src_loc) + __vcs.update(src_loc, __target_rev) + locked_rev = __vcs.get_revision(src_loc) + if is_vcs(installed[lock_name]): + installed[lock_name]['ref'] = locked_rev + lockfile['develop'].update({pipfile_name: installed[lock_name]}) except IndexError: pass if write: @@ -1132,21 +1162,45 @@ def do_lock( # TODO: be smarter about this. vcs_deps = convert_deps_to_pip(project.vcs_packages, project, r=False) if vcs_deps: + vcs_uri_map = {extract_uri_from_vcs_dep(v): k for k, v in project.vcs_packages.items()} for line in pip_freeze.strip().split('\n'): # if the line doesn't match a vcs dependency in the Pipfile, # ignore it - if not any(dep in line for dep in vcs_deps): + _vcs_match = first(_uri for _uri in vcs_uri_map.keys() if _uri in line) + if not _vcs_match: continue + pipfile_name = vcs_uri_map[_vcs_match] + src_loc = os.path.join(project.virtualenv_location, pipfile_name) + pipfile_rev = project.vcs_packages[pipfile_name].get('ref', None) + _pip_uri = line.lstrip('-e ') + backend_name = str(_pip_uri.split('+', 1)[0]) + backend = vcs_registry._registry[first(b for b in vcs_registry if b == backend_name)] + __vcs = backend(url=_pip_uri) + __target_rev = __vcs.make_rev_options(pipfile_rev) + try: installed = convert_deps_from_pip(line) - name = list(installed.keys())[0] - if is_vcs(installed[name]): - # Convert name to PEP 423 name. - installed = {pep423_name(name): installed[name]} - lockfile['default'].update(installed) + lock_name = first(installed.keys()) + locked_rev = None + lockfile_src_loc = os.path.join(project.virtualenv_location, lock_name) + paths = [loc for loc in [src_loc, lockfile_src_loc] if os.path.exists(loc)] + if paths: + # If the pipfile rev and the installed rev don't match + if pipfile_rev != __vcs.get_url_rev()[1]: + for _p in paths: + __vcs.update(_p, __target_rev) + locked_rev = __vcs.get_revision(_p) + else: + __vcs.obtain(src_loc) + __vcs.update(src_loc, __target_rev) + locked_rev = __vcs.get_revision(src_loc) + if is_vcs(installed[lock_name]): + installed[lock_name]['ref'] = locked_rev + lockfile['default'].update({pipfile_name: installed[lock_name]}) except IndexError: pass + # Support for --keep-outdated… if keep_outdated: for section_name, section in ( diff --git a/pipenv/project.py b/pipenv/project.py index 2294d43f..76bcdadc 100644 --- a/pipenv/project.py +++ b/pipenv/project.py @@ -497,41 +497,41 @@ class Project(object): def lockfile_content(self): return self.load_lockfile() - @property - def editable_packages(self): + def _get_editable_packages(self, dev=False): + section = 'dev-packages' if dev else 'packages' packages = { k: v - for k, v in self.parsed_pipfile.get('packages', {}).items() + for k, v in self.parsed_pipfile.get(section, {}).items() if is_editable(v) } return packages - @property - def editable_dev_packages(self): + def _get_vcs_packages(self, dev=False): + section = 'dev-packages' if dev else 'packages' packages = { k: v - for k, v in self.parsed_pipfile.get('dev-packages', {}).items() - if is_editable(v) + for k, v in self.parsed_pipfile.get(section, {}).items() + if is_vcs(v) or is_vcs(k) } - return packages + return packages or {} + + @property + def editable_packages(self): + return self._get_editable_packages(dev=False) + + @property + def editable_dev_packages(self): + return self._get_editable_packages(dev=True) @property def vcs_packages(self): """Returns a list of VCS packages, for not pip-tools to consume.""" - ps = {} - for k, v in self.parsed_pipfile.get('packages', {}).items(): - if is_vcs(v) or is_vcs(k): - ps.update({k: v}) - return ps + return self._get_vcs_packages(dev=False) @property def vcs_dev_packages(self): """Returns a list of VCS packages, for not pip-tools to consume.""" - ps = {} - for k, v in self.parsed_pipfile.get('dev-packages', {}).items(): - if is_vcs(v) or is_vcs(k): - ps.update({k: v}) - return ps + return self._get_vcs_packages(dev=True) @property def all_packages(self): diff --git a/pipenv/utils.py b/pipenv/utils.py index 973b1c83..2ba75154 100644 --- a/pipenv/utils.py +++ b/pipenv/utils.py @@ -1358,3 +1358,10 @@ def safe_expandvars(value): if isinstance(value, six.string_types): return os.path.expandvars(value) return value + + +def extract_uri_from_vcs_dep(dep): + valid_keys = VCS_LIST + ('uri', 'file') + if hasattr(dep, 'keys'): + return first(dep[k] for k in valid_keys if k in dep) or None + return None From f1550d84803caa6a1a924267a3c67dd14da0bbe1 Mon Sep 17 00:00:00 2001 From: Dan Ryan Date: Wed, 16 May 2018 17:28:51 -0400 Subject: [PATCH 04/14] Lock vcs deps to exact commit with dependencies - Manually obtain and update VCS repository with exact commit - Always store exact commit in the lockfile - Fixes #2180, #1690, #1611, #2096 Signed-off-by: Dan Ryan --- pipenv/core.py | 105 +++++--------------------- pipenv/utils.py | 61 +++++++++++++++ tests/integration/test_install_uri.py | 26 +++++++ 3 files changed, 107 insertions(+), 85 deletions(-) diff --git a/pipenv/core.py b/pipenv/core.py index dec3e103..e95d4747 100644 --- a/pipenv/core.py +++ b/pipenv/core.py @@ -1000,6 +1000,7 @@ def do_lock( ): """Executes the freeze functionality.""" from notpip._vendor.distlib.markers import Evaluator + from .utils import get_vcs_deps allowed_marker_keys = ['markers'] + [k for k in Evaluator.allowed_values.keys()] cached_lockfile = {} if not pre: @@ -1036,6 +1037,9 @@ def do_lock( if dev_package in project.packages: dev_packages[dev_package] = project.packages[dev_package] # Resolve dev-package dependencies, with pip-tools. + pip_freeze = delegator.run( + '{0} freeze'.format(escape_grouped_arguments(which_pip(allow_global=system))) + ).out deps = convert_deps_to_pip( dev_packages, project, r=False, include_index=True ) @@ -1067,51 +1071,14 @@ def do_lock( lockfile['develop'][dep['name']]['markers'] = dep['markers'] # Add refs for VCS installs. # TODO: be smarter about this. - vcs_deps = convert_deps_to_pip(project.vcs_dev_packages, project, r=False) - pip_freeze = delegator.run( - '{0} freeze'.format(escape_grouped_arguments(which_pip(allow_global=system))) - ).out - vcs_registry = vcs() - if vcs_deps: - vcs_uri_map = {extract_uri_from_vcs_dep(v): k for k, v in project.vcs_dev_packages.items()} - for line in pip_freeze.strip().split('\n'): - # if the line doesn't match a vcs dependency in the Pipfile, - # ignore it - _vcs_match = first(_uri for _uri in vcs_uri_map.keys() if _uri in line) - if not _vcs_match: - continue - - pipfile_name = vcs_uri_map[_vcs_match] - src_loc = os.path.join(project.virtualenv_location, pipfile_name) - pipfile_rev = project.vcs_packages[pipfile_name].get('ref', None) - _pip_uri = line.lstrip('-e ') - backend_name = str(_pip_uri.split('+', 1)[0]) - backend = vcs_registry._registry[first(b for b in vcs_registry if b == backend_name)] - __vcs = backend(url=_pip_uri) - __target_rev = __vcs.make_rev_options(pipfile_rev) - - try: - installed = convert_deps_from_pip(line) - lock_name = first(installed.keys()) - locked_rev = None - lockfile_src_loc = os.path.join(project.virtualenv_location, lock_name) - paths = set([loc for loc in [src_loc, lockfile_src_loc] if os.path.exists(loc)]) - paths = list(paths) - if paths: - # If the pipfile rev and the installed rev don't match - if pipfile_rev != __vcs.get_url_rev()[1]: - for _p in paths: - __vcs.update(_p, __target_rev) - locked_rev = __vcs.get_revision(_p) - else: - __vcs.obtain(src_loc) - __vcs.update(src_loc, __target_rev) - locked_rev = __vcs.get_revision(src_loc) - if is_vcs(installed[lock_name]): - installed[lock_name]['ref'] = locked_rev - lockfile['develop'].update({pipfile_name: installed[lock_name]}) - except IndexError: - pass + vcs_dev_lines, vcs_dev_lockfiles = get_vcs_deps(project, pip_freeze, which=which, verbose=verbose, clear=clear, pre=pre, allow_global=system, dev=True) + for lf in vcs_dev_lockfiles: + try: + name = first(lf.keys()) + except AttributeError: + continue + if hasattr(lf[name], 'keys'): + lockfile['develop'].update(lf) if write: # Alert the user of progress. click.echo( @@ -1160,46 +1127,14 @@ def do_lock( lockfile['default'][dep['name']]['markers'] = dep['markers'] # Add refs for VCS installs. # TODO: be smarter about this. - vcs_deps = convert_deps_to_pip(project.vcs_packages, project, r=False) - if vcs_deps: - vcs_uri_map = {extract_uri_from_vcs_dep(v): k for k, v in project.vcs_packages.items()} - for line in pip_freeze.strip().split('\n'): - # if the line doesn't match a vcs dependency in the Pipfile, - # ignore it - _vcs_match = first(_uri for _uri in vcs_uri_map.keys() if _uri in line) - if not _vcs_match: - continue - - pipfile_name = vcs_uri_map[_vcs_match] - src_loc = os.path.join(project.virtualenv_location, pipfile_name) - pipfile_rev = project.vcs_packages[pipfile_name].get('ref', None) - _pip_uri = line.lstrip('-e ') - backend_name = str(_pip_uri.split('+', 1)[0]) - backend = vcs_registry._registry[first(b for b in vcs_registry if b == backend_name)] - __vcs = backend(url=_pip_uri) - __target_rev = __vcs.make_rev_options(pipfile_rev) - - try: - installed = convert_deps_from_pip(line) - lock_name = first(installed.keys()) - locked_rev = None - lockfile_src_loc = os.path.join(project.virtualenv_location, lock_name) - paths = [loc for loc in [src_loc, lockfile_src_loc] if os.path.exists(loc)] - if paths: - # If the pipfile rev and the installed rev don't match - if pipfile_rev != __vcs.get_url_rev()[1]: - for _p in paths: - __vcs.update(_p, __target_rev) - locked_rev = __vcs.get_revision(_p) - else: - __vcs.obtain(src_loc) - __vcs.update(src_loc, __target_rev) - locked_rev = __vcs.get_revision(src_loc) - if is_vcs(installed[lock_name]): - installed[lock_name]['ref'] = locked_rev - lockfile['default'].update({pipfile_name: installed[lock_name]}) - except IndexError: - pass + _vcs_deps, vcs_lockfiles = get_vcs_deps(project, pip_freeze, which=which, verbose=verbose, clear=clear, pre=pre, allow_global=system, dev=False) + for lf in vcs_lockfiles: + try: + name = first(lf.keys()) + except AttributeError: + continue + if hasattr(lf[name], 'keys'): + lockfile['default'].update(lf) # Support for --keep-outdated… if keep_outdated: diff --git a/pipenv/utils.py b/pipenv/utils.py index 2ba75154..9ad18c7b 100644 --- a/pipenv/utils.py +++ b/pipenv/utils.py @@ -1365,3 +1365,64 @@ def extract_uri_from_vcs_dep(dep): if hasattr(dep, 'keys'): return first(dep[k] for k in valid_keys if k in dep) or None return None + + +def install_or_update_vcs(vcs_obj, src_dir, name, rev=None): + target_dir = os.path.join(src_dir, name) + target_rev = vcs_obj.make_rev_options(rev) + if not os.path.exists(target_dir): + vcs_obj.obtain(target_dir) + vcs_obj.update(target_dir, target_rev) + return vcs_obj.get_revision(target_dir) + + +def get_vcs_deps(project, pip_freeze=None, which=None, verbose=False, clear=False, pre=False, allow_global=False, dev=False): + from ._compat import vcs + section = 'vcs_dev_packages' if dev else 'vcs_packages' + lines = [] + lockfiles = [] + try: + packages = getattr(project, section) + except AttributeError: + return [], [] + vcs_registry = vcs() + vcs_uri_map = { + extract_uri_from_vcs_dep(v): {'name': k, 'ref': v.get('ref')} + for k, v in packages.items() + } + for line in pip_freeze.strip().split('\n'): + # if the line doesn't match a vcs dependency in the Pipfile, + # ignore it + _vcs_match = first(_uri for _uri in vcs_uri_map.keys() if _uri in line) + if not _vcs_match: + continue + + pipfile_name = vcs_uri_map[_vcs_match]['name'] + pipfile_rev = vcs_uri_map[_vcs_match]['ref'] + src_dir = os.environ.get('PIP_SRC', os.path.join(project.virtualenv_location, 'src')) + mkdir_p(src_dir) + names = {pipfile_name} + _pip_uri = line.lstrip('-e ') + backend_name = str(_pip_uri.split('+', 1)[0]) + backend = vcs_registry._registry[first(b for b in vcs_registry if b == backend_name)] + __vcs = backend(url=_pip_uri) + + installed = convert_deps_from_pip(line) + if not hasattr(installed, 'keys'): + pass + lock_name = first(installed.keys()) + names.add(lock_name) + locked_rev = None + for _name in names: + locked_rev = install_or_update_vcs(__vcs, src_dir, _name, rev=pipfile_rev) + if is_vcs(installed[lock_name]): + installed[lock_name]['ref'] = locked_rev + lockfiles.append({pipfile_name: installed[lock_name]}) + pipfile_srcdir = os.path.join(src_dir, pipfile_name) + lockfile_srcdir = os.path.join(src_dir, lock_name) + lines.append(line) + if os.path.exists(pipfile_srcdir): + lockfiles.extend(venv_resolve_deps(['-e {0}'.format(pipfile_srcdir)], which=which, verbose=verbose, project=project, clear=clear, pre=pre, allow_global=allow_global)) + else: + lockfiles.extend(venv_resolve_deps(['-e {0}'.format(lockfile_srcdir)], which=which, verbose=verbose, project=project, clear=clear, pre=pre, allow_global=allow_global)) + return lines, lockfiles diff --git a/tests/integration/test_install_uri.py b/tests/integration/test_install_uri.py index 94391f57..a19577e6 100644 --- a/tests/integration/test_install_uri.py +++ b/tests/integration/test_install_uri.py @@ -2,6 +2,10 @@ import pytest import os from flaky import flaky import delegator +try: + from pathlib import Path +except ImportError: + from pathlib2 import Path @pytest.mark.vcs @@ -144,3 +148,25 @@ def test_install_local_vcs_not_in_lockfile(PipenvInstance, pip_src_dir): assert six_key in p.lockfile['default'] # Make sure we didn't put six in the lockfile by accident as a vcs ref assert 'six' not in p.lockfile['default'] + + +@pytest.mark.vcs +@pytest.mark.install +@pytest.mark.needs_internet +def test_get_vcs_refs(PipenvInstance, pip_src_dir): + with PipenvInstance(chdir=True) as p: + c = p.pipenv('install -e git+https://github.com/hynek/structlog.git@16.1.0#egg=structlog') + assert c.return_code == 0 + assert 'structlog' in p.pipfile['packages'] + assert 'structlog' in p.lockfile['default'] + assert 'six' in p.lockfile['default'] + assert p.lockfile['default']['structlog']['ref'] == 'a39f6906a268fb2f4c365042b31d0200468fb492' + pipfile = Path(p.pipfile_path) + new_content = pipfile.read_bytes().replace(b'16.1.0', b'18.1.0') + pipfile.write_bytes(new_content) + c = p.pipenv('lock') + assert c.return_code == 0 + assert p.lockfile['default']['structlog']['ref'] == 'a73fbd3a9c3cafb11f43168582083f839b883034' + assert 'structlog' in p.pipfile['packages'] + assert 'structlog' in p.lockfile['default'] + assert 'six' in p.lockfile['default'] From 4845552560ed59079f4814602ef0b003ed6d0319 Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Sun, 20 May 2018 09:42:19 -0400 Subject: [PATCH 05/14] new dockerfile for ubuntu 18.04 Signed-off-by: Kenneth Reitz --- Dockerfile | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Dockerfile b/Dockerfile index 4bab57e2..ccf35a6c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,11 +1,7 @@ -FROM ubuntu:17.10 +FROM ubuntu:18.04 # -- Install Pipenv: -RUN apt-get update \ - && apt-get install software-properties-common python-software-properties -y \ - && add-apt-repository ppa:pypa/ppa -y \ - && apt-get update \ - && apt-get install git pipenv -y +RUN apt update && apt install python3-pip -y && pip3 install pipenv ENV LC_ALL C.UTF-8 ENV LANG C.UTF-8 From 1f495db5095822d3b2793685eddcde0af5f9e7ed Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Sun, 20 May 2018 09:54:27 -0400 Subject: [PATCH 06/14] docker-compose based tests Signed-off-by: Kenneth Reitz --- .buildkite/pipeline.yml | 2 +- Dockerfile.tests | 23 +++++++++++++++++++++++ Makefile | 3 +++ docker-compose.yml | 9 +++++++++ 4 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 Dockerfile.tests create mode 100644 Makefile create mode 100644 docker-compose.yml diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index 48175a72..9274f481 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -1,4 +1,4 @@ steps: - label: ":python:" commands: - - ./run-tests.sh \ No newline at end of file + - make \ No newline at end of file diff --git a/Dockerfile.tests b/Dockerfile.tests new file mode 100644 index 00000000..5ffc78d8 --- /dev/null +++ b/Dockerfile.tests @@ -0,0 +1,23 @@ +FROM ubuntu:18.04 + +# -- Install Pipenv: +RUN apt update && apt install python-pip python3-pip -y && pip3 install pipenv + +ENV LC_ALL C.UTF-8 +ENV LANG C.UTF-8 + +# -- Install Application into container: +RUN set -ex && mkdir /app + +WORKDIR /pipenv + +# -------------------- +# - Using This File: - +# -------------------- + +# FROM kennethreitz/pipenv + +# COPY . /app + +# -- Replace with the correct path to your app's main executable +# CMD python3 main.py diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..25b48eb8 --- /dev/null +++ b/Makefile @@ -0,0 +1,3 @@ +test: + docker-compose build + docker-compose up \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..663c4fc0 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,9 @@ +version: '3' +services: + pipenv-tests: + build: + context: . + dockerfile: Dockerfile.tests + command: bash /pipenv/run-tests.sh + volumes: + - .:/pipenv From 86aee384e1a82162013a4f61baf631749bea4667 Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Sun, 20 May 2018 09:57:10 -0400 Subject: [PATCH 07/14] also build time Signed-off-by: Kenneth Reitz --- Dockerfile.tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile.tests b/Dockerfile.tests index 5ffc78d8..1b235af4 100644 --- a/Dockerfile.tests +++ b/Dockerfile.tests @@ -1,7 +1,7 @@ FROM ubuntu:18.04 # -- Install Pipenv: -RUN apt update && apt install python-pip python3-pip -y && pip3 install pipenv +RUN apt update && apt install python-pip python3-pip time -y && pip3 install pipenv ENV LC_ALL C.UTF-8 ENV LANG C.UTF-8 From 439c0089cbd68f4221f2d50e8d1bd7cbbe0b1faa Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Sun, 20 May 2018 10:02:54 -0400 Subject: [PATCH 08/14] also install git Signed-off-by: Kenneth Reitz --- Dockerfile.tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile.tests b/Dockerfile.tests index 1b235af4..01f6f207 100644 --- a/Dockerfile.tests +++ b/Dockerfile.tests @@ -1,7 +1,7 @@ FROM ubuntu:18.04 # -- Install Pipenv: -RUN apt update && apt install python-pip python3-pip time -y && pip3 install pipenv +RUN apt update && apt install python-pip python3-pip time git -y && pip3 install pipenv ENV LC_ALL C.UTF-8 ENV LANG C.UTF-8 From 0343454988bdcee45a198480cb525528a6d63a66 Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Sun, 20 May 2018 10:12:00 -0400 Subject: [PATCH 09/14] pipenv-tests Signed-off-by: Kenneth Reitz --- Dockerfile.tests | 23 ----------------------- docker-compose.yml | 4 +--- 2 files changed, 1 insertion(+), 26 deletions(-) delete mode 100644 Dockerfile.tests diff --git a/Dockerfile.tests b/Dockerfile.tests deleted file mode 100644 index 01f6f207..00000000 --- a/Dockerfile.tests +++ /dev/null @@ -1,23 +0,0 @@ -FROM ubuntu:18.04 - -# -- Install Pipenv: -RUN apt update && apt install python-pip python3-pip time git -y && pip3 install pipenv - -ENV LC_ALL C.UTF-8 -ENV LANG C.UTF-8 - -# -- Install Application into container: -RUN set -ex && mkdir /app - -WORKDIR /pipenv - -# -------------------- -# - Using This File: - -# -------------------- - -# FROM kennethreitz/pipenv - -# COPY . /app - -# -- Replace with the correct path to your app's main executable -# CMD python3 main.py diff --git a/docker-compose.yml b/docker-compose.yml index 663c4fc0..1fede25a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,9 +1,7 @@ version: '3' services: pipenv-tests: - build: - context: . - dockerfile: Dockerfile.tests + image: kennethreitz/pipenv-tests command: bash /pipenv/run-tests.sh volumes: - .:/pipenv From 4361cf7f3a4aba42555ffc965494ee95776b298b Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Sun, 20 May 2018 10:25:30 -0400 Subject: [PATCH 10/14] empty commit From c2495dcd995d8bbe833c634de7e5aa91483de7bf Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Sun, 20 May 2018 10:33:54 -0400 Subject: [PATCH 11/14] update makefile Signed-off-by: Kenneth Reitz --- Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/Makefile b/Makefile index 25b48eb8..51b267c5 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,2 @@ test: - docker-compose build docker-compose up \ No newline at end of file From 92290cb2f6486400bc2e47867bbe26bab3f9ceef Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Sun, 20 May 2018 10:35:13 -0400 Subject: [PATCH 12/14] stick to traditional tests for now Signed-off-by: Kenneth Reitz --- .buildkite/pipeline.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index 9274f481..46b2e799 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -1,4 +1,5 @@ steps: - label: ":python:" commands: - - make \ No newline at end of file + # - make + - ./run-tests.sh \ No newline at end of file From 0567c10d685b0ee25d629d9abe0692a23880811f Mon Sep 17 00:00:00 2001 From: Jeremy Fleischman Date: Wed, 2 May 2018 10:03:05 -0700 Subject: [PATCH 13/14] When formatting a requirement, only lowercase its name. This fixes https://github.com/pypa/pipenv/issues/2113. This bug was introduced in as a band-aid fix to . Pipenv then copied that code in , and inherited this latent bug. Maybe the right fix is for pypa/packaging to lowercase the name? There's a comment here about normalizing the requirement's name, which might be what this is referring to. To test this, I invented a new, very simple python package called `depends-on-marked-package`. The setup.py for this package is just: ```python import setuptools setuptools.setup( name="depends-on-marked-package", version="0.0.1", packages=setuptools.find_packages(), install_requires=['pytz; platform_python_implementation=="CPython"'], ) ``` This is a simplified version of gevent's setup.py's install_requires upon greenlet. --- pipenv/patched/piptools/utils.py | 32 +++++++++++++++++- tests/integration/test_install_markers.py | 20 +++++++++++ ..._marked_package-0.0.1-py2.py3-none-any.whl | Bin 0 -> 1215 bytes 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 tests/pypi/depends-on-marked-package/depends_on_marked_package-0.0.1-py2.py3-none-any.whl diff --git a/pipenv/patched/piptools/utils.py b/pipenv/patched/piptools/utils.py index db8bb9b3..f3de3dd3 100644 --- a/pipenv/patched/piptools/utils.py +++ b/pipenv/patched/piptools/utils.py @@ -58,6 +58,36 @@ def make_install_requirement(name, version, extras, markers, constraint=False): constraint=constraint) +def _requirement_to_str_lowercase_name(requirement): + """ + Formats a packaging.requirements.Requirement with a lowercase name. + + This is simply a copy of + https://github.com/pypa/packaging/blob/16.8/packaging/requirements.py#L109-L124 + modified to lowercase the dependency name. + + Previously, we were invoking the original Requirement.__str__ method and + lowercasing the entire result, which would lowercase the name, *and* other, + important stuff that should not be lowercased (such as the marker). See + this issue for more information: https://github.com/pypa/pipenv/issues/2113. + """ + parts = [requirement.name.lower()] + + if requirement.extras: + parts.append("[{0}]".format(",".join(sorted(requirement.extras)))) + + if requirement.specifier: + parts.append(str(requirement.specifier)) + + if requirement.url: + parts.append("@ {0}".format(requirement.url)) + + if requirement.marker: + parts.append("; {0}".format(requirement.marker)) + + return "".join(parts) + + def format_requirement(ireq, marker=None): """ Generic formatter for pretty printing InstallRequirements to the terminal @@ -66,7 +96,7 @@ def format_requirement(ireq, marker=None): if ireq.editable: line = '-e {}'.format(ireq.link) else: - line = str(ireq.req).lower() + line = _requirement_to_str_lowercase_name(ireq.req) if marker: line = '{}; {}'.format(line, marker) diff --git a/tests/integration/test_install_markers.py b/tests/integration/test_install_markers.py index 87235d4a..9e3fa1d2 100644 --- a/tests/integration/test_install_markers.py +++ b/tests/integration/test_install_markers.py @@ -33,6 +33,26 @@ tablib = {version = "*", markers="os_name=='splashwear'"} c = p.pipenv('run python -c "import tablib;"') assert c.return_code == 1 +@pytest.mark.markers +@flaky +def test_platform_python_implementation_marker(PipenvInstance, pypi): + """Markers should be converted during locking to help users who input this incorrectly + """ + with PipenvInstance(pypi=pypi) as p: + with open(p.pipfile_path, 'w') as f: + contents = """ +[packages] +depends-on-marked-package = "*" + """.strip() + f.write(contents) + + c = p.pipenv('install') + assert c.return_code == 0 + + # depends-on-marked-package has an install_requires of 'pytz; platform_python_implementation=="CPython"' + # Verify that that marker shows up in our lockfile unaltered. + assert p.lockfile['default']['pytz']['markers'] == "platform_python_implementation == 'CPython'" + @pytest.mark.run @pytest.mark.alt diff --git a/tests/pypi/depends-on-marked-package/depends_on_marked_package-0.0.1-py2.py3-none-any.whl b/tests/pypi/depends-on-marked-package/depends_on_marked_package-0.0.1-py2.py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..d320deb3a4d39d987501a55af6abdc192c263cb4 GIT binary patch literal 1215 zcmWIWW@Zs#U|`^2SZJ`_XENJ$BW56v5s1x!I3=|pH7}(&K0hx$H?b%?H6^|vF*!Ri zJyq90&p^*mFD0|ML^m@pEnmMRzaTy*wJbG9ucV^nF%v@oin+o9f7;`L=H&sgK1t?= zd$_v#aG&?^J$sSYTUYDcne&^246YbIDDpq+t?Q+8Qh!sBhu29Ry-t1hm4O!wE*P6# zF~0JI>(qJui(hrF@oMOLojvKZDM&+8%l9dlr_c5vjTI)B&YnK+ebx8O>XuFkWtSaj zZrzZ`F0}&a#(zL;M3P&5T|*pQ977yq`)s)n8Hl)k|I>BBcBz${RR>>_RQIC3rx)#R zUwC#{MfTNt^Ny&(JwBkBj11|e+Rib`vj-ph-PpT_bxroP`U{VSjApmQ4&gIwmm zB#z6!qrH!RO#Zms;G}(V^3u~XR(B%A1*bfj>a(`?)8lFV9j1tr~mXAAW%R_r_y&$08-xgDp1%QF6)x|u!Ie|`S(42EZA#moWTj7%cTxU&i{ z#K2%lBZwk1j3CJpa4teO96g~U3}*o*0pfiCOZMpIqbDeY`F}_< YACkNRyjj^mCa?fu15m#vsGMQ|0Hc4WyZ`_I literal 0 HcmV?d00001 From df126c1be34ed4c4476269a6dc9c8342f3fa9c96 Mon Sep 17 00:00:00 2001 From: Jeremy Fleischman Date: Tue, 22 May 2018 23:19:27 -0700 Subject: [PATCH 14/14] Fix broken links. This fixes #2246. --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index af7ab55b..d7fa45c6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,8 +3,8 @@ Before opening any issues or proposing any pull requests, please do the following: -1. Read our [Contributor's Guide](http://docs.pipenv.org/en/latest/dev/contributing/). -2. Understand our [development philosophy](http://docs.pipenv.org/en/latest/dev/philosophy/). +1. Read our [Contributor's Guide](https://docs.pipenv.org/dev/contributing/). +2. Understand our [development philosophy](https://docs.pipenv.org/dev/philosophy/). To get the greatest chance of helpful responses, please also observe the following additional notes.