mirror of
https://github.com/kennethreitz/pipenv.git
synced 2026-06-05 22:50:18 +00:00
c7e1abab24
Obv could also *not* create the empty virtualenv when running pipenv clean, but in general can imagine this also occurring if you created an empty virtualenv and then tried to do clean within it. (installed packages was [''])
1060 lines
37 KiB
Python
1060 lines
37 KiB
Python
import os
|
|
from pkg_resources import parse_version
|
|
import re
|
|
import tempfile
|
|
import shutil
|
|
import json
|
|
import pytest
|
|
import warnings
|
|
from pipenv.core import activate_virtualenv
|
|
from pipenv.utils import (
|
|
temp_environ, get_windows_path, mkdir_p, normalize_drive, rmtree, TemporaryDirectory
|
|
)
|
|
from pipenv.vendor import toml
|
|
from pipenv.vendor import delegator
|
|
from pipenv.project import Project
|
|
from pipenv.vendor.six import PY2
|
|
if PY2:
|
|
class ResourceWarning(Warning):
|
|
pass
|
|
|
|
try:
|
|
from pathlib import Path
|
|
except ImportError:
|
|
from pipenv.vendor.pathlib2 import Path
|
|
|
|
os.environ['PIPENV_DONT_USE_PYENV'] = '1'
|
|
os.environ['PIPENV_IGNORE_VIRTUALENVS'] = '1'
|
|
os.environ['PIPENV_VENV_IN_PROJECT'] = '1'
|
|
os.environ['PYPI_VENDOR_DIR'] = os.path.sep.join([os.path.dirname(__file__), 'pypi'])
|
|
|
|
|
|
@pytest.fixture(scope='module')
|
|
def pip_src_dir(request):
|
|
old_src_dir = os.environ.get('PIP_SRC', '')
|
|
new_src_dir = TemporaryDirectory(prefix='pipenv-', suffix='-testsrc')
|
|
os.environ['PIP_SRC'] = new_src_dir.name
|
|
|
|
def finalize():
|
|
new_src_dir.cleanup()
|
|
os.environ['PIP_SRC'] = old_src_dir
|
|
|
|
request.addfinalizer(finalize)
|
|
return request
|
|
|
|
|
|
class PipenvInstance():
|
|
"""An instance of a Pipenv Project..."""
|
|
def __init__(self, pypi=None, pipfile=True, chdir=False):
|
|
self.pypi = pypi
|
|
self.original_umask = os.umask(0o007)
|
|
self.original_dir = os.path.abspath(os.curdir)
|
|
self._path = TemporaryDirectory(suffix='project', prefix='pipenv')
|
|
self.path = self._path.name
|
|
# set file creation perms
|
|
self.pipfile_path = None
|
|
self.chdir = chdir
|
|
|
|
if self.pypi:
|
|
os.environ['PIPENV_TEST_INDEX'] = '{0}/simple'.format(self.pypi.url)
|
|
|
|
if pipfile:
|
|
p_path = os.sep.join([self.path, 'Pipfile'])
|
|
with open(p_path, 'a'):
|
|
os.utime(p_path, None)
|
|
|
|
self.chdir = False or chdir
|
|
self.pipfile_path = p_path
|
|
|
|
def __enter__(self):
|
|
if self.chdir:
|
|
os.chdir(self.path)
|
|
return self
|
|
|
|
def __exit__(self, *args):
|
|
warn_msg = 'Failed to remove resource: {!r}'
|
|
if self.chdir:
|
|
os.chdir(self.original_dir)
|
|
self.path = None
|
|
try:
|
|
self._path.cleanup()
|
|
except OSError as e:
|
|
_warn_msg = warn_msg.format(e)
|
|
warnings.warn(_warn_msg, ResourceWarning)
|
|
finally:
|
|
os.umask(self.original_umask)
|
|
|
|
def pipenv(self, cmd, block=True):
|
|
if self.pipfile_path:
|
|
os.environ['PIPENV_PIPFILE'] = self.pipfile_path
|
|
|
|
c = delegator.run('pipenv {0}'.format(cmd), block=block)
|
|
|
|
if 'PIPENV_PIPFILE' in os.environ:
|
|
del os.environ['PIPENV_PIPFILE']
|
|
|
|
# Pretty output for failing tests.
|
|
if block:
|
|
print('$ pipenv {0}'.format(cmd))
|
|
print(c.out)
|
|
print(c.err)
|
|
|
|
# Where the action happens.
|
|
return c
|
|
|
|
@property
|
|
def pipfile(self):
|
|
p_path = os.sep.join([self.path, 'Pipfile'])
|
|
with open(p_path, 'r') as f:
|
|
return toml.loads(f.read())
|
|
|
|
@property
|
|
def lockfile(self):
|
|
p_path = os.sep.join([self.path, 'Pipfile.lock'])
|
|
with open(p_path, 'r') as f:
|
|
return json.loads(f.read())
|
|
|
|
|
|
class TestPipenv:
|
|
"""The ultimate testing class."""
|
|
|
|
@pytest.mark.cli
|
|
def test_pipenv_where(self, pypi_secure):
|
|
with PipenvInstance(pypi=pypi_secure) as p:
|
|
assert normalize_drive(p.path) in p.pipenv('--where').out
|
|
|
|
@pytest.mark.cli
|
|
def test_pipenv_venv(self):
|
|
with PipenvInstance() as p:
|
|
p.pipenv('--python python')
|
|
venv_path = p.pipenv('--venv').out.strip()
|
|
assert os.path.isdir(venv_path)
|
|
|
|
@pytest.mark.cli
|
|
def test_pipenv_py(self):
|
|
with PipenvInstance() as p:
|
|
p.pipenv('--python python')
|
|
python = p.pipenv('--py').out.strip()
|
|
assert os.path.basename(python).startswith('python')
|
|
|
|
@pytest.mark.cli
|
|
def test_pipenv_rm(self):
|
|
with PipenvInstance() as p:
|
|
p.pipenv('--python python')
|
|
venv_path = p.pipenv('--venv').out.strip()
|
|
assert os.path.isdir(venv_path)
|
|
|
|
assert p.pipenv('--rm').out
|
|
assert not os.path.isdir(venv_path)
|
|
|
|
@pytest.mark.cli
|
|
def test_pipenv_graph(self, pypi):
|
|
with PipenvInstance(pypi=pypi) as p:
|
|
p.pipenv('install requests')
|
|
assert 'requests' in p.pipenv('graph').out
|
|
assert 'requests' in p.pipenv('graph --json').out
|
|
|
|
@pytest.mark.cli
|
|
def test_pipenv_graph_reverse(self, pypi):
|
|
with PipenvInstance(pypi=pypi) as p:
|
|
p.pipenv('install requests==2.18.4')
|
|
output = p.pipenv('graph --reverse').out
|
|
|
|
requests_dependency = [
|
|
('certifi', 'certifi>=2017.4.17'),
|
|
('chardet', 'chardet(>=3.0.2,<3.1.0|<3.1.0,>=3.0.2)'),
|
|
('idna', 'idna(>=2.5,<2.7|<2.7,>=2.5)'),
|
|
('urllib3', 'urllib3(>=1.21.1,<1.23|<1.23,>=1.21.1)')
|
|
]
|
|
|
|
for dep_name, dep_constraint in requests_dependency:
|
|
dep_match = re.search(r'^{}==[\d.]+$'.format(dep_name), output, flags=re.MULTILINE)
|
|
dep_requests_match = re.search(r'^ - requests==2.18.4 \[requires: {}\]$'.format(dep_constraint), output, flags=re.MULTILINE)
|
|
assert dep_match is not None
|
|
assert dep_requests_match is not None
|
|
assert dep_requests_match.start() > dep_match.start()
|
|
|
|
c = p.pipenv('graph --reverse --json')
|
|
assert c.return_code == 1
|
|
assert 'Warning: Using both --reverse and --json together is not supported.' in c.err
|
|
|
|
@pytest.mark.cli
|
|
def test_pipenv_check(self, pypi):
|
|
with PipenvInstance(pypi=pypi) as p:
|
|
p.pipenv('install requests==1.0.0')
|
|
assert 'requests' in p.pipenv('check').out
|
|
|
|
@pytest.mark.cli
|
|
def test_venv_envs(self):
|
|
with PipenvInstance() as p:
|
|
assert p.pipenv('--envs').out
|
|
|
|
@pytest.mark.cli
|
|
def test_bare_output(self):
|
|
with PipenvInstance() as p:
|
|
assert p.pipenv('').out
|
|
|
|
@pytest.mark.cli
|
|
def test_help(self):
|
|
with PipenvInstance() as p:
|
|
assert p.pipenv('--help').out
|
|
|
|
@pytest.mark.cli
|
|
def test_man(self):
|
|
with PipenvInstance() as p:
|
|
c = p.pipenv('--man')
|
|
assert c.return_code == 0 or c.err
|
|
|
|
@pytest.mark.cli
|
|
@pytest.mark.install
|
|
def test_install_parse_error(self, pypi):
|
|
with PipenvInstance(pypi=pypi) as p:
|
|
# Make sure unparseable packages don't wind up in the pipfile
|
|
# Escape $ for shell input
|
|
c = p.pipenv('install requests u/\\/p@r\$34b13+pkg')
|
|
assert c.return_code != 0
|
|
assert 'u/\\/p@r$34b13+pkg' not in p.pipfile['packages']
|
|
|
|
@pytest.mark.install
|
|
@pytest.mark.setup
|
|
@pytest.mark.skip(reason="this doesn't work on travis")
|
|
def test_basic_setup(self, pypi):
|
|
with PipenvInstance(pypi=pypi) as p:
|
|
with PipenvInstance(pipfile=False) as p:
|
|
c = p.pipenv('install requests')
|
|
assert c.return_code == 0
|
|
|
|
assert 'requests' in p.pipfile['packages']
|
|
assert 'requests' in p.lockfile['default']
|
|
assert 'chardet' in p.lockfile['default']
|
|
assert 'idna' in p.lockfile['default']
|
|
assert 'urllib3' in p.lockfile['default']
|
|
assert 'certifi' in p.lockfile['default']
|
|
|
|
@pytest.mark.install
|
|
def test_basic_install(self, pypi):
|
|
with PipenvInstance(pypi=pypi) as p:
|
|
c = p.pipenv('install requests')
|
|
assert c.return_code == 0
|
|
assert 'requests' in p.pipfile['packages']
|
|
assert 'requests' in p.lockfile['default']
|
|
assert 'chardet' in p.lockfile['default']
|
|
assert 'idna' in p.lockfile['default']
|
|
assert 'urllib3' in p.lockfile['default']
|
|
assert 'certifi' in p.lockfile['default']
|
|
|
|
@pytest.mark.complex_lock
|
|
def test_complex_lock(self, pypi):
|
|
with PipenvInstance(pypi=pypi) as p:
|
|
c = p.pipenv('install apscheduler')
|
|
assert c.return_code == 0
|
|
assert 'apscheduler' in p.pipfile['packages']
|
|
assert 'funcsigs' in p.lockfile[u'default']
|
|
assert 'futures' in p.lockfile[u'default']
|
|
|
|
@pytest.mark.dev
|
|
@pytest.mark.run
|
|
@pytest.mark.install
|
|
def test_basic_dev_install(self, pypi):
|
|
with PipenvInstance(pypi=pypi) as p:
|
|
c = p.pipenv('install requests --dev')
|
|
assert c.return_code == 0
|
|
assert 'requests' in p.pipfile['dev-packages']
|
|
assert 'requests' in p.lockfile['develop']
|
|
assert 'chardet' in p.lockfile['develop']
|
|
assert 'idna' in p.lockfile['develop']
|
|
assert 'urllib3' in p.lockfile['develop']
|
|
assert 'certifi' in p.lockfile['develop']
|
|
|
|
c = p.pipenv('run python -m requests.help')
|
|
assert c.return_code == 0
|
|
|
|
@pytest.mark.dev
|
|
@pytest.mark.install
|
|
def test_install_without_dev(self, pypi):
|
|
"""Ensure that running `pipenv install` doesn't install dev packages"""
|
|
with PipenvInstance(pypi=pypi) as p:
|
|
with open(p.pipfile_path, 'w') as f:
|
|
contents = """
|
|
[packages]
|
|
tablib = "*"
|
|
|
|
[dev-packages]
|
|
records = "*"
|
|
""".strip()
|
|
f.write(contents)
|
|
c = p.pipenv('install')
|
|
assert c.return_code == 0
|
|
assert 'tablib' in p.pipfile['packages']
|
|
assert 'records' in p.pipfile['dev-packages']
|
|
assert 'tablib' in p.lockfile['default']
|
|
assert 'records' in p.lockfile['develop']
|
|
c = p.pipenv('run python -c "import records"')
|
|
assert c.return_code != 0
|
|
c = p.pipenv('run python -c "import tablib"')
|
|
assert c.return_code == 0
|
|
|
|
|
|
@pytest.mark.run
|
|
@pytest.mark.uninstall
|
|
def test_uninstall(self, pypi):
|
|
with PipenvInstance(pypi=pypi) as p:
|
|
c = p.pipenv('install requests')
|
|
assert c.return_code == 0
|
|
assert 'requests' in p.pipfile['packages']
|
|
assert 'requests' in p.lockfile['default']
|
|
assert 'chardet' in p.lockfile['default']
|
|
assert 'idna' in p.lockfile['default']
|
|
assert 'urllib3' in p.lockfile['default']
|
|
assert 'certifi' in p.lockfile['default']
|
|
|
|
c = p.pipenv('uninstall requests')
|
|
assert c.return_code == 0
|
|
assert 'requests' not in p.pipfile['dev-packages']
|
|
assert 'requests' not in p.lockfile['develop']
|
|
assert 'chardet' not in p.lockfile['develop']
|
|
assert 'idna' not in p.lockfile['develop']
|
|
assert 'urllib3' not in p.lockfile['develop']
|
|
assert 'certifi' not in p.lockfile['develop']
|
|
|
|
c = p.pipenv('run python -m requests.help')
|
|
assert c.return_code > 0
|
|
|
|
@pytest.mark.files
|
|
@pytest.mark.run
|
|
@pytest.mark.uninstall
|
|
def test_uninstall_all_local_files(self):
|
|
file_name = 'tablib-0.12.1.tar.gz'
|
|
# Not sure where travis/appveyor run tests from
|
|
test_dir = os.path.dirname(os.path.abspath(__file__))
|
|
source_path = os.path.abspath(os.path.join(test_dir, 'test_artifacts', file_name))
|
|
|
|
with PipenvInstance() as p:
|
|
shutil.copy(source_path, os.path.join(p.path, file_name))
|
|
os.mkdir(os.path.join(p.path, "tablib"))
|
|
c = p.pipenv('install {}'.format(file_name))
|
|
c = p.pipenv('uninstall --all --verbose')
|
|
assert c.return_code == 0
|
|
assert 'tablib' in c.out
|
|
assert 'tablib' not in p.pipfile['packages']
|
|
|
|
@pytest.mark.run
|
|
@pytest.mark.uninstall
|
|
def test_uninstall_all_dev(self, pypi):
|
|
with PipenvInstance(pypi=pypi) as p:
|
|
c = p.pipenv('install --dev requests flask')
|
|
assert c.return_code == 0
|
|
|
|
c = p.pipenv('install tpfd')
|
|
assert c.return_code == 0
|
|
|
|
assert 'tpfd' in p.pipfile['packages']
|
|
assert 'requests' in p.pipfile['dev-packages']
|
|
assert 'flask' in p.pipfile['dev-packages']
|
|
assert 'tpfd' in p.lockfile['default']
|
|
assert 'requests' in p.lockfile['develop']
|
|
assert 'flask' in p.lockfile['develop']
|
|
|
|
|
|
c = p.pipenv('uninstall --all-dev')
|
|
assert c.return_code == 0
|
|
assert 'requests' not in p.pipfile['dev-packages']
|
|
assert 'pytest' not in p.pipfile['dev-packages']
|
|
assert 'requests' not in p.lockfile['develop']
|
|
assert 'pytest' not in p.lockfile['develop']
|
|
assert 'tpfd' in p.pipfile['packages']
|
|
assert 'tpfd' in p.lockfile['default']
|
|
|
|
|
|
c = p.pipenv('run python -m requests.help')
|
|
assert c.return_code > 0
|
|
|
|
c = p.pipenv('run python -c "import tpfd"')
|
|
assert c.return_code == 0
|
|
|
|
@pytest.mark.extras
|
|
@pytest.mark.install
|
|
def test_extras_install(self, pypi):
|
|
with PipenvInstance(pypi=pypi) as p:
|
|
c = p.pipenv('install requests[socks]')
|
|
assert c.return_code == 0
|
|
assert 'requests' in p.pipfile['packages']
|
|
assert 'extras' in p.pipfile['packages']['requests']
|
|
|
|
assert 'requests' in p.lockfile['default']
|
|
assert 'chardet' in p.lockfile['default']
|
|
assert 'idna' in p.lockfile['default']
|
|
assert 'urllib3' in p.lockfile['default']
|
|
assert 'pysocks' in p.lockfile['default']
|
|
|
|
@pytest.mark.extras
|
|
@pytest.mark.install
|
|
@pytest.mark.local
|
|
@pytest.mark.skip(reason="I'm not mocking this.")
|
|
def test_local_extras_install(self, pypi):
|
|
with PipenvInstance(pypi=pypi) as p:
|
|
setup_py = os.path.join(p.path, 'setup.py')
|
|
with open(setup_py, 'w') as fh:
|
|
contents = """
|
|
from setuptools import setup, find_packages
|
|
|
|
setup(
|
|
name='test_pipenv',
|
|
version='0.1',
|
|
description='Pipenv Test Package',
|
|
author='Pipenv Test',
|
|
author_email='test@pipenv.package',
|
|
license='PIPENV',
|
|
packages=find_packages(),
|
|
install_requires=['tablib'],
|
|
extras_require={'dev': ['flake8', 'pylint']},
|
|
zip_safe=False
|
|
)
|
|
""".strip()
|
|
fh.write(contents)
|
|
c = p.pipenv('install .[dev]')
|
|
assert c.return_code == 0
|
|
key = [k for k in p.pipfile['packages'].keys()][0]
|
|
dep = p.pipfile['packages'][key]
|
|
assert dep['path'] == '.'
|
|
assert dep['extras'] == ['dev']
|
|
assert key in p.lockfile['default']
|
|
assert 'dev' in p.lockfile['default'][key]['extras']
|
|
|
|
@pytest.mark.vcs
|
|
@pytest.mark.install
|
|
def test_basic_vcs_install(self, pypi):
|
|
with PipenvInstance(pypi=pypi) as p:
|
|
c = p.pipenv('install git+https://github.com/requests/requests.git#egg=requests')
|
|
assert c.return_code == 0
|
|
# edge case where normal package starts with VCS name shouldn't be flagged as vcs
|
|
c = p.pipenv('install gitdb2')
|
|
assert c.return_code == 0
|
|
assert all(package in p.pipfile['packages'] for package in ['requests', 'gitdb2'])
|
|
assert 'git' in p.pipfile['packages']['requests']
|
|
assert p.lockfile['default']['requests'] == {"git": "https://github.com/requests/requests.git"}
|
|
assert 'gitdb2' in p.lockfile['default']
|
|
|
|
@pytest.mark.e
|
|
@pytest.mark.vcs
|
|
@pytest.mark.install
|
|
def test_editable_vcs_install(self, pip_src_dir, pypi):
|
|
with PipenvInstance(pypi=pypi) as p:
|
|
c = p.pipenv('install -e git+https://github.com/requests/requests.git#egg=requests')
|
|
assert c.return_code == 0
|
|
assert 'requests' in p.pipfile['packages']
|
|
assert 'git' in p.pipfile['packages']['requests']
|
|
assert 'editable' in p.pipfile['packages']['requests']
|
|
assert 'editable' in p.lockfile['default']['requests']
|
|
assert 'chardet' in p.lockfile['default']
|
|
assert 'idna' in p.lockfile['default']
|
|
assert 'urllib3' in p.lockfile['default']
|
|
assert 'certifi' in p.lockfile['default']
|
|
|
|
@pytest.mark.install
|
|
@pytest.mark.pin
|
|
def test_windows_pinned_pipfile(self, pypi):
|
|
with PipenvInstance(pypi=pypi) as p:
|
|
with open(p.pipfile_path, 'w') as f:
|
|
contents = """
|
|
[packages]
|
|
tablib = "<0.12"
|
|
""".strip()
|
|
f.write(contents)
|
|
c = p.pipenv('install')
|
|
assert c.return_code == 0
|
|
assert 'tablib' in p.pipfile['packages']
|
|
assert 'tablib' in p.lockfile['default']
|
|
|
|
@pytest.mark.run
|
|
@pytest.mark.install
|
|
def test_multiprocess_bug_and_install(self, pypi):
|
|
with temp_environ():
|
|
os.environ['PIPENV_MAX_SUBPROCESS'] = '2'
|
|
|
|
with PipenvInstance(pypi=pypi) as p:
|
|
with open(p.pipfile_path, 'w') as f:
|
|
contents = """
|
|
[packages]
|
|
requests = "*"
|
|
records = "*"
|
|
tpfd = "*"
|
|
""".strip()
|
|
f.write(contents)
|
|
|
|
c = p.pipenv('install')
|
|
assert c.return_code == 0
|
|
|
|
assert 'requests' in p.lockfile['default']
|
|
assert 'idna' in p.lockfile['default']
|
|
assert 'urllib3' in p.lockfile['default']
|
|
assert 'certifi' in p.lockfile['default']
|
|
assert 'records' in p.lockfile['default']
|
|
assert 'tpfd' in p.lockfile['default']
|
|
assert 'parse' in p.lockfile['default']
|
|
|
|
c = p.pipenv('run python -c "import requests; import idna; import certifi; import records; import tpfd; import parse;"')
|
|
assert c.return_code == 0
|
|
|
|
@pytest.mark.sequential
|
|
@pytest.mark.install
|
|
def test_sequential_mode(self, pypi):
|
|
|
|
with PipenvInstance(pypi=pypi) as p:
|
|
with open(p.pipfile_path, 'w') as f:
|
|
contents = """
|
|
[packages]
|
|
requests = "*"
|
|
records = "*"
|
|
tpfd = "*"
|
|
""".strip()
|
|
f.write(contents)
|
|
|
|
c = p.pipenv('install --sequential')
|
|
assert c.return_code == 0
|
|
|
|
assert 'requests' in p.lockfile['default']
|
|
assert 'idna' in p.lockfile['default']
|
|
assert 'urllib3' in p.lockfile['default']
|
|
assert 'certifi' in p.lockfile['default']
|
|
assert 'records' in p.lockfile['default']
|
|
assert 'tpfd' in p.lockfile['default']
|
|
assert 'parse' in p.lockfile['default']
|
|
|
|
c = p.pipenv('run python -c "import requests; import idna; import certifi; import records; import tpfd; import parse;"')
|
|
assert c.return_code == 0
|
|
|
|
@pytest.mark.install
|
|
@pytest.mark.resolver
|
|
@pytest.mark.backup_resolver
|
|
def test_backup_resolver(self, pypi):
|
|
with PipenvInstance(pypi=pypi) as p:
|
|
with open(p.pipfile_path, 'w') as f:
|
|
contents = """
|
|
[packages]
|
|
"ibm-db-sa-py3" = "==0.3.1-1"
|
|
""".strip()
|
|
f.write(contents)
|
|
|
|
c = p.pipenv('install')
|
|
assert c.return_code == 0
|
|
assert 'ibm-db-sa-py3' in p.lockfile['default']
|
|
|
|
@pytest.mark.run
|
|
@pytest.mark.markers
|
|
@pytest.mark.install
|
|
def test_package_environment_markers(self):
|
|
|
|
with PipenvInstance() as p:
|
|
with open(p.pipfile_path, 'w') as f:
|
|
contents = """
|
|
[packages]
|
|
requests = {version = "*", markers="os_name=='splashwear'"}
|
|
""".strip()
|
|
f.write(contents)
|
|
|
|
c = p.pipenv('install')
|
|
assert c.return_code == 0
|
|
|
|
assert 'Ignoring' in c.out
|
|
assert 'markers' in p.lockfile['default']['requests']
|
|
|
|
c = p.pipenv('run python -c "import requests;"')
|
|
assert c.return_code == 1
|
|
|
|
@pytest.mark.run
|
|
@pytest.mark.alt
|
|
@pytest.mark.install
|
|
def test_specific_package_environment_markers(self, pypi):
|
|
|
|
with PipenvInstance(pypi=pypi) as p:
|
|
with open(p.pipfile_path, 'w') as f:
|
|
contents = """
|
|
[packages]
|
|
requests = {version = "*", os_name = "== 'splashwear'"}
|
|
""".strip()
|
|
f.write(contents)
|
|
|
|
c = p.pipenv('install')
|
|
assert c.return_code == 0
|
|
|
|
assert 'Ignoring' in c.out
|
|
assert 'markers' in p.lockfile['default']['requests']
|
|
|
|
c = p.pipenv('run python -c "import requests;"')
|
|
assert c.return_code == 1
|
|
|
|
@pytest.mark.install
|
|
@pytest.mark.vcs
|
|
@pytest.mark.tablib
|
|
def test_install_editable_git_tag(self, pip_src_dir, pypi):
|
|
with PipenvInstance(pypi=pypi) as p:
|
|
c = p.pipenv('install -e git+https://github.com/kennethreitz/tablib.git@v0.12.1#egg=tablib')
|
|
assert c.return_code == 0
|
|
assert 'tablib' in p.pipfile['packages']
|
|
assert 'tablib' in p.lockfile['default']
|
|
assert 'git' in p.lockfile['default']['tablib']
|
|
assert p.lockfile['default']['tablib']['git'] == 'https://github.com/kennethreitz/tablib.git'
|
|
assert 'ref' in p.lockfile['default']['tablib']
|
|
|
|
@pytest.mark.run
|
|
@pytest.mark.alt
|
|
@pytest.mark.install
|
|
def test_alternative_version_specifier(self, pypi):
|
|
|
|
with PipenvInstance(pypi=pypi) as p:
|
|
with open(p.pipfile_path, 'w') as f:
|
|
contents = """
|
|
[packages]
|
|
requests = {version = "*"}
|
|
""".strip()
|
|
f.write(contents)
|
|
|
|
c = p.pipenv('install')
|
|
assert c.return_code == 0
|
|
|
|
assert 'requests' in p.lockfile['default']
|
|
assert 'idna' in p.lockfile['default']
|
|
assert 'urllib3' in p.lockfile['default']
|
|
assert 'certifi' in p.lockfile['default']
|
|
assert 'chardet' in p.lockfile['default']
|
|
|
|
c = p.pipenv('run python -c "import requests; import idna; import certifi;"')
|
|
assert c.return_code == 0
|
|
|
|
@pytest.mark.bad
|
|
@pytest.mark.install
|
|
def test_bad_packages(self, pypi):
|
|
|
|
with PipenvInstance(pypi=pypi) as p:
|
|
c = p.pipenv('install NotAPackage')
|
|
assert c.return_code > 0
|
|
|
|
@pytest.mark.dotvenv
|
|
def test_venv_in_project(self, pypi):
|
|
|
|
with temp_environ():
|
|
os.environ['PIPENV_VENV_IN_PROJECT'] = '1'
|
|
with PipenvInstance(pypi=pypi) as p:
|
|
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_reuse_previous_venv(self, pypi):
|
|
with PipenvInstance(chdir=True, pypi=pypi) as p:
|
|
os.mkdir('.venv')
|
|
c = p.pipenv('install requests')
|
|
assert c.return_code == 0
|
|
|
|
assert normalize_drive(p.path) in p.pipenv('--venv').out
|
|
|
|
@pytest.mark.dotvenv
|
|
@pytest.mark.install
|
|
@pytest.mark.complex
|
|
@pytest.mark.shell
|
|
@pytest.mark.windows
|
|
@pytest.mark.pew
|
|
@pytest.mark.skip('Not mocking this.')
|
|
def test_shell_nested_venv_in_project(self, pypi):
|
|
import subprocess
|
|
with temp_environ():
|
|
os.environ['PIPENV_VENV_IN_PROJECT'] = '1'
|
|
os.environ['PIPENV_IGNORE_VIRTUALENVS'] = '1'
|
|
os.environ['PIPENV_SHELL_COMPAT'] = '1'
|
|
with PipenvInstance(chdir=True, pypi=pypi) as p:
|
|
# Signal to pew to look in the project directory for the environment
|
|
os.environ['WORKON_HOME'] = p.path
|
|
project = Project()
|
|
c = p.pipenv('install requests')
|
|
assert c.return_code == 0
|
|
assert 'requests' in p.pipfile['packages']
|
|
assert 'requests' in p.lockfile['default']
|
|
# Check that .venv now shows in pew's managed list
|
|
pew_list = delegator.run('pewtwo ls')
|
|
assert '.venv' in pew_list.out
|
|
# Check for the venv directory
|
|
c = delegator.run('pewtwo dir .venv')
|
|
# Compare pew's virtualenv path to what we expect
|
|
venv_path = get_windows_path(project.project_directory, '.venv')
|
|
# os.path.normpath will normalize slashes
|
|
assert venv_path == normalize_drive(os.path.normpath(c.out.strip()))
|
|
# Have pew run 'pip freeze' in the virtualenv
|
|
# This is functionally the same as spawning a subshell
|
|
# If we can do this we can theoretically make a subshell
|
|
# This test doesn't work on *nix
|
|
if os.name == 'nt':
|
|
args = ['pewtwo', 'in', '.venv', 'pip', 'freeze']
|
|
process = subprocess.Popen(
|
|
args,
|
|
shell=True,
|
|
universal_newlines=True,
|
|
stdin=subprocess.PIPE,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE
|
|
)
|
|
out, _ = process.communicate()
|
|
assert any(req.startswith('requests') for req in out.splitlines()) is True
|
|
|
|
|
|
@pytest.mark.run
|
|
@pytest.mark.dotenv
|
|
def test_env(self):
|
|
|
|
with PipenvInstance(pipfile=False, chdir=True) as p:
|
|
with open('.env', 'w') as f:
|
|
f.write('HELLO=WORLD')
|
|
|
|
c = p.pipenv('run python -c "import os; print(os.environ[\'HELLO\'])"')
|
|
assert c.return_code == 0
|
|
assert 'WORLD' in c.out
|
|
|
|
@pytest.mark.e
|
|
@pytest.mark.install
|
|
@pytest.mark.skip(reason="this doesn't work on windows")
|
|
def test_e_dot(self, pip_src_dir):
|
|
|
|
with PipenvInstance() as p:
|
|
path = os.path.abspath(os.path.sep.join([os.path.dirname(__file__), '..']))
|
|
c = p.pipenv('install -e \'{0}\' --dev'.format(path))
|
|
|
|
assert c.return_code == 0
|
|
|
|
key = [k for k in p.pipfile['dev-packages'].keys()][0]
|
|
assert 'path' in p.pipfile['dev-packages'][key]
|
|
assert 'requests' in p.lockfile['develop']
|
|
|
|
@pytest.mark.code
|
|
@pytest.mark.install
|
|
@pytest.mark.skip(reason='non deterministic')
|
|
def test_code_import_manual(self):
|
|
|
|
with PipenvInstance() as p:
|
|
|
|
with PipenvInstance(chdir=True) as p:
|
|
with open('t.py', 'w') as f:
|
|
f.write('import requests')
|
|
|
|
p.pipenv('install -c .')
|
|
assert 'requests' in p.pipfile['packages']
|
|
|
|
@pytest.mark.code
|
|
@pytest.mark.check
|
|
@pytest.mark.unused
|
|
@pytest.mark.skip(reason="non-deterministic")
|
|
def test_check_unused(self, pypi):
|
|
|
|
with PipenvInstance() as p:
|
|
with PipenvInstance(chdir=True, pypi=pypi) as p:
|
|
with open('__init__.py', 'w') as f:
|
|
contents = """
|
|
import tablib
|
|
import records
|
|
""".strip()
|
|
f.write(contents)
|
|
p.pipenv('install requests')
|
|
p.pipenv('install tablib')
|
|
p.pipenv('install records')
|
|
|
|
assert all(pkg in p.pipfile['packages'] for pkg in ['requests', 'tablib', 'records'])
|
|
|
|
c = p.pipenv('check --unused .')
|
|
assert 'tablib' not in c.out
|
|
|
|
@pytest.mark.extras
|
|
@pytest.mark.install
|
|
@pytest.mark.requirements
|
|
@pytest.mark.skip(reason="Not mocking this.")
|
|
def test_requirements_to_pipfile(self, pypi):
|
|
|
|
with PipenvInstance(pipfile=False, chdir=True, pypi=pypi) as p:
|
|
|
|
# Write a requirements file
|
|
with open('requirements.txt', 'w') as f:
|
|
f.write('requests[socks]==2.18.1\n')
|
|
|
|
c = p.pipenv('install')
|
|
assert c.return_code == 0
|
|
print(c.out)
|
|
print(c.err)
|
|
print(delegator.run('ls -l').out)
|
|
|
|
# assert stuff in pipfile
|
|
assert 'requests' in p.pipfile['packages']
|
|
assert 'extras' in p.pipfile['packages']['requests']
|
|
|
|
# assert stuff in lockfile
|
|
assert 'requests' in p.lockfile['default']
|
|
assert 'chardet' in p.lockfile['default']
|
|
assert 'idna' in p.lockfile['default']
|
|
assert 'urllib3' in p.lockfile['default']
|
|
assert 'pysocks' in p.lockfile['default']
|
|
|
|
@pytest.mark.code
|
|
@pytest.mark.virtualenv
|
|
def test_activate_virtualenv_no_source(self):
|
|
command = activate_virtualenv(source=False)
|
|
venv = Project().virtualenv_location
|
|
|
|
assert command == '{0}/bin/activate'.format(venv)
|
|
|
|
@pytest.mark.lock
|
|
@pytest.mark.requirements
|
|
def test_lock_requirements_file(self, pypi):
|
|
|
|
with PipenvInstance(pypi=pypi) as p:
|
|
with open(p.pipfile_path, 'w') as f:
|
|
contents = """
|
|
[packages]
|
|
requests = "==2.14.0"
|
|
[dev-packages]
|
|
flask = "==0.12.2"
|
|
""".strip()
|
|
f.write(contents)
|
|
|
|
req_list = ("requests==2.14.0")
|
|
|
|
dev_req_list = ("flask==0.12.2")
|
|
|
|
c = p.pipenv('lock -r')
|
|
d = p.pipenv('lock -r -d')
|
|
assert c.return_code == 0
|
|
assert d.return_code == 0
|
|
|
|
for req in req_list:
|
|
assert req in c.out
|
|
|
|
for req in dev_req_list:
|
|
assert req in d.out
|
|
|
|
@pytest.mark.lock
|
|
@pytest.mark.complex
|
|
def test_complex_lock_with_vcs_deps(self, pip_src_dir, pypi):
|
|
|
|
with PipenvInstance(pypi=pypi) as p:
|
|
with open(p.pipfile_path, 'w') as f:
|
|
contents = """
|
|
[packages]
|
|
click = "==6.7"
|
|
|
|
[dev-packages]
|
|
requests = {git = "https://github.com/requests/requests", egg = "requests"}
|
|
""".strip()
|
|
f.write(contents)
|
|
|
|
c = p.pipenv('install')
|
|
assert c.return_code == 0
|
|
lock = p.lockfile
|
|
assert 'requests' in lock['develop']
|
|
assert 'click' in lock['default']
|
|
|
|
c = p.pipenv('run pip install -e git+https://github.com/dateutil/dateutil#egg=python_dateutil')
|
|
assert c.return_code == 0
|
|
|
|
c = p.pipenv('lock')
|
|
assert c.return_code == 0
|
|
lock = p.lockfile
|
|
assert 'requests' in lock['develop']
|
|
assert 'click' in lock['default']
|
|
assert 'python_dateutil' not in lock['default']
|
|
assert 'python_dateutil' not in lock['develop']
|
|
|
|
@pytest.mark.lock
|
|
@pytest.mark.requirements
|
|
@pytest.mark.complex
|
|
@pytest.mark.maya
|
|
def test_complex_deps_lock_and_install_properly(self, pypi):
|
|
|
|
with PipenvInstance(pypi=pypi) as p:
|
|
with open(p.pipfile_path, 'w') as f:
|
|
contents = """
|
|
[packages]
|
|
maya = "*"
|
|
""".strip()
|
|
f.write(contents)
|
|
|
|
c = p.pipenv('lock')
|
|
assert c.return_code == 0
|
|
|
|
c = p.pipenv('install')
|
|
assert c.return_code == 0
|
|
|
|
@pytest.mark.extras
|
|
@pytest.mark.lock
|
|
@pytest.mark.requirements
|
|
@pytest.mark.complex
|
|
def test_complex_lock_deep_extras(self, pypi):
|
|
# records[pandas] requires tablib[pandas] which requires pandas.
|
|
|
|
with PipenvInstance(pypi=pypi) as p:
|
|
with open(p.pipfile_path, 'w') as f:
|
|
contents = """
|
|
[packages]
|
|
records = {extras = ["pandas"], version = "==0.5.2"}
|
|
""".strip()
|
|
f.write(contents)
|
|
|
|
c = p.pipenv('lock')
|
|
assert c.return_code == 0
|
|
assert 'tablib' in p.lockfile['default']
|
|
assert 'pandas' in p.lockfile['default']
|
|
c = p.pipenv('install')
|
|
assert c.return_code == 0
|
|
|
|
@pytest.mark.lock
|
|
@pytest.mark.deploy
|
|
def test_deploy_works(self, pypi):
|
|
|
|
with PipenvInstance(pypi=pypi) as p:
|
|
with open(p.pipfile_path, 'w') as f:
|
|
contents = """
|
|
[packages]
|
|
requests = "==2.14.0"
|
|
flask = "==0.12.2"
|
|
[dev-packages]
|
|
pytest = "==3.1.1"
|
|
""".strip()
|
|
f.write(contents)
|
|
|
|
p.pipenv('lock')
|
|
|
|
with open(p.pipfile_path, 'w') as f:
|
|
contents = """
|
|
[packages]
|
|
requests = "==2.14.0"
|
|
""".strip()
|
|
f.write(contents)
|
|
|
|
c = p.pipenv('install --deploy')
|
|
assert c.return_code > 0
|
|
|
|
@pytest.mark.install
|
|
@pytest.mark.files
|
|
@pytest.mark.urls
|
|
def test_urls_work(self, pypi):
|
|
|
|
with PipenvInstance(pypi=pypi) as p:
|
|
|
|
c = p.pipenv('install https://github.com/divio/django-cms/archive/release/3.4.x.zip')
|
|
key = [k for k in p.pipfile['packages'].keys()][0]
|
|
dep = p.pipfile['packages'][key]
|
|
|
|
assert 'file' in dep
|
|
assert c.return_code == 0
|
|
|
|
key = [k for k in p.lockfile['default'].keys()][0]
|
|
dep = p.lockfile['default'][key]
|
|
|
|
assert 'file' in dep
|
|
|
|
@pytest.mark.install
|
|
@pytest.mark.files
|
|
@pytest.mark.resolver
|
|
@pytest.mark.eggs
|
|
def test_local_package(self, pip_src_dir):
|
|
"""This test ensures that local packages (directories with a setup.py)
|
|
installed in editable mode have their dependencies resolved as well"""
|
|
file_name = 'tablib-0.12.1.tar.gz'
|
|
package = 'tablib-0.12.1'
|
|
# Not sure where travis/appveyor run tests from
|
|
test_dir = os.path.dirname(os.path.abspath(__file__))
|
|
source_path = os.path.abspath(os.path.join(test_dir, 'test_artifacts', file_name))
|
|
with PipenvInstance() as p:
|
|
# This tests for a bug when installing a zipfile in the current dir
|
|
copy_to = os.path.join(p.path, file_name)
|
|
shutil.copy(source_path, copy_to)
|
|
import tarfile
|
|
with tarfile.open(copy_to, 'r:gz') as tgz:
|
|
tgz.extractall(path=p.path)
|
|
c = p.pipenv('install -e {0}'.format(package))
|
|
assert c.return_code == 0
|
|
assert all(pkg in p.lockfile['default'] for pkg in ['xlrd', 'xlwt', 'pyyaml', 'odfpy'])
|
|
|
|
|
|
@pytest.mark.install
|
|
@pytest.mark.files
|
|
def test_local_zipfiles(self):
|
|
file_name = 'tablib-0.12.1.tar.gz'
|
|
# Not sure where travis/appveyor run tests from
|
|
test_dir = os.path.dirname(os.path.abspath(__file__))
|
|
source_path = os.path.abspath(os.path.join(test_dir, 'test_artifacts', file_name))
|
|
|
|
with PipenvInstance() as p:
|
|
# This tests for a bug when installing a zipfile in the current dir
|
|
shutil.copy(source_path, os.path.join(p.path, file_name))
|
|
|
|
c = p.pipenv('install {}'.format(file_name))
|
|
key = [k for k in p.pipfile['packages'].keys()][0]
|
|
dep = p.pipfile['packages'][key]
|
|
|
|
assert 'file' in dep or 'path' in dep
|
|
assert c.return_code == 0
|
|
|
|
key = [k for k in p.lockfile['default'].keys()][0]
|
|
dep = p.lockfile['default'][key]
|
|
|
|
assert 'file' in dep or 'path' in dep
|
|
|
|
|
|
@pytest.mark.install
|
|
@pytest.mark.files
|
|
@pytest.mark.urls
|
|
def test_install_remote_requirements(self, pypi):
|
|
with PipenvInstance(pypi=pypi) as p:
|
|
# using a github hosted requirements.txt file
|
|
c = p.pipenv('install -r https://raw.githubusercontent.com/kennethreitz/pipenv/3688148ac7cfecefb085c474b092c31d791952c1/tests/test_artifacts/requirements.txt')
|
|
|
|
assert c.return_code == 0
|
|
# check Pipfile with versions
|
|
assert 'requests' in p.pipfile['packages']
|
|
assert p.pipfile['packages']['requests'] == u'==2.18.4'
|
|
assert 'records' in p.pipfile['packages']
|
|
assert p.pipfile['packages']['records'] == u'==0.5.2'
|
|
|
|
# check Pipfile.lock
|
|
assert 'requests' in p.lockfile['default']
|
|
assert 'records' in p.lockfile['default']
|
|
|
|
|
|
@pytest.mark.install
|
|
@pytest.mark.files
|
|
def test_relative_paths(self, pypi):
|
|
file_name = 'tablib-0.12.1.tar.gz'
|
|
test_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)))
|
|
source_path = os.path.abspath(os.path.join(test_dir, 'test_artifacts', file_name))
|
|
|
|
with PipenvInstance(pypi=pypi) as p:
|
|
artifact_dir = 'artifacts'
|
|
artifact_path = os.path.join(p.path, artifact_dir)
|
|
mkdir_p(artifact_path)
|
|
shutil.copy(source_path, os.path.join(artifact_path, file_name))
|
|
# Test installing a relative path in a subdirectory
|
|
c = p.pipenv('install {}/{}'.format(artifact_dir, file_name))
|
|
key = [k for k in p.pipfile['packages'].keys()][0]
|
|
dep = p.pipfile['packages'][key]
|
|
|
|
assert 'path' in dep
|
|
assert Path(os.path.join('.', artifact_dir, file_name)) == Path(dep['path'])
|
|
assert c.return_code == 0
|
|
|
|
@pytest.mark.install
|
|
@pytest.mark.local_file
|
|
def test_install_local_file_collision(self, pypi):
|
|
with PipenvInstance(pypi=pypi) as p:
|
|
target_package = 'alembic'
|
|
fake_file = os.path.join(p.path, target_package)
|
|
with open(fake_file, 'w') as f:
|
|
f.write('')
|
|
c = p.pipenv('install {}'.format(target_package))
|
|
assert c.return_code == 0
|
|
assert target_package in p.pipfile['packages']
|
|
assert p.pipfile['packages'][target_package] == '*'
|
|
assert target_package in p.lockfile['default']
|
|
|
|
@pytest.mark.clean
|
|
def test_clean_on_empty_venv(self, pypi):
|
|
with PipenvInstance(pypi=pypi) as p:
|
|
c = p.pipenv('clean')
|
|
assert c.return_code == 0
|