Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Dan Ryan
2017-09-07 23:16:02 -04:00
10 changed files with 119 additions and 53 deletions
+12
View File
@@ -1,3 +1,15 @@
6.1.5:
- Grab hashes for un-grabbable hashes.
6.1.4:
- New update via $ pipenv --update, instead.
6.1.3:
- Skip validation of Pipfiles, massive speedup for far-away users.
- Other speed-ups.
6.1.1:
- Bug fix.
6.1.0:
- Selfupdating! Very fancy. $ pipenv update.
- Verbose mode for update, install.
6.0.3:
- Major bug fix.
- Fix for Daniel Ryan's weird corner case.
+1 -1
View File
@@ -48,7 +48,7 @@ install:
# about it being out of date.
- "pip install --disable-pip-version-check --user --upgrade pip"
- "pip install -e . --upgrade"
- "pipenv install --dev"
- "pipenv install --dev --skip-lock"
test_script:
- "pipenv run pytest test_windows/ tests/test_utils.py tests/test_project.py"
-1
View File
@@ -253,7 +253,6 @@ $ pipenv lock
variables. To activate them, simply create the variable in your shell and pipenv
will detect it.
- ``PIPENV_SKIP_VALIDATION`` — Tells Pipenv to skip ``Pipfile`` validation (case-checking) — useful for slow internet connections.
- ``PIPENV_SHELL_COMPAT`` — Toggle from our default ``pipenv shell`` mode to classic.
(Suggested for use with pyenv).
+1 -1
View File
@@ -3,4 +3,4 @@
# //___/ / / / //___/ / // // / / || / /
# // / / // ((____ // / / ||/ /
__version__ = '6.0.3'
__version__ = '6.1.5'
+84 -29
View File
@@ -73,14 +73,45 @@ def check_for_updates():
current = semver.parse_version_info(__version__)
if latest > current:
click.echo('{0}: {1} is now available. You get bonus points for upgrading!'.format(
click.echo('{0}: {1} is now available. You get bonus points for upgrading ($ {})!'.format(
crayons.green('Courtesy Notice'),
crayons.yellow('Pipenv v{v.major}.{v.minor}.{v.patch}'.format(v=latest)),
crayons.yellow('Pipenv {v.major}.{v.minor}.{v.patch}'.format(v=latest)),
crayons.red('pipenv --update')
), err=True)
except Exception:
pass
def enhance(user=False):
r = requests.get('https://pypi.python.org/pypi/pipenv/json', timeout=0.5)
latest = sorted([semver.parse_version_info(v) for v in list(r.json()['releases'].keys())])[-1]
current = semver.parse_version_info(__version__)
if current < latest:
import site
click.echo('{0}: {1} is now available. Automatically upgrading!'.format(
crayons.green('Courtesy Notice'),
crayons.yellow('Pipenv {v.major}.{v.minor}.{v.patch}'.format(v=latest)),
), err=True)
# Resolve user site, enable user mode automatically.
if site.ENABLE_USER_SITE and site.USER_SITE in sys.modules['pipenv'].__file__:
args = ['install', '--upgrade', 'pipenv']
else:
args = ['install', '--user', '--upgrade', 'pipenv']
sys.modules['pip'].main(args)
click.echo('{0} to {1}!'.format(
crayons.green('Pipenv updated'),
crayons.yellow('{v.major}.{v.minor}.{v.patch}'.format(v=latest))
))
else:
click.echo(crayons.green('All good!'))
def cleanup_virtualenv(bare=True):
"""Removes the virtualenv directory from the system."""
@@ -104,7 +135,10 @@ def ensure_latest_pip():
if 'however' in c.err:
# If version is out of date, update.
click.echo(crayons.yellow('Pip is out of date... updating to latest.'))
c = delegator.run('"{0}" install pip --upgrade'.format(which_pip()), block=False)
windows = '-m' if os.name == 'nt' else ''
c = delegator.run('"{0}" install {1} pip --upgrade'.format(which_pip()), windows, block=False)
click.echo(crayons.blue(c.out))
@@ -135,6 +169,8 @@ def ensure_pipfile(validate=True):
else:
project.add_package_to_pipfile(str(package.req))
project.recase_pipfile()
else:
click.echo(crayons.yellow('Creating a Pipfile for this project...'), err=True)
# Create the pipfile if it doesn't exist.
@@ -242,7 +278,7 @@ def do_where(virtualenv=False, bare=True):
click.echo(location)
def do_install_dependencies(dev=False, only=False, bare=False, requirements=False, allow_global=False, ignore_hashes=False, skip_lock=False):
def do_install_dependencies(dev=False, only=False, bare=False, requirements=False, allow_global=False, ignore_hashes=False, skip_lock=False, verbose=False):
""""Executes the install functionality."""
if requirements:
@@ -259,6 +295,7 @@ def do_install_dependencies(dev=False, only=False, bare=False, requirements=Fals
with open(project.lockfile_location) as f:
lockfile = split_vcs(json.load(f))
# Allow pip to resolve dependencies when in skip-lock mode.
no_deps = (not skip_lock)
# Install default dependencies, always.
@@ -289,7 +326,7 @@ def do_install_dependencies(dev=False, only=False, bare=False, requirements=Fals
# pip install:
for dep, ignore_hash in progress.bar(deps_list):
c = pip_install(dep, ignore_hashes=ignore_hash, allow_global=allow_global, no_deps=no_deps)
c = pip_install(dep, ignore_hashes=ignore_hash, allow_global=allow_global, no_deps=no_deps, verbose=verbose)
if c.return_code != 0:
click.echo(crayons.red('An error occured while installing!'))
@@ -620,7 +657,7 @@ def do_purge(bare=False, downloads=False, allow_global=False):
click.echo(crayons.yellow('Environment now purged and fresh!'))
def do_init(dev=False, requirements=False, allow_global=False, ignore_hashes=False, no_hashes=True, ignore_pipfile=False, skip_lock=False):
def do_init(dev=False, requirements=False, allow_global=False, ignore_hashes=False, no_hashes=True, ignore_pipfile=False, skip_lock=False, verbose=False):
"""Executes the init functionality."""
ensure_pipfile()
@@ -663,14 +700,14 @@ def do_init(dev=False, requirements=False, allow_global=False, ignore_hashes=Fal
ignore_hashes = False
do_install_dependencies(dev=dev, requirements=requirements, allow_global=allow_global,
ignore_hashes=ignore_hashes, skip_lock=skip_lock)
ignore_hashes=ignore_hashes, skip_lock=skip_lock, verbose=verbose)
# Activate virtualenv instructions.
if not allow_global:
do_activate_virtualenv()
def pip_install(package_name=None, r=None, allow_global=False, ignore_hashes=False, no_deps=True):
def pip_install(package_name=None, r=None, allow_global=False, ignore_hashes=False, no_deps=True, verbose=False):
# Create files for hash mode.
if (not ignore_hashes) and (r is None):
@@ -702,6 +739,10 @@ def pip_install(package_name=None, r=None, allow_global=False, ignore_hashes=Fal
no_deps = '--no-deps' if no_deps else ''
pip_command = '"{0}" install {3} {1} -i {2}'.format(which_pip(allow_global=allow_global), install_reqs, source['url'], no_deps)
if verbose:
click.echo('$ {0}'.format(pip_command), err=True)
c = delegator.run(pip_command)
if c.return_code == 0:
@@ -804,6 +845,7 @@ def easter_egg(package_name):
@click.group(invoke_without_command=True)
@click.option('--update', is_flag=True, default=False, help="Upate pipenv & pip.")
@click.option('--where', is_flag=True, default=False, help="Output project home information.")
@click.option('--venv', is_flag=True, default=False, help="Output virtualenv information.")
@click.option('--rm', is_flag=True, default=False, help="Remove the virtualenv.")
@@ -813,9 +855,18 @@ def easter_egg(package_name):
@click.option('--help', '-h', is_flag=True, default=None, help="Show this message then exit.")
@click.version_option(prog_name=crayons.yellow('pipenv'), version=__version__)
@click.pass_context
def cli(ctx, where=False, venv=False, rm=False, bare=False, three=False, python=False, help=False):
def cli(ctx, where=False, venv=False, rm=False, bare=False, three=False, python=False, help=False, update=False):
check_for_updates()
if not update:
check_for_updates()
else:
# Update pip to latest version.
ensure_latest_pip()
# Upgrade self to latest version.
enhance()
sys.exit()
if ctx.invoked_subcommand is None:
# --where was passed...
@@ -869,9 +920,10 @@ def cli(ctx, where=False, venv=False, rm=False, bare=False, three=False, python=
@click.option('--three/--two', is_flag=True, default=None, help="Use Python 3/2 when creating virtualenv.")
@click.option('--python', default=False, nargs=1, help="Specify which version of Python virtualenv should use.")
@click.option('--system', is_flag=True, default=False, help="System pip management.")
@click.option('--verbose', is_flag=True, default=False, help="Verbose mode.")
@click.option('--ignore-pipfile', is_flag=True, default=False, help="Ignore Pipfile when installing, using the Pipfile.lock.")
@click.option('--skip-lock', is_flag=True, default=False, help=u"Ignore locking mechanisms when installing—use the Pipfile, instead.")
def install(package_name=False, more_packages=False, dev=False, three=False, python=False, system=False, lock=True, hashes=True, ignore_pipfile=False, skip_lock=False):
def install(package_name=False, more_packages=False, dev=False, three=False, python=False, system=False, lock=True, hashes=True, ignore_pipfile=False, skip_lock=False, verbose=False):
# Automatically use an activated virtualenv.
if PIPENV_USE_SYSTEM:
@@ -895,7 +947,7 @@ def install(package_name=False, more_packages=False, dev=False, three=False, pyt
if package_name is False:
click.echo(crayons.yellow('No package provided, installing all dependencies.'), err=True)
do_init(dev=dev, allow_global=system, ignore_hashes=not hashes, ignore_pipfile=ignore_pipfile, skip_lock=skip_lock)
do_init(dev=dev, allow_global=system, ignore_hashes=not hashes, ignore_pipfile=ignore_pipfile, skip_lock=skip_lock, verbose=verbose)
sys.exit(0)
for package_name in package_names:
@@ -903,7 +955,7 @@ def install(package_name=False, more_packages=False, dev=False, three=False, pyt
# pip install:
with spinner():
c = pip_install(package_name, ignore_hashes=True, allow_global=system, no_deps=False)
c = pip_install(package_name, ignore_hashes=True, allow_global=system, no_deps=False, verbose=verbose)
click.echo(crayons.blue(format_pip_output(c.out)))
@@ -1152,6 +1204,7 @@ def run(command, args, three=None, python=False):
@click.option('--three/--two', is_flag=True, default=None, help="Use Python 3/2 when creating virtualenv.")
@click.option('--python', default=False, nargs=1, help="Specify which version of Python virtualenv should use.")
def check(three=None, python=False):
# Ensure that virtualenv is available.
ensure_project(three=three, python=python, validate=False)
@@ -1181,27 +1234,29 @@ def check(three=None, python=False):
click.echo(crayons.green('Passed!'))
@click.command(help="Updates pip to latest version, uninstalls all packages, and re-installs package(s) in [packages] to latest compatible versions.")
@click.command(help="Updates Pipenv & pip to latest, uninstalls all packages, and re-installs package(s) in [packages] to latest compatible versions.")
@click.option('--verbose', '-v', is_flag=True, default=False, help="Verbose mode.")
@click.option('--dev', '-d', is_flag=True, default=False, help="Additionally install package(s) in [dev-packages].")
@click.option('--three/--two', is_flag=True, default=None, help="Use Python 3/2 when creating virtualenv.")
@click.option('--python', default=False, nargs=1, help="Specify which version of Python virtualenv should use.")
@click.option('--dry-run', is_flag=True, default=False, help="Just output outdated packages.")
@click.option('--bare', is_flag=True, default=False, help="Minimal output.")
def update(dev=False, three=None, python=None, dry_run=False, bare=False):
def update(dev=False, three=None, python=None, dry_run=False, bare=False, dont_upgrade=False, user=False, verbose=False):
# Ensure that virtualenv is available.
ensure_project(three=three, python=python, validate=False)
# --dry-run
if dry_run:
dont_upgrade = True
updates = False
# Dev packages
if not bare:
click.echo(crayons.yellow('Checking dependencies...'), err=True)
packages = project.dev_packages
packages.update(project.packages)
packages = project.packages
if dev:
packages.update(project.dev_packages)
installed_packages = {}
deps = convert_deps_to_pip(packages, r=False)
@@ -1220,26 +1275,26 @@ def update(dev=False, three=None, python=None, dry_run=False, bare=False):
name = result['name']
installed = result['version']
latest = installed_packages[name]
if installed != latest:
if not bare:
click.echo('{0}=={1} is availble ({2} installed)!'.format(name, latest, installed))
else:
click.echo('{0}=={1}'.format(name, latest))
updates = True
try:
latest = installed_packages[name]
if installed != latest:
if not bare:
click.echo('{0}=={1} is available ({2} installed)!'.format(name, latest, installed))
else:
click.echo('{0}=={1}'.format(name, latest))
updates = True
except KeyError:
pass
if not updates and not bare:
click.echo(crayons.green('All good!'))
sys.exit(int(updates))
# Update pip to latest version.
ensure_latest_pip()
click.echo(crayons.yellow('Updating all dependencies from Pipfile...'))
do_purge()
do_init(dev=dev)
do_init(dev=dev, verbose=verbose)
click.echo(crayons.yellow('All dependencies are now up-to-date!'))
+1 -1
View File
@@ -29,7 +29,7 @@ PIPENV_USE_SYSTEM = os.environ.get('VIRTUAL_ENV') if 'PIPENV_IGNORE_VIRTUALENVS'
PIPENV_USE_HASHES = True
# Tells pipenv to skip case-checking (slow internet connections).
PIPENV_SKIP_VALIDATION = os.environ.get('PIPENV_SKIP_VALIDATION')
PIPENV_SKIP_VALIDATION = True
# Use shell compatibility mode when using venv in project mode.
if PIPENV_VENV_IN_PROJECT:
+4 -1
View File
@@ -273,4 +273,7 @@ class Project(object):
p[key][package_name] = package[package_name]
# Write Pipfile.
self.write_toml(recase_file(p))
self.write_toml(p)
def recase_pipfile(self):
self.write_toml(recase_file(self._pipfile))
+10 -15
View File
@@ -23,7 +23,7 @@ class PipCommand(pip.basecommand.Command):
def shellquote(s):
return "'" + s.replace("'", "'\\''") + "'"
return "'" + s.replace("'", "'\\''") + "'"
def clean_pkg_version(version):
@@ -55,18 +55,13 @@ def resolve_deps(deps, sources=None, verbose=False, hashes=False):
if verbose:
logging.log.verbose = True
r = Resolver(constraints=constraints, repository=pypi)
resolver = Resolver(constraints=constraints, repository=pypi)
results = []
_hashes = r.resolve_hashes(r.resolve())
# convert to a dictionary indexed by package names instead of install req objects
resolved_hashes = {}
for req, _hash in _hashes.items():
resolved_hashes[pep423_name(req.name)] = {
'version': clean_pkg_version(req.specifier),
'hashes': list(_hash)
}
for result in r.resolve():
# pre-resolve instead of iterating to avoid asking pypi for hashes of editable packages
resolved_tree = resolver.resolve()
for result in resolved_tree:
name = pep423_name(result.name)
version = clean_pkg_version(result.specifier)
@@ -78,9 +73,10 @@ def resolve_deps(deps, sources=None, verbose=False, hashes=False):
collected_hashes.append(release['digests']['sha256'])
collected_hashes = ['sha256:' + s for s in collected_hashes]
# Add pypi resolved hashes
if name in resolved_hashes and resolved_hashes[name]['version'] == version:
collected_hashes.extend(resolved_hashes[name]['hashes'])
# Collect un-collectable hashes.
if not collected_hashes:
collected_hashes = list(resolver.resolve_hashes([result]).items()[0][1])
results.append({'name': name, 'version': version, 'hashes': collected_hashes})
except ValueError:
@@ -361,4 +357,3 @@ def find_requirements(max_depth=3):
if os.path.isfile(r):
return r
raise RuntimeError('No requirements.txt found!')
+2
View File
@@ -182,8 +182,10 @@ class TestPipenv():
# Build the environment.
os.environ['PIPENV_VENV_IN_PROJECT'] = '1'
delegator.run('touch Pipfile')
# Install packages for test.
# print(delegator.run('pipenv install pep8').err)
assert delegator.run('pipenv install pep8').return_code == 0
assert delegator.run('pipenv install pytest').return_code == 0
+4 -4
View File
@@ -65,12 +65,12 @@ class TestProject():
delegator.run('rm -fr test_add_to_pipfile')
# Confirm Flask added to packages.
assert 'Flask' in p['packages']
assert p['packages']['Flask'] == '*'
assert 'flask' in p['packages']
assert p['packages']['flask'] == '*'
# Confirm Django added to dev-packages.
assert 'Django' in p['dev-packages']
assert p['dev-packages']['Django'] == '==1.10.1'
assert 'django' in p['dev-packages']
assert p['dev-packages']['django'] == '==1.10.1'
# Confirm casing is normalized.
assert 'click-completion' in p['packages']