Merge branch 'master' into patch-2

This commit is contained in:
Dan Ryan
2018-03-30 19:11:34 -04:00
committed by GitHub
14 changed files with 146 additions and 89 deletions
-6
View File
@@ -503,9 +503,6 @@ def lock(
# Ensure that virtualenv is available.
core.ensure_project(three=three, python=python)
# Load the --pre settings from the Pipfile.
if not pre:
pre = core.project.settings.get('pre')
if requirements:
core.do_init(dev=dev, requirements=requirements)
core.do_lock(
@@ -739,9 +736,6 @@ def update(
crayons.white('.', bold=True),
)
)
# Load the --pre settings from the Pipfile.
if not pre:
pre = core.project.settings.get('pre')
core.do_lock(
verbose=verbose, clear=clear, pre=pre, keep_outdated=keep_outdated
)
+11 -9
View File
@@ -1011,6 +1011,8 @@ def do_lock(
from notpip._vendor.distlib.markers import Evaluator
allowed_marker_keys = ['markers'] + [k for k in Evaluator.allowed_values.keys()]
cached_lockfile = {}
if not pre:
pre = project.settings.get('allow_prereleases')
if keep_outdated:
if not project.lockfile_exists:
click.echo(
@@ -1634,8 +1636,11 @@ def warn_in_virtualenv():
click.echo(
'{0}: Pipenv found itself running within a virtual environment, '
'so it will automatically use that environment, instead of '
'creating its own for any project.'.format(
crayons.green('Courtesy Notice')
'creating its own for any project. You can set '
'{1} to force pipenv to ignore that environment and create '
'its own instead.'.format(
crayons.green('Courtesy Notice'),
crayons.normal('PIPENV_IGNORE_VIRTUALENVS=1', bold=True),
),
err=True,
)
@@ -1643,7 +1648,6 @@ def warn_in_virtualenv():
def ensure_lockfile(keep_outdated=False):
"""Ensures that the lockfile is uptodate."""
pre = project.settings.get('allow_prereleases')
if not keep_outdated:
keep_outdated = project.settings.get('keep_outdated')
# Write out the lockfile if it doesn't exist, but not if the Pipfile is being ignored
@@ -1660,9 +1664,9 @@ def ensure_lockfile(keep_outdated=False):
),
err=True,
)
do_lock(pre=pre, keep_outdated=keep_outdated)
do_lock(keep_outdated=keep_outdated)
else:
do_lock(pre=pre, keep_outdated=keep_outdated)
do_lock(keep_outdated=keep_outdated)
def do_py(system=False):
@@ -2017,8 +2021,6 @@ def do_uninstall(
system = True
# Ensure that virtualenv is available.
ensure_project(three=three, python=python)
# Load the --pre settings from the Pipfile.
pre = project.settings.get('allow_prereleases')
package_names = (package_name,) + more_packages
pipfile_remove = True
# Un-install all dependencies, if --all was provided.
@@ -2085,7 +2087,7 @@ def do_uninstall(
project.remove_package_from_pipfile(package_name, dev=True)
project.remove_package_from_pipfile(package_name, dev=False)
if lock:
do_lock(system=system, pre=pre, keep_outdated=keep_outdated)
do_lock(system=system, keep_outdated=keep_outdated)
def do_shell(three=None, python=False, fancy=False, shell_args=None):
@@ -2183,7 +2185,7 @@ def inline_activate_virtualenv():
activate_this = which('activate_this.py')
with open(activate_this) as f:
code = compile(f.read(), activate_this, 'exec')
exec (code, dict(__file__=activate_this))
exec(code, dict(__file__=activate_this))
# Catch all errors, just in case.
except Exception:
click.echo(
+1 -1
View File
@@ -231,7 +231,7 @@ class TOMLFile:
if has_anonymous_entry():
return items
else:
return items + [('', self[''])]
return list(items) + [('', self[''])]
@property
def primitive(self):
+8 -1
View File
@@ -9,6 +9,13 @@ import sys
import os
DEFAULT_SOURCE = {
u'url': u'https://pypi.python.org/simple',
u'verify_ssl': True,
u'name': u'pypi',
}
def format_full_version(info):
version = '{0.major}.{0.minor}.{0.micro}'.format(info)
kind = info.releaselevel
@@ -89,7 +96,7 @@ class PipfileParser(object):
# Load the default configuration.
default_config = {
u'source': [{u'url': u'https://pypi.python.org/simple', u'verify_ssl': True, 'name': "pypi"}],
u'source': [DEFAULT_SOURCE],
u'packages': {},
u'requires': {},
u'dev-packages': {}
+36 -36
View File
@@ -12,6 +12,7 @@ import hashlib
import contoml
import delegator
import pipfile
import pipfile.api
import toml
from pip9 import ConfigOptionParser
@@ -51,6 +52,26 @@ if PIPENV_PIPFILE:
_pipfile_cache = {}
if PIPENV_TEST_INDEX:
DEFAULT_SOURCE = {
u'url': PIPENV_TEST_INDEX,
u'verify_ssl': True,
u'name': u'custom',
}
else:
DEFAULT_SOURCE = {
u'url': u'https://pypi.python.org/simple',
u'verify_ssl': True,
u'name': u'pypi',
}
pipfile.api.DEFAULT_SOURCE = DEFAULT_SOURCE
class SourceNotFound(KeyError):
pass
class Project(object):
"""docstring for Project"""
@@ -490,35 +511,20 @@ class Project(object):
config_parser = ConfigOptionParser(name=self.name)
install = dict(config_parser.get_config_section('install'))
indexes = install.get('extra-index-url', '').lstrip('\n').split('\n')
if PIPENV_TEST_INDEX:
sources = [
{
u'url': PIPENV_TEST_INDEX,
u'verify_ssl': True,
u'name': u'custom',
}
]
else:
# Default source.
pypi_source = {
u'url': u'https://pypi.python.org/simple',
u'verify_ssl': True,
u'name': 'pypi',
}
sources = [pypi_source]
for i, index in enumerate(indexes):
if not index:
continue
sources = [DEFAULT_SOURCE]
for i, index in enumerate(indexes):
if not index:
continue
source_name = 'pip_index_{}'.format(i)
verify_ssl = index.startswith('https')
sources.append(
{
u'url': index,
u'verify_ssl': verify_ssl,
u'name': source_name,
}
)
source_name = 'pip_index_{}'.format(i)
verify_ssl = index.startswith('https')
sources.append(
{
u'url': index,
u'verify_ssl': verify_ssl,
u'name': source_name,
}
)
data = {
u'source': sources,
# Default packages.
@@ -565,15 +571,8 @@ class Project(object):
if 'source' in self.parsed_pipfile:
return self.parsed_pipfile['source']
else:
return [
{
u'url': u'https://pypi.python.org/simple',
u'verify_ssl': True,
'name': 'pypi',
}
]
return [DEFAULT_SOURCE]
def get_source(self, name=None, url=None):
for source in self.sources:
@@ -584,6 +583,7 @@ class Project(object):
elif url:
if source.get('url') in url:
return source
raise SourceNotFound(name or url)
def destroy_lockfile(self):
"""Deletes the lockfile."""
+1 -1
View File
@@ -1207,7 +1207,7 @@ class TemporaryDirectory(object):
in it are removed.
"""
def __init__(self, suffix=None, prefix=None, dir=None):
def __init__(self, suffix, prefix, dir=None):
if 'RAM_DISK' in os.environ:
import uuid
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -6,7 +6,6 @@ Home-page: https://github.com/kennethreitz/pytest-pypi
Author: Kenneth Reitz
Author-email: me@kennethreitz.org
License: MIT
Description-Content-Type: UNKNOWN
Description: pytest-httpbin
==============
+89 -34
View File
@@ -11,6 +11,7 @@ from pipenv.utils import (
)
from pipenv.vendor import toml
from pipenv.vendor import delegator
from pipenv.vendor import requests
from pipenv.patched import pipfile
from pipenv.project import Project
from pipenv.vendor.six import PY2
@@ -23,15 +24,31 @@ try:
except ImportError:
from pipenv.vendor.pathlib2 import Path
py3_only = pytest.mark.skipif(sys.version_info < (3, 0), reason="requires Python3")
nix_only = pytest.mark.skipif(os.name != 'nt', reason="doesn't run on windows")
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'])
def check_internet():
try:
# Kenneth represents the Internet LGTM.
resp = requests.get('http://httpbin.org/ip', timeout=1.0)
resp.raise_for_status()
except Exception:
warnings.warn('Cannot connect to HTTPBin...', ResourceWarning)
warnings.warn('Will skip tests requiring Internet', ResourceWarning)
return False
return True
WE_HAVE_INTERNET = check_internet()
needs_internet = pytest.mark.skipif(not WE_HAVE_INTERNET, reason='requires internet')
py3_only = pytest.mark.skipif(sys.version_info < (3, 0), reason="requires Python3")
nix_only = pytest.mark.skipif(os.name != 'nt', reason="doesn't run on windows")
@pytest.fixture(scope='module')
def pip_src_dir(request):
old_src_dir = os.environ.get('PIP_SRC', '')
@@ -46,13 +63,16 @@ def pip_src_dir(request):
return request
class PipenvInstance():
VERBOSE_COMMANDS = ('install', 'lock', 'uninstall')
class PipenvInstance(object):
"""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 = TemporaryDirectory(suffix='-project', prefix='pipenv-')
self.path = self._path.name
# set file creation perms
self.pipfile_path = None
@@ -91,7 +111,11 @@ class PipenvInstance():
if self.pipfile_path:
os.environ['PIPENV_PIPFILE'] = self.pipfile_path
c = delegator.run('pipenv {0}'.format(cmd), block=block)
with TemporaryDirectory(prefix='pipenv-', suffix='-cache') as tempdir:
os.environ['PIPENV_CACHE_DIR'] = tempdir.name
c = delegator.run('pipenv {0}'.format(cmd), block=block)
if 'PIPENV_CACHE_DIR' in os.environ:
del os.environ['PIPENV_CACHE_DIR']
if 'PIPENV_PIPFILE' in os.environ:
del os.environ['PIPENV_PIPFILE']
@@ -182,6 +206,7 @@ class TestPipenv:
assert 'Warning: Using both --reverse and --json together is not supported.' in c.err
@pytest.mark.cli
@needs_internet
def test_pipenv_check(self, pypi):
with PipenvInstance(pypi=pypi) as p:
p.pipenv('install requests==1.0.0')
@@ -354,7 +379,8 @@ tablib = "*"
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
c = p.pipenv('uninstall --all')
assert c.return_code == 0
assert 'tablib' in c.out
assert 'tablib' not in p.pipfile['packages']
@@ -442,7 +468,8 @@ setup(
@pytest.mark.vcs
@pytest.mark.install
def test_basic_vcs_install(self, pypi):
@needs_internet
def test_basic_vcs_install(self, pip_src_dir, 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
@@ -457,6 +484,7 @@ setup(
@pytest.mark.e
@pytest.mark.vcs
@pytest.mark.install
@needs_internet
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')
@@ -546,8 +574,9 @@ tpfd = "*"
@pytest.mark.install
@pytest.mark.resolver
@pytest.mark.backup_resolver
def test_backup_resolver(self, pypi):
with PipenvInstance(pypi=pypi) as p:
@needs_internet
def test_backup_resolver(self):
with PipenvInstance() as p:
with open(p.pipfile_path, 'w') as f:
contents = """
[packages]
@@ -561,8 +590,6 @@ tpfd = "*"
@pytest.mark.run
@pytest.mark.markers
@pytest.mark.install
@pytest.mark.failed
def test_package_environment_markers(self, pypi):
with PipenvInstance(pypi=pypi) as p:
@@ -605,10 +632,10 @@ requests = {version = "*", os_name = "== 'splashwear'"}
@pytest.mark.markers
@pytest.mark.install
def test_top_level_overrides_environment_markers(self):
def test_top_level_overrides_environment_markers(self, pypi):
"""Top-level environment markers should take precedence.
"""
with PipenvInstance() as p:
with PipenvInstance(pypi=pypi) as p:
with open(p.pipfile_path, 'w') as f:
contents = """
[packages]
@@ -624,7 +651,7 @@ funcsigs = {version = "*", os_name = "== 'splashwear'"}
@pytest.mark.markers
@pytest.mark.install
def test_global_overrides_environment_markers(self):
def test_global_overrides_environment_markers(self, pypi):
"""Empty (unconditional) dependency should take precedence.
If a dependency is specified without environment markers, it should
@@ -632,7 +659,7 @@ funcsigs = {version = "*", os_name = "== 'splashwear'"}
APScheduler requires funcsigs only on Python 2, but since funcsigs is
also specified as an unconditional dep, its markers should be empty.
"""
with PipenvInstance() as p:
with PipenvInstance(pypi=pypi) as p:
with open(p.pipfile_path, 'w') as f:
contents = """
[packages]
@@ -649,8 +676,11 @@ funcsigs = "*"
@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:
@needs_internet
def test_install_editable_git_tag(self, pip_src_dir):
# This uses the real PyPI since we need Internet to access the Git
# dependency anyway.
with PipenvInstance() 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']
@@ -923,9 +953,11 @@ flask = "==0.12.2"
@pytest.mark.lock
@pytest.mark.complex
def test_complex_lock_with_vcs_deps(self, pip_src_dir, pypi):
with PipenvInstance(pypi=pypi) as p:
@needs_internet
def test_complex_lock_with_vcs_deps(self, pip_src_dir):
# This uses the real PyPI since we need Internet to access the Git
# dependency anyway.
with PipenvInstance() as p:
with open(p.pipfile_path, 'w') as f:
contents = """
[packages]
@@ -955,14 +987,34 @@ requests = {git = "https://github.com/requests/requests", egg = "requests"}
@pytest.mark.lock
@pytest.mark.requirements
@pytest.mark.complex
@pytest.mark.maya
def test_complex_deps_lock_and_install_properly(self, pypi):
def test_lock_with_prereleases(self, pypi):
with PipenvInstance(pypi=pypi) as p:
with open(p.pipfile_path, 'w') as f:
contents = """
[packages]
sqlalchemy = "==1.2.0b3"
[pipenv]
allow_prereleases = true
""".strip()
f.write(contents)
c = p.pipenv('lock')
assert c.return_code == 0
assert p.lockfile['default']['sqlalchemy']['version'] == '==1.2.0b3'
@pytest.mark.lock
@pytest.mark.requirements
@pytest.mark.complex
@pytest.mark.maya
@needs_internet
def test_complex_deps_lock_and_install_properly(self):
# This uses the real PyPI because Maya has too many dependencies...
with PipenvInstance() as p:
with open(p.pipfile_path, 'w') as f:
contents = """
[packages]
maya = "*"
""".strip()
f.write(contents)
@@ -975,12 +1027,13 @@ maya = "*"
@pytest.mark.extras
@pytest.mark.lock
@pytest.mark.requirements
@pytest.mark.complex
def test_complex_lock_deep_extras(self, pypi):
@needs_internet
def test_complex_lock_deep_extras(self):
# records[pandas] requires tablib[pandas] which requires pandas.
# This uses the real PyPI; Pandas has too many requirements to mock.
with PipenvInstance(pypi=pypi) as p:
with PipenvInstance() as p:
with open(p.pipfile_path, 'w') as f:
contents = """
[packages]
@@ -988,12 +1041,12 @@ records = {extras = ["pandas"], version = "==0.5.2"}
""".strip()
f.write(contents)
c = p.pipenv('install')
assert c.return_code == 0
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
@@ -1009,9 +1062,10 @@ flask = "==0.12.2"
pytest = "==3.1.1"
""".strip()
f.write(contents)
p.pipenv('lock')
c = p.pipenv('install')
assert c.return_code == 0
c = p.pipenv('lock')
assert c.return_code == 0
with open(p.pipfile_path, 'w') as f:
contents = """
[packages]
@@ -1025,6 +1079,7 @@ requests = "==2.14.0"
@pytest.mark.install
@pytest.mark.files
@pytest.mark.urls
@needs_internet
def test_urls_work(self, pypi):
with PipenvInstance(pypi=pypi) as p:
@@ -1077,6 +1132,7 @@ requests = "==2.14.0"
shutil.copy(source_path, os.path.join(p.path, file_name))
c = p.pipenv('install {}'.format(file_name))
assert c.return_code == 0
key = [k for k in p.pipfile['packages'].keys()][0]
dep = p.pipfile['packages'][key]
@@ -1091,6 +1147,7 @@ requests = "==2.14.0"
@pytest.mark.install
@pytest.mark.files
@pytest.mark.urls
@needs_internet
def test_install_remote_requirements(self, pypi):
with PipenvInstance(pypi=pypi) as p:
# using a github hosted requirements.txt file
@@ -1158,10 +1215,8 @@ requests = "==2.14.0"
url = 'https://${PYPI_USERNAME}:${PYPI_PASSWORD}@pypi.python.org/simple'
verify_ssl = true
name = 'pypi'
[requires]
python_version = '2.7'
[packages]
flask = "==0.12.2"
""")