From 359906c669cab7e23b633d514af322ccfb3ea3c0 Mon Sep 17 00:00:00 2001 From: Dan Ryan Date: Wed, 29 May 2019 01:38:31 -0400 Subject: [PATCH] Update tests to resolve some transient resolution issues Signed-off-by: Dan Ryan probably need to sync submodules for this to work Signed-off-by: Dan Ryan Update to new version of artifacts Signed-off-by: Dan Ryan Fix windows failure Signed-off-by: Dan Ryan Update azure-pipelines.yml for Azure Pipelines Update lockfile test for windows Signed-off-by: Dan Ryan Fix scandir test Signed-off-by: Dan Ryan Update azure test steps Signed-off-by: Dan Ryan Fix virtualenv test Signed-off-by: Dan Ryan Fix python discovery when nothing is supplied Signed-off-by: Dan Ryan Fix cli ensure_project call Signed-off-by: Dan Ryan Fix run in virtualenv test Signed-off-by: Dan Ryan Show why virtualenv test failed if it did Signed-off-by: Dan Ryan Fix python interpreter discovery Signed-off-by: Dan Ryan scale down lock test modifications and increase error logging Signed-off-by: Dan Ryan Fix spinner bugs on windows and python discovery Signed-off-by: Dan Ryan Fix pythonfinder search algorithm to dodge false paths on win Signed-off-by: Dan Ryan use pipenv directly Signed-off-by: Dan Ryan --- .azure-pipelines/steps/build-package.yml | 18 +++++++ .azure-pipelines/steps/create-virtualenv.yml | 2 + .azure-pipelines/steps/run-tests-linux.yml | 8 +--- .azure-pipelines/steps/run-tests-windows.yml | 6 ++- .azure-pipelines/steps/run-vendor-scripts.yml | 18 +++++++ azure-pipelines.yml | 31 +++++++++--- pipenv/cli/command.py | 6 ++- pipenv/cli/options.py | 35 ++++++++++++-- pipenv/core.py | 33 +++++++------ pipenv/environments.py | 6 +-- pipenv/utils.py | 46 ++++++++++++++++-- pipenv/vendor/pythonfinder/utils.py | 2 +- pipenv/vendor/vistir/misc.py | 4 +- pipenv/vendor/vistir/spin.py | 2 - tests/integration/conftest.py | 9 +++- tests/integration/test_cli.py | 1 + tests/integration/test_dot_venv.py | 4 +- tests/integration/test_install_basic.py | 28 ++++++----- tests/integration/test_install_markers.py | 4 +- tests/integration/test_lock.py | 8 ++-- tests/integration/test_project.py | 47 +++++++++++++------ tests/pypi | 2 +- 22 files changed, 236 insertions(+), 84 deletions(-) diff --git a/.azure-pipelines/steps/build-package.yml b/.azure-pipelines/steps/build-package.yml index 884d07e7..81a6160b 100644 --- a/.azure-pipelines/steps/build-package.yml +++ b/.azure-pipelines/steps/build-package.yml @@ -1,4 +1,22 @@ steps: +- task: UsePythonVersion@0 + inputs: + versionSpec: $(python.version) + architecture: '$(python.architecture)' + addToPath: true + displayName: Use Python $(python.version) + +- template: install-dependencies.yml + +- script: | + echo '##vso[task.setvariable variable=PIPENV_DEFAULT_PYTHON_VERSION]'$(python.version) + env: + PYTHON_VERSION: $(python.version) + +- template: create-virtualenv.yml + parameters: + python_version: $(python.version) + - script: | python -m pip install --upgrade wheel pip setuptools twine readme_renderer[md] python setup.py sdist bdist_wheel diff --git a/.azure-pipelines/steps/create-virtualenv.yml b/.azure-pipelines/steps/create-virtualenv.yml index 873efdc0..5f6160c4 100644 --- a/.azure-pipelines/steps/create-virtualenv.yml +++ b/.azure-pipelines/steps/create-virtualenv.yml @@ -34,6 +34,8 @@ steps: echo "GIT_SSL_CAINFO: $(GIT_SSL_CAINFO)" echo "PIPENV PYTHON VERSION: $(python.version)" echo "python_version: ${{ parameters.python_version }}" + git submodule sync + git submodule update --init --recursive $(PY_EXE) -m pipenv install --deploy --dev --python="$(PY_EXE)" env: PIPENV_DEFAULT_PYTHON_VERSION: ${{ parameters.python_version }} diff --git a/.azure-pipelines/steps/run-tests-linux.yml b/.azure-pipelines/steps/run-tests-linux.yml index 7d63d812..185a83b2 100644 --- a/.azure-pipelines/steps/run-tests-linux.yml +++ b/.azure-pipelines/steps/run-tests-linux.yml @@ -4,15 +4,11 @@ parameters: steps: - script: | # Fix Git SSL errors - echo "Using pipenv python version: $PIPENV_DEFAULT_PYTHON_VERSION" + echo "Using pipenv python version: $(PIPENV_DEFAULT_PYTHON_VERSION)" git submodule sync && git submodule update --init --recursive pipenv run pytest --junitxml=test-results.xml displayName: Run integration tests env: - PY_EXE: $(PY_EXE) - GIT_SSL_CAINFO: $(GIT_SSL_CAINFO) - LANG: $(LANG) - PIP_PROCESS_DEPENDENCY_LINKS: '$(PIP_PROCESS_DEPENDENCY_LINKS)' - PIPENV_DEFAULT_PYTHON_VERSION: '${{ parameters.python_version }}' PYTHONWARNINGS: ignore:DEPRECATION PIPENV_NOSPIN: '1' + PIPENV_DEFAULT_PYTHON_VERSION: ${{ parameters.python_version }} diff --git a/.azure-pipelines/steps/run-tests-windows.yml b/.azure-pipelines/steps/run-tests-windows.yml index 21e7e49d..1730fa14 100644 --- a/.azure-pipelines/steps/run-tests-windows.yml +++ b/.azure-pipelines/steps/run-tests-windows.yml @@ -6,14 +6,16 @@ steps: subst T: "$env:TEMP" Write-Host "##vso[task.setvariable variable=TEMP]T:\" Write-Host "##vso[task.setvariable variable=TMP]T:\" + Write-Host "##vso[task.setvariable variable=PIPENV_DEFAULT_PYTHON_VERSION]$env:PYTHON_VERSION" + Write-Host "##vso[task.setvariable variable=PIPENV_NOSPIN]1" displayName: Fix Temp Variable + env: + PYTHON_VERSION: ${{ parameters.python_version }} - script: | - echo "Using pipenv python version: $PIPENV_DEFAULT_PYTHON_VERSION" git submodule sync && git submodule update --init --recursive pipenv run pytest -ra --ignore=pipenv\patched --ignore=pipenv\vendor --junitxml=test-results.xml tests displayName: Run integration tests env: - PIPENV_DEFAULT_PYTHON_VERSION: '${{ parameters.python_version }}' PYTHONWARNINGS: 'ignore:DEPRECATION' PIPENV_NOSPIN: '1' diff --git a/.azure-pipelines/steps/run-vendor-scripts.yml b/.azure-pipelines/steps/run-vendor-scripts.yml index be10e263..2aca1fe0 100644 --- a/.azure-pipelines/steps/run-vendor-scripts.yml +++ b/.azure-pipelines/steps/run-vendor-scripts.yml @@ -2,6 +2,24 @@ parameters: python_version: '' steps: +- task: UsePythonVersion@0 + inputs: + versionSpec: $(python.version) + architecture: '$(python.architecture)' + addToPath: true + displayName: Use Python $(python.version) + +- template: install-dependencies.yml + +- script: | + echo '##vso[task.setvariable variable=PIPENV_DEFAULT_PYTHON_VERSION]'$(python.version) + env: + PYTHON_VERSION: $(python.version) + +- template: create-virtualenv.yml + parameters: + python_version: $(python.version) + - script: | python -m pip install --upgrade invoke requests parver bs4 vistir towncrier pip setuptools wheel --upgrade-strategy=eager python -m invoke vendoring.update diff --git a/azure-pipelines.yml b/azure-pipelines.yml index ce4657c5..3b6dec74 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -18,6 +18,9 @@ trigger: - .gitattributes - .editorconfig +variables: +- group: CI + jobs: - job: TestLinux pool: @@ -38,12 +41,28 @@ jobs: - template: .azure-pipelines/steps/run-tests.yml parameters: vmImage: 'Ubuntu-16.04' - - template: .azure-pipelines/steps/run-vendor-scripts.yml - parameters: - vmImage: 'Ubuntu-16.04' - - template: .azure-pipelines/steps/build-package.yml - parameters: - vmImage: 'Ubuntu-16.04' + +- job: TestVendoring + pool: + vmImage: 'Ubuntu-16.04' + variables: + python.version: '3.7.2' + python.architecture: x64 + steps: + - template: .azure-pipelines/steps/run-vendor-scripts.yml + parameters: + vmImage: 'Ubuntu-16.04' + +- job: TestPackaging + pool: + vmImage: 'Ubuntu-16.04' + variables: + python.version: '3.7.2' + python.architecture: x64 + steps: + - template: .azure-pipelines/steps/build-package.yml + parameters: + vmImage: 'Ubuntu-16.04' - job: TestWindows pool: diff --git a/pipenv/cli/command.py b/pipenv/cli/command.py index e51c98a6..5168ecce 100644 --- a/pipenv/cli/command.py +++ b/pipenv/cli/command.py @@ -316,7 +316,10 @@ def lock( from ..core import ensure_project, do_init, do_lock # Ensure that virtualenv is available. - ensure_project(three=state.three, python=state.python, pypi_mirror=state.pypi_mirror) + ensure_project( + three=state.three, python=state.python, pypi_mirror=state.pypi_mirror, + warn=(not state.quiet) + ) if state.installstate.requirementstxt: do_init( dev=state.installstate.dev, @@ -330,6 +333,7 @@ def lock( pre=state.installstate.pre, keep_outdated=state.installstate.keep_outdated, pypi_mirror=state.pypi_mirror, + write=not state.quiet, ) diff --git a/pipenv/cli/options.py b/pipenv/cli/options.py index 3d29f264..56b0827e 100644 --- a/pipenv/cli/options.py +++ b/pipenv/cli/options.py @@ -6,7 +6,7 @@ import os import click.types from click import ( - BadParameter, Group, Option, argument, echo, make_pass_decorator, option + BadParameter, BadArgumentUsage, Group, Option, argument, echo, make_pass_decorator, option ) from click_didyoumean import DYMMixin @@ -56,6 +56,7 @@ class State(object): self.index = None self.extra_index_urls = [] self.verbose = False + self.quiet = False self.pypi_mirror = None self.python = None self.two = None @@ -231,12 +232,32 @@ def verbose_option(f): def callback(ctx, param, value): state = ctx.ensure_object(State) if value: + if state.quiet: + raise BadArgumentUsage( + "--verbose and --quiet are mutually exclusive! Please choose one!", + ctx=ctx + ) state.verbose = True - setup_verbosity(ctx, param, value) + setup_verbosity(ctx, param, 1) return option("--verbose", "-v", is_flag=True, expose_value=False, callback=callback, help="Verbose mode.", type=click.types.BOOL)(f) +def quiet_option(f): + def callback(ctx, param, value): + state = ctx.ensure_object(State) + if value: + if state.verbose: + raise BadArgumentUsage( + "--verbose and --quiet are mutually exclusive! Please choose one!", + ctx=ctx + ) + state.quiet = True + setup_verbosity(ctx, param, -1) + return option("--quiet", "-q", is_flag=True, expose_value=False, + callback=callback, help="Quiet mode.", type=click.types.BOOL)(f) + + def site_packages_option(f): def callback(ctx, param, value): state = ctx.ensure_object(State) @@ -313,8 +334,14 @@ def setup_verbosity(ctx, param, value): if not value: return import logging - logging.getLogger("pip").setLevel(logging.INFO) - environments.PIPENV_VERBOSITY = 1 + loggers = ("pip", "piptools") + if value == 1: + for logger in loggers: + logging.getLogger(logger).setLevel(logging.INFO) + elif value == -1: + for logger in loggers: + logging.getLogger(logger).setLevel(logging.CRITICAL) + environments.PIPENV_VERBOSITY = value def validate_python_path(ctx, param, value): diff --git a/pipenv/core.py b/pipenv/core.py index 9b4fa5a4..7762cb68 100644 --- a/pipenv/core.py +++ b/pipenv/core.py @@ -35,7 +35,7 @@ from .utils import ( get_canonical_names, is_pinned, is_pypi_url, is_required_version, is_star, is_valid_url, parse_indexes, pep423_name, prepare_pip_source_args, proper_case, python_version, venv_resolve_deps, run_command, - is_python_command, find_python + is_python_command, find_python, make_posix, interrupt_handled_subprocess ) @@ -371,6 +371,9 @@ def ensure_python(three=None, python=None): if not python: python = PIPENV_DEFAULT_PYTHON_VERSION path_to_python = find_a_system_python(python) + if environments.is_verbose(): + click.echo(u"Using python: {0}".format(python), err=True) + click.echo(u"Path to python: {0}".format(path_to_python), err=True) if not path_to_python and python is not None: # We need to install Python. click.echo( @@ -885,11 +888,13 @@ def do_create_virtualenv(python=None, site_packages=False, pypi_mirror=None): ) # Default to using sys.executable, if Python wasn't provided. + using_string = u"Using" if not python: python = sys.executable + using_string = "Using default python from" click.echo( u"{0} {1} {3} {2}".format( - crayons.normal("Using", bold=True), + crayons.normal(using_string, bold=True), crayons.red(python, bold=True), crayons.normal(fix_utf8("to create virtualenv…"), bold=True), crayons.green("({0})".format(python_version(python))), @@ -919,21 +924,19 @@ def do_create_virtualenv(python=None, site_packages=False, pypi_mirror=None): pip_config = {} # Actually create the virtualenv. + error = None with create_spinner(u"Creating virtual environment...") as sp: - c = vistir.misc.run( - cmd, verbose=False, return_object=True, write_to_stdout=False, - combine_stderr=False, block=True, nospin=True, env=pip_config, + with interrupt_handled_subprocess(cmd, combine_stderr=False, env=pip_config) as c: + click.echo(crayons.blue(u"{0}".format(c.out)), err=True) + if c.returncode != 0: + error = c.err if environments.is_verbose() else exceptions.prettify_exc(c.err) + sp.fail(environments.PIPENV_SPINNER_FAIL_TEXT.format(u"Failed creating virtual environment")) + else: + sp.green.ok(environments.PIPENV_SPINNER_OK_TEXT.format(u"Successfully created virtual environment!")) + if error is not None: + raise exceptions.VirtualenvCreationException( + extra=crayons.red("{0}".format(error)) ) - click.echo(crayons.blue(u"{0}".format(c.out)), err=True) - if c.returncode != 0: - sp.fail(environments.PIPENV_SPINNER_FAIL_TEXT.format(u"Failed creating virtual environment")) - error = c.err if environments.is_verbose() else exceptions.prettify_exc(c.err) - raise exceptions.VirtualenvCreationException( - extra=crayons.red("{0}".format(error)) - ) - else: - - sp.green.ok(environments.PIPENV_SPINNER_OK_TEXT.format(u"Successfully created virtual environment!")) # Associate project directory with the environment. # This mimics Pew's "setproject". diff --git a/pipenv/environments.py b/pipenv/environments.py index e7e64d31..79af98d4 100644 --- a/pipenv/environments.py +++ b/pipenv/environments.py @@ -126,7 +126,7 @@ PIPENV_MAX_ROUNDS = int(os.environ.get("PIPENV_MAX_ROUNDS", "16")) Default is 16, an arbitrary number that works most of the time. """ -PIPENV_MAX_SUBPROCESS = int(os.environ.get("PIPENV_MAX_SUBPROCESS", "16")) +PIPENV_MAX_SUBPROCESS = int(os.environ.get("PIPENV_MAX_SUBPROCESS", "8")) """How many subprocesses should Pipenv use when installing. Default is 16, an arbitrary number that seems to work. @@ -150,14 +150,12 @@ environments. if PIPENV_IS_CI: PIPENV_NOSPIN = True -PIPENV_SPINNER = "dots" +PIPENV_SPINNER = "dots" if not os.name == "nt" else "bouncingBar" """Sets the default spinner type. Spinners are identitcal to the node.js spinners and can be found at https://github.com/sindresorhus/cli-spinners """ -if os.name == "nt": - PIPENV_SPINNER = "bouncingBar" PIPENV_PIPFILE = os.environ.get("PIPENV_PIPFILE") """If set, this specifies a custom Pipfile location. diff --git a/pipenv/utils.py b/pipenv/utils.py index b99c51e7..fc9df248 100644 --- a/pipenv/utils.py +++ b/pipenv/utils.py @@ -6,6 +6,7 @@ import logging import os import posixpath import re +import signal import shutil import stat import sys @@ -25,7 +26,7 @@ six.add_move(six.MovedAttribute("Set", "collections", "collections.abc")) # noq from six.moves import Mapping, Sequence, Set from six.moves.urllib.parse import urlparse from .vendor.vistir.compat import ResourceWarning, lru_cache -from .vendor.vistir.misc import fs_str +from .vendor.vistir.misc import fs_str, run import crayons import parse @@ -964,9 +965,9 @@ def create_spinner(text, nospin=None, spinner_name=None): if nospin is None: nospin = environments.PIPENV_NOSPIN with spin.create_spinner( - spinner_name=spinner_name, - start_text=fs_str(text), - nospin=nospin, write_to_stdout=False + spinner_name=spinner_name, + start_text=fs_str(text), + nospin=nospin, write_to_stdout=False ) as sp: yield sp @@ -2103,3 +2104,40 @@ def make_marker_from_specifier(spec): specset = cleanup_pyspecs(SpecifierSet(spec)) marker_str = " and ".join([format_pyversion(pv) for pv in specset]) return Marker(marker_str) + + +@contextlib.contextmanager +def interrupt_handled_subprocess( + cmd, verbose=False, return_object=True, write_to_stdout=False, combine_stderr=True, + block=True, nospin=True, env=None +): + """Given a :class:`subprocess.Popen` instance, wrap it in exception handlers. + + Terminates the subprocess when and if a `SystemExit` or `KeyboardInterrupt` are + processed. + + Arguments: + :param str cmd: A command to run + :param bool verbose: Whether to run with verbose mode enabled, default False + :param bool return_object: Whether to return a subprocess instance or a 2-tuple, default True + :param bool write_to_stdout: Whether to write directly to stdout, default False + :param bool combine_stderr: Whether to combine stdout and stderr, default True + :param bool block: Whether the subprocess should be a blocking subprocess, default True + :param bool nospin: Whether to suppress the spinner with the subprocess, default True + :param Optional[Dict[str, str]] env: A dictionary to merge into the subprocess environment + :return: A subprocess, wrapped in exception handlers, as a context manager + :rtype: :class:`subprocess.Popen` obj: An instance of a running subprocess + """ + obj = run( + cmd, verbose=verbose, return_object=True, write_to_stdout=False, + combine_stderr=False, block=True, nospin=True, env=env, + ) + try: + yield obj + except (SystemExit, KeyboardInterrupt): + if os.name == "nt": + os.kill(obj.pid, signal.CTRL_BREAK_EVENT) + else: + os.kill(obj.pid, signal.SIGINT) + obj.wait() + raise diff --git a/pipenv/vendor/pythonfinder/utils.py b/pipenv/vendor/pythonfinder/utils.py index 1defda5f..bbab5381 100644 --- a/pipenv/vendor/pythonfinder/utils.py +++ b/pipenv/vendor/pythonfinder/utils.py @@ -62,7 +62,7 @@ KNOWN_EXTS = {"exe", "py", "fish", "sh", ""} KNOWN_EXTS = KNOWN_EXTS | set( filter(None, os.environ.get("PATHEXT", "").split(os.pathsep)) ) -PY_MATCH_STR = r"((?P{0})(?:\d?(?:\.\d[cpm]{{0,3}}))?(?:-?[\d\.]+)*[^z])".format( +PY_MATCH_STR = r"((?P{0})(?:\d?(?:\.\d[cpm]{{0,3}}))?(?:-?[\d\.]+)*[^zw])".format( "|".join(PYTHON_IMPLEMENTATIONS) ) EXE_MATCH_STR = r"{0}(?:\.(?P{1}))?".format(PY_MATCH_STR, "|".join(KNOWN_EXTS)) diff --git a/pipenv/vendor/vistir/misc.py b/pipenv/vendor/vistir/misc.py index e46700e5..8d3322d2 100644 --- a/pipenv/vendor/vistir/misc.py +++ b/pipenv/vendor/vistir/misc.py @@ -6,6 +6,7 @@ import json import locale import logging import os +import signal import subprocess import sys from collections import OrderedDict @@ -303,9 +304,10 @@ def _create_subprocess( else: try: c.out, c.err = c.communicate() - except (SystemExit, TimeoutError): + except (SystemExit, KeyboardInterrupt, TimeoutError): c.terminate() c.out, c.err = c.communicate() + raise if not block: c.wait() c.out = to_text("{0}".format(c.out)) if c.out else fs_str("") diff --git a/pipenv/vendor/vistir/spin.py b/pipenv/vendor/vistir/spin.py index 1e67e482..64b615de 100644 --- a/pipenv/vendor/vistir/spin.py +++ b/pipenv/vendor/vistir/spin.py @@ -41,7 +41,6 @@ if os.name == "nt": # pragma: no cover """ spinner.fail() spinner.stop() - sys.exit(0) else: # pragma: no cover @@ -55,7 +54,6 @@ else: # pragma: no cover """ spinner.red.fail("✘") spinner.stop() - sys.exit(0) CLEAR_LINE = chr(27) + "[K" diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index c239c075..74429dbc 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -17,6 +17,7 @@ from vistir.contextmanagers import temp_environ from vistir.path import mkdir_p, create_tracked_tempdir, handle_remove_readonly from pipenv._compat import Path +from pipenv.cmdparse import Script from pipenv.exceptions import VirtualenvActivationException from pipenv.vendor import delegator, requests, toml, tomlkit from pytest_pypi.app import prepare_fixtures @@ -111,6 +112,8 @@ def pytest_runtest_setup(item): sys.version_info < (3, 0) ): pytest.skip('test only runs on python 3') + if item.get_closest_marker('skip_osx') is not None and sys.platform == 'darwin': + pytest.skip('test does not apply on OSX') if item.get_closest_marker('lte_py36') is not None and ( sys.version_info >= (3, 7) ): @@ -329,8 +332,10 @@ class _PipenvInstance(object): with TemporaryDirectory(prefix='pipenv-', suffix='-cache') as tempdir: os.environ['PIPENV_CACHE_DIR'] = fs_str(tempdir.name) - c = delegator.run('pipenv {0}'.format(cmd), block=block, - cwd=os.path.abspath(self.path)) + c = delegator.run( + 'pipenv {0}'.format(cmd), block=block, + cwd=os.path.abspath(self.path), env=os.environ.copy() + ) if 'PIPENV_CACHE_DIR' in os.environ: del os.environ['PIPENV_CACHE_DIR'] diff --git a/tests/integration/test_cli.py b/tests/integration/test_cli.py index f131ae44..4be05cfb 100644 --- a/tests/integration/test_cli.py +++ b/tests/integration/test_cli.py @@ -217,6 +217,7 @@ def test_install_parse_error(PipenvInstance, pypi): @pytest.mark.code @pytest.mark.check @pytest.mark.unused +@pytest.mark.skip_osx @pytest.mark.needs_internet(reason='required by check') def test_check_unused(PipenvInstance, pypi): with PipenvInstance(chdir=True, pypi=pypi) as p: diff --git a/tests/integration/test_dot_venv.py b/tests/integration/test_dot_venv.py index 07904b16..840560f9 100644 --- a/tests/integration/test_dot_venv.py +++ b/tests/integration/test_dot_venv.py @@ -70,12 +70,12 @@ def test_venv_file(venv_name, PipenvInstance, pypi): venv_loc = Path(c.out.strip()).absolute() assert venv_loc.exists() assert venv_loc.joinpath('.project').exists() - venv_path = venv_loc.as_posix() + venv_path = normalize_drive(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 + assert venv_path == normalize_drive(venv_expected_path) @pytest.mark.dotvenv diff --git a/tests/integration/test_install_basic.py b/tests/integration/test_install_basic.py index 8b9df96c..ea6efb3e 100644 --- a/tests/integration/test_install_basic.py +++ b/tests/integration/test_install_basic.py @@ -28,8 +28,9 @@ def test_basic_setup(PipenvInstance, pypi): assert "certifi" in p.lockfile["default"] -@pytest.mark.install @flaky +@pytest.mark.install +@pytest.mark.skip_osx def test_basic_install(PipenvInstance, pypi): with PipenvInstance(pypi=pypi) as p: c = p.pipenv("install requests") @@ -42,8 +43,8 @@ def test_basic_install(PipenvInstance, pypi): assert "certifi" in p.lockfile["default"] -@pytest.mark.install @flaky +@pytest.mark.install def test_mirror_install(PipenvInstance, pypi): with temp_environ(), PipenvInstance(chdir=True, pypi=pypi) as p: mirror_url = os.environ.pop( @@ -68,9 +69,9 @@ def test_mirror_install(PipenvInstance, pypi): assert "certifi" in p.lockfile["default"] +@flaky @pytest.mark.install @pytest.mark.needs_internet -@flaky def test_bad_mirror_install(PipenvInstance, pypi): with temp_environ(), PipenvInstance(chdir=True) as p: # This demonstrates that the mirror parameter is being used @@ -79,8 +80,8 @@ def test_bad_mirror_install(PipenvInstance, pypi): assert c.return_code != 0 -@pytest.mark.complex @pytest.mark.lock +@pytest.mark.complex @pytest.mark.skip(reason="Does not work unless you can explicitly install into py2") def test_complex_lock(PipenvInstance, pypi): with PipenvInstance(pypi=pypi) as p: @@ -91,9 +92,9 @@ def test_complex_lock(PipenvInstance, pypi): assert "futures" in p.lockfile[u"default"] +@flaky @pytest.mark.dev @pytest.mark.run -@flaky def test_basic_dev_install(PipenvInstance, pypi): with PipenvInstance(pypi=pypi) as p: c = p.pipenv("install requests --dev") @@ -109,9 +110,9 @@ def test_basic_dev_install(PipenvInstance, pypi): assert c.return_code == 0 +@flaky @pytest.mark.dev @pytest.mark.install -@flaky def test_install_without_dev(PipenvInstance, pypi): """Ensure that running `pipenv install` doesn't install dev packages""" with PipenvInstance(pypi=pypi, chdir=True) as p: @@ -136,8 +137,8 @@ pytz = "*" assert c.return_code == 0 -@pytest.mark.install @flaky +@pytest.mark.install def test_install_without_dev_section(PipenvInstance, pypi): with PipenvInstance(pypi=pypi) as p: with open(p.pipfile_path, "w") as f: @@ -156,9 +157,9 @@ six = "*" assert c.return_code == 0 +@flaky @pytest.mark.extras @pytest.mark.install -@flaky def test_extras_install(PipenvInstance, pypi): with PipenvInstance(pypi=pypi, chdir=True) as p: c = p.pipenv("install requests[socks]") @@ -173,9 +174,9 @@ def test_extras_install(PipenvInstance, pypi): assert "pysocks" in p.lockfile["default"] -@pytest.mark.install -@pytest.mark.pin @flaky +@pytest.mark.pin +@pytest.mark.install def test_windows_pinned_pipfile(PipenvInstance, pypi): with PipenvInstance(pypi=pypi) as p: with open(p.pipfile_path, "w") as f: @@ -190,10 +191,10 @@ requests = "==2.19.1" assert "requests" in p.lockfile["default"] +@flaky @pytest.mark.install @pytest.mark.resolver @pytest.mark.backup_resolver -@flaky def test_backup_resolver(PipenvInstance, pypi): with PipenvInstance(pypi=pypi) as p: with open(p.pipfile_path, "w") as f: @@ -208,9 +209,9 @@ def test_backup_resolver(PipenvInstance, pypi): assert "ibm-db-sa-py3" in p.lockfile["default"] +@flaky @pytest.mark.run @pytest.mark.alt -@flaky def test_alternative_version_specifier(PipenvInstance, pypi): with PipenvInstance(pypi=pypi) as p: with open(p.pipfile_path, "w") as f: @@ -233,9 +234,9 @@ requests = {version = "*"} assert c.return_code == 0 +@flaky @pytest.mark.run @pytest.mark.alt -@flaky def test_outline_table_specifier(PipenvInstance, pypi): with PipenvInstance(pypi=pypi) as p: with open(p.pipfile_path, "w") as f: @@ -297,6 +298,7 @@ def test_requirements_to_pipfile(PipenvInstance, pypi): @pytest.mark.install +@pytest.mark.skip_osx @pytest.mark.requirements def test_skip_requirements_when_pipfile(PipenvInstance, pypi): """Ensure requirements.txt is NOT imported when diff --git a/tests/integration/test_install_markers.py b/tests/integration/test_install_markers.py index 9d62e980..87770ed7 100644 --- a/tests/integration/test_install_markers.py +++ b/tests/integration/test_install_markers.py @@ -140,7 +140,7 @@ def test_resolver_unique_markers(PipenvInstance, pypi): This verifies that we clean that successfully. """ with PipenvInstance(chdir=True, pypi=pypi) as p: - c = p.pipenv('install vcrpy==1.11.0') + c = p.pipenv('install vcrpy==2.0.1') assert c.return_code == 0 c = p.pipenv('lock') assert c.return_code == 0 @@ -148,7 +148,7 @@ def test_resolver_unique_markers(PipenvInstance, pypi): yarl = p.lockfile['default']['yarl'] assert 'markers' in yarl # Two possible marker sets are ok here - assert yarl['markers'] in ["python_version in '3.4, 3.5, 3.6'", "python_version >= '3.4.1'"] + assert yarl['markers'] in ["python_version in '3.4, 3.5, 3.6'", "python_version >= '3.4'"] @pytest.mark.project diff --git a/tests/integration/test_lock.py b/tests/integration/test_lock.py index 881e2e40..dc2b10cf 100644 --- a/tests/integration/test_lock.py +++ b/tests/integration/test_lock.py @@ -596,18 +596,20 @@ def test_lock_no_warnings(PipenvInstance, pypi): @pytest.mark.lock @pytest.mark.install @pytest.mark.skipif(sys.version_info >= (3, 5), reason="scandir doesn't get installed on python 3.5+") -def test_lock_missing_cache_entries_gets_all_hashes(monkeypatch, PipenvInstance, pypi, tmpdir): +def test_lock_missing_cache_entries_gets_all_hashes(PipenvInstance, pypi, tmpdir): """ Test locking pathlib2 on python2.7 which needs `scandir`, but fails to resolve when using a fresh dependency cache. """ - with monkeypatch.context() as m: - monkeypatch.setattr("pipenv.patched.piptools.locations.CACHE_DIR", tmpdir.strpath) + with temp_environ(): + os.environ["PIPENV_CACHE_DIR"] = str(tmpdir.strpath) with PipenvInstance(pypi=pypi, chdir=True) as p: p._pipfile.add("pathlib2", "*") assert "pathlib2" in p.pipfile["packages"] c = p.pipenv("install") + assert c.return_code == 0, (c.err, ("\n".join(["{0}: {1}\n".format(k, v) for k, v in os.environ.items()]))) + c = p.pipenv("lock --clear") assert c.return_code == 0, c.err assert "pathlib2" in p.lockfile["default"] assert "scandir" in p.lockfile["default"] diff --git a/tests/integration/test_project.py b/tests/integration/test_project.py index 4adf46ab..436f11c1 100644 --- a/tests/integration/test_project.py +++ b/tests/integration/test_project.py @@ -10,6 +10,7 @@ from pipenv.patched import pipfile from pipenv.project import Project from pipenv.utils import temp_environ from pipenv.vendor.vistir.path import is_in_path +from pipenv.vendor.delegator import run as delegator_run import pipenv.environments @@ -173,22 +174,38 @@ def test_include_editable_packages(PipenvInstance, pypi, testsroot, pathlib_tmpd @pytest.mark.virtualenv def test_run_in_virtualenv_with_global_context(PipenvInstance, pypi, virtualenv): with PipenvInstance(chdir=True, pypi=pypi, venv_root=virtualenv.as_posix(), ignore_virtualenvs=False, venv_in_project=False) as p: - c = p.pipenv('run pip freeze') - assert c.return_code == 0 - assert 'Creating a virtualenv' not in c.err + c = delegator_run( + "pipenv run pip freeze", cwd=os.path.abspath(p.path), + env=os.environ.copy() + ) + assert c.return_code == 0, (c.out, c.err) + assert 'Creating a virtualenv' not in c.err, c.err project = Project() - assert project.virtualenv_location == virtualenv.as_posix() - c = p.pipenv("run pip install click") - assert c.return_code == 0 - assert "Courtesy Notice" in c.err - c = p.pipenv("install six") - assert c.return_code == 0 - c = p.pipenv('run python -c "import click;print(click.__file__)"') - assert c.return_code == 0 - assert is_in_path(c.out.strip(), str(virtualenv)) - c = p.pipenv("clean --dry-run") - assert c.return_code == 0 - assert "click" in c.out + assert project.virtualenv_location == virtualenv.as_posix(), ( + project.virtualenv_location, virtualenv.as_posix() + ) + c = delegator_run( + "pipenv run pip install click", cwd=os.path.abspath(p.path), + env=os.environ.copy() + ) + assert c.return_code == 0, (c.out, c.err) + assert "Courtesy Notice" in c.err, (c.out, c.err) + c = delegator_run( + "pipenv install six", cwd=os.path.abspath(p.path), env=os.environ.copy() + ) + assert c.return_code == 0, (c.out, c.err) + c = delegator_run( + 'pipenv run python -c "import click;print(click.__file__)"', + cwd=os.path.abspath(p.path), env=os.environ.copy() + ) + assert c.return_code == 0, (c.out, c.err) + assert is_in_path(c.out.strip(), str(virtualenv)), (c.out.strip(), str(virtualenv)) + c = delegator_run( + "pipenv clean --dry-run", cwd=os.path.abspath(p.path), + env=os.environ.copy() + ) + assert c.return_code == 0, (c.out, c.err) + assert "click" in c.out, c.out @pytest.mark.project diff --git a/tests/pypi b/tests/pypi index 7f759bef..f3260ec6 160000 --- a/tests/pypi +++ b/tests/pypi @@ -1 +1 @@ -Subproject commit 7f759bef456439ac130cfb6f6547a43527841d15 +Subproject commit f3260ec6bf5c435865d0def587e7f00f625952e9