Make install work

This commit is contained in:
Tzu-ping Chung
2018-06-28 19:14:22 +08:00
parent 0ac156c567
commit 5ee7514ebd
5 changed files with 488 additions and 469 deletions
+1 -1
View File
@@ -394,7 +394,7 @@ def install(
keep_outdated=False,
selective_upgrade=False,
):
from .core import do_install
from .operations.install import do_install
do_install(
package_name=package_name,
-3
View File
@@ -6,7 +6,6 @@ import signal
import json as simplejson
import click
import click_completion
import crayons
import delegator
from .vendor import pexpect
@@ -38,8 +37,6 @@ if sys.version_info < (3, 3):
from .vendor.backports.shutil_get_terminal_size import get_terminal_size
else:
from shutil import get_terminal_size
# Enable shell completion.
click_completion.init()
# ###################3 I PLAN TO KEEP THESE HERE. #########################
+471
View File
@@ -0,0 +1,471 @@
import json
import logging
import os
import re
import sys
import tempfile
import time
from pipenv.patched import crayons
from pipenv.vendor import click, delegator, requirementslib, six
from pipenv import progress
from pipenv._compat import Path
from pipenv.core import project, which_pip
from pipenv.environments import (
PIPENV_CACHE_DIR,
PIPENV_HIDE_EMOJIS,
PIPENV_MAX_SUBPROCESS,
)
from pipenv.project import SourceNotFound
from pipenv.utils import (
create_mirror_source,
escape_grouped_arguments,
fs_str,
is_pypi_url,
is_valid_url,
prepare_pip_source_args,
split_file,
)
from ._utils import convert_deps_to_pip
if not PIPENV_HIDE_EMOJIS:
now = time.localtime()
# Halloween easter-egg.
if ((now.tm_mon == 10) and (now.tm_mday == 30)) or (
(now.tm_mon == 10) and (now.tm_mday == 31)
):
INSTALL_LABEL = '🎃 '
# Christmas easter-egg.
elif ((now.tm_mon == 12) and (now.tm_mday == 24)) or (
(now.tm_mon == 12) and (now.tm_mday == 25)
):
INSTALL_LABEL = '🎅 '
else:
INSTALL_LABEL = '🐍 '
INSTALL_LABEL2 = crayons.normal('', bold=True)
STARTING_LABEL = ' '
else:
INSTALL_LABEL = ' '
INSTALL_LABEL2 = ' '
STARTING_LABEL = ' '
def _merge_deps(
file_dict,
project,
dev=False,
requirements=False,
ignore_hashes=False,
blocking=False,
only=False,
):
"""
Given a file_dict, merges dependencies and converts them to pip dependency lists.
:param dict file_dict: The result of calling :func:`pipenv.utils.split_file`
:param :class:`pipenv.project.Project` project: Pipenv project
:param bool dev=False: Flag indicating whether dev dependencies are to be installed
:param bool requirements=False: Flag indicating whether to use a requirements file
:param bool ignore_hashes=False:
:param bool blocking=False:
:param bool only=False:
:return: Pip-converted 3-tuples of [deps, requirements_deps]
"""
deps = []
requirements_deps = []
for section in list(file_dict.keys()):
# Turn develop-vcs into ['develop', 'vcs']
section_name, suffix = section.rsplit(
'-', 1
) if '-' in section and not section == 'dev-packages' else (
section, None
)
if not file_dict[section] or section_name not in (
'dev-packages', 'packages', 'default', 'develop'
):
continue
is_dev = section_name in ('dev-packages', 'develop')
if is_dev and not dev:
continue
if ignore_hashes:
for k, v in file_dict[section]:
if 'hash' in v:
del v['hash']
# Block and ignore hashes for all suffixed sections (vcs/editable)
no_hashes = True if suffix else ignore_hashes
block = True if suffix else blocking
include_index = True if not suffix else False
converted = convert_deps_to_pip(
file_dict[section], project, r=False, include_index=include_index
)
deps.extend((d, no_hashes, block) for d in converted)
if dev and is_dev and requirements:
requirements_deps.extend((d, no_hashes, block) for d in converted)
return deps, requirements_deps
def split_argument(req, short=None, long_=None, num=-1):
"""Split an argument from a string (finds None if not present).
Uses -short <arg>, --long <arg>, and --long=arg as permutations.
returns string, index
"""
index_entries = []
if long_:
index_entries.append('--{0}'.format(long_))
if short:
index_entries.append('-{0}'.format(short))
match_string = '|'.join(index_entries)
matches = re.findall('(?<=\s)({0})([\s=])(\S+)'.format(match_string), req)
remove_strings = []
match_values = []
for match in matches:
match_values.append(match[-1])
remove_strings.append(''.join(match))
for string_to_remove in remove_strings:
req = req.replace(' {0}'.format(string_to_remove), '')
if not match_values:
return req, None
if num == 1:
return req, match_values[0]
if num == -1:
return req, match_values
return req, match_values[:num]
def pip_install(
package_name=None,
r=None,
allow_global=False,
ignore_hashes=False,
no_deps=True,
verbose=False,
block=True,
index=None,
pre=False,
selective_upgrade=False,
requirements_dir=None,
extra_indexes=None,
pypi_mirror=None,
):
from notpip._internal import logger as piplogger
from notpip._vendor.pyparsing import ParseException
if verbose:
click.echo(
crayons.normal('Installing {0!r}'.format(package_name), bold=True),
err=True,
)
piplogger.setLevel(logging.INFO)
# Create files for hash mode.
if not package_name.startswith('-e ') and (not ignore_hashes) and (
r is None
):
fd, r = tempfile.mkstemp(
prefix='pipenv-', suffix='-requirement.txt', dir=requirements_dir
)
with os.fdopen(fd, 'w') as f:
f.write(package_name)
# Install dependencies when a package is a VCS dependency.
try:
req = requirementslib.Requirement.from_line(
package_name.split('--hash')[0].split('--trusted-host')[0]
).vcs
except (ParseException, ValueError) as e:
click.echo('{0}: {1}'.format(crayons.red('WARNING'), e), err=True)
click.echo(
'{0}... You will have to reinstall any packages that failed to install.'.format(
crayons.red('ABORTING INSTALL')
),
err=True,
)
click.echo(
'You may have to manually run {0} when you are finished.'.format(
crayons.normal('pipenv lock', bold=True)
)
)
sys.exit(1)
if req:
no_deps = False
# Don't specify a source directory when using --system.
if not allow_global and ('PIP_SRC' not in os.environ):
src = '--src {0}'.format(
escape_grouped_arguments(project.virtualenv_src_location)
)
else:
src = ''
else:
src = ''
# Try installing for each source in project.sources.
if index:
if not is_valid_url(index):
index = project.find_source(index).get('url')
sources = [{'url': index}]
if extra_indexes:
if isinstance(extra_indexes, six.string_types):
extra_indexes = [extra_indexes]
for idx in extra_indexes:
try:
extra_src = project.find_source(idx).get('url')
except SourceNotFound:
extra_src = idx
if extra_src != index:
sources.append({'url': extra_src})
else:
for idx in project.pipfile_sources:
if idx['url'] != sources[0]['url']:
sources.append({'url': idx['url']})
else:
sources = project.pipfile_sources
if pypi_mirror:
sources = [create_mirror_source(pypi_mirror) if is_pypi_url(source['url']) else source for source in sources]
if package_name.startswith('-e '):
install_reqs = ' -e "{0}"'.format(package_name.split('-e ')[1])
elif r:
install_reqs = ' -r {0}'.format(escape_grouped_arguments(r))
else:
install_reqs = ' "{0}"'.format(package_name)
# Skip hash-checking mode, when appropriate.
if r:
with open(r) as f:
if '--hash' not in f.read():
ignore_hashes = True
else:
if '--hash' not in install_reqs:
ignore_hashes = True
verbose_flag = '--verbose' if verbose else ''
if not ignore_hashes:
install_reqs += ' --require-hashes'
no_deps = '--no-deps' if no_deps else ''
pre = '--pre' if pre else ''
quoted_pip = which_pip(allow_global=allow_global)
quoted_pip = escape_grouped_arguments(quoted_pip)
upgrade_strategy = '--upgrade --upgrade-strategy=only-if-needed' if selective_upgrade else ''
pip_command = '{0} install {4} {5} {6} {7} {3} {1} {2} --exists-action w'.format(
quoted_pip,
install_reqs,
' '.join(prepare_pip_source_args(sources)),
no_deps,
pre,
src,
verbose_flag,
upgrade_strategy,
)
if verbose:
click.echo('$ {0}'.format(pip_command), err=True)
cache_dir = Path(PIPENV_CACHE_DIR)
pip_config = {
'PIP_CACHE_DIR': fs_str(cache_dir.as_posix()),
'PIP_WHEEL_DIR': fs_str(cache_dir.joinpath('wheels').as_posix()),
'PIP_DESTINATION_DIR': fs_str(cache_dir.joinpath('pkgs').as_posix()),
}
c = delegator.run(pip_command, block=block, env=pip_config)
return c
def format_pip_output(out, r=None):
def gen(out):
for line in out.split('\n'):
# Remove requirements file information from pip9 output.
if '(from -r' in line:
yield line[: line.index('(from -r')]
else:
yield line
out = '\n'.join([l for l in gen(out)])
return out
def format_pip_error(error):
error = error.replace(
'Expected', str(crayons.green('Expected', bold=True))
)
error = error.replace('Got', str(crayons.red('Got', bold=True)))
error = error.replace(
'THESE PACKAGES DO NOT MATCH THE HASHES FROM THE REQUIREMENTS FILE',
str(
crayons.red(
'THESE PACKAGES DO NOT MATCH THE HASHES FROM Pipfile.lock!',
bold=True,
)
),
)
error = error.replace(
'someone may have tampered with them',
str(crayons.red('someone may have tampered with them')),
)
error = error.replace(
'option to pip install', 'option to \'pipenv install\''
)
return error
def do_install_dependencies(
dev=False,
only=False,
bare=False,
requirements=False,
allow_global=False,
ignore_hashes=False,
skip_lock=False,
verbose=False,
concurrent=True,
requirements_dir=None,
pypi_mirror=False,
):
""""Executes the install functionality.
If requirements is True, simply spits out a requirements format to stdout.
"""
def cleanup_procs(procs, concurrent):
for c in procs:
if concurrent:
c.block()
if 'Ignoring' in c.out:
click.echo(crayons.yellow(c.out.strip()))
if verbose:
click.echo(crayons.blue(c.out or c.err))
# The Installation failed...
if c.return_code != 0:
# Save the Failed Dependency for later.
failed_deps_list.append((c.dep, c.ignore_hash))
# Alert the user.
click.echo(
'{0} {1}! Will try again.'.format(
crayons.red('An error occurred while installing'),
crayons.green(c.dep.split('--hash')[0].strip()),
)
)
if requirements:
bare = True
blocking = (not concurrent)
# Load the lockfile if it exists, or if only is being used (e.g. lock is being used).
if skip_lock or only or not project.lockfile_exists:
if not bare:
click.echo(
crayons.normal(
u'Installing dependencies from Pipfile...', bold=True
)
)
lockfile = split_file(project._lockfile)
else:
with open(project.lockfile_location) as f:
lockfile = split_file(json.load(f))
if not bare:
click.echo(
crayons.normal(
u'Installing dependencies from Pipfile.lock ({0})...'.format(
lockfile['_meta'].get('hash', {}).get('sha256')[-6:]
),
bold=True,
)
)
# Allow pip to resolve dependencies when in skip-lock mode.
no_deps = (not skip_lock)
deps_list, dev_deps_list = _merge_deps(
lockfile,
project,
dev=dev,
requirements=requirements,
ignore_hashes=ignore_hashes,
blocking=blocking,
only=only,
)
failed_deps_list = []
if requirements:
# Comment out packages that shouldn't be included in
# requirements.txt, for pip9.
# Additional package selectors, specific to pip's --hash checking mode.
for l in (deps_list, dev_deps_list):
for i, dep in enumerate(l):
l[i] = list(l[i])
if '--hash' in l[i][0]:
l[i][0] = (l[i][0].split('--hash')[0].strip())
index_args = prepare_pip_source_args(project.sources)
index_args = ' '.join(index_args).replace(' -', '\n-')
# Output only default dependencies
click.echo(index_args)
if not dev:
click.echo('\n'.join(d[0] for d in sorted(deps_list)))
sys.exit(0)
# Output only dev dependencies
if dev:
click.echo('\n'.join(d[0] for d in sorted(dev_deps_list)))
sys.exit(0)
procs = []
deps_list_bar = progress.bar(
deps_list, label=INSTALL_LABEL if os.name != 'nt' else ''
)
for dep, ignore_hash, block in deps_list_bar:
if len(procs) < PIPENV_MAX_SUBPROCESS:
# Use a specific index, if specified.
dep, index = split_argument(dep, short='i', long_='index', num=1)
dep, extra_indexes = split_argument(dep, long_='extra-index-url')
# Install the module.
c = pip_install(
dep,
ignore_hashes=ignore_hash,
allow_global=allow_global,
no_deps=no_deps,
verbose=verbose,
block=block,
index=index,
requirements_dir=requirements_dir,
extra_indexes=extra_indexes,
pypi_mirror=pypi_mirror,
)
c.dep = dep
c.ignore_hash = ignore_hash
procs.append(c)
if len(procs) >= PIPENV_MAX_SUBPROCESS or len(procs) == len(deps_list):
cleanup_procs(procs, concurrent)
procs = []
cleanup_procs(procs, concurrent)
# Iterate over the hopefully-poorly-packaged dependencies...
if failed_deps_list:
click.echo(
crayons.normal(
u'Installing initially failed dependencies...', bold=True
)
)
for dep, ignore_hash in progress.bar(
failed_deps_list, label=INSTALL_LABEL2
):
# Use a specific index, if specified.
dep, index = split_argument(dep, short='i', long_='index', num=1)
dep, extra_indexes = split_argument(dep, long_='extra-index-url')
# Install the module.
c = pip_install(
dep,
ignore_hashes=ignore_hash,
allow_global=allow_global,
no_deps=no_deps,
verbose=verbose,
index=index,
requirements_dir=requirements_dir,
extra_indexes=extra_indexes,
)
# The Installation failed...
if c.return_code != 0:
# We echo both c.out and c.err because pip returns error details on out.
click.echo(crayons.blue(format_pip_output(c.out)))
click.echo(crayons.blue(format_pip_error(c.err)), err=True)
# Return the subprocess' return code.
sys.exit(c.return_code)
else:
click.echo(
'{0} {1}{2}'.format(
crayons.green('Success installing'),
crayons.green(dep.split('--hash')[0].strip()),
crayons.green('!'),
)
)
+1 -1
View File
@@ -7,8 +7,8 @@ from pipenv.vendor import click
from pipenv._compat import TemporaryDirectory
from pipenv.core import project
from ._install import do_install_dependencies
from .ensure import ensure_pipfile
from .install import do_install_dependencies
from .lock import do_lock
from .virtualenv import cleanup_virtualenv, do_create_virtualenv
+15 -464
View File
@@ -1,478 +1,29 @@
import json
import logging
import os
import sys
import tempfile
import time
from pipenv.patched import crayons
from pipenv.vendor import click, delegator, requirementslib, six
from pipenv.vendor import click, requirementslib
from pipenv import progress
from pipenv._compat import Path, TemporaryDirectory
from pipenv.core import BAD_PACKAGES, project, which_pip
from pipenv.environments import (
PIPENV_CACHE_DIR,
PIPENV_HIDE_EMOJIS,
PIPENV_MAX_SUBPROCESS,
PIPENV_USE_SYSTEM,
)
from pipenv.project import SourceNotFound
from pipenv._compat import TemporaryDirectory
from pipenv.core import BAD_PACKAGES, project
from pipenv.environments import PIPENV_USE_SYSTEM
from pipenv.utils import (
create_mirror_source,
download_file,
escape_grouped_arguments,
fs_str,
is_pypi_url,
is_star,
is_valid_url,
prepare_pip_source_args,
proper_case,
split_file,
)
from ._utils import convert_deps_to_pip
from ._install import (
format_pip_error,
format_pip_output,
pip_install,
split_argument,
)
from ._utils import convert_deps_to_pip, spinner
from .ensure import ensure_project, import_requirements
if not PIPENV_HIDE_EMOJIS:
now = time.localtime()
# Halloween easter-egg.
if ((now.tm_mon == 10) and (now.tm_mday == 30)) or (
(now.tm_mon == 10) and (now.tm_mday == 31)
):
INSTALL_LABEL = '🎃 '
# Christmas easter-egg.
elif ((now.tm_mon == 12) and (now.tm_mday == 24)) or (
(now.tm_mon == 12) and (now.tm_mday == 25)
):
INSTALL_LABEL = '🎅 '
else:
INSTALL_LABEL = '🐍 '
INSTALL_LABEL2 = crayons.normal('', bold=True)
STARTING_LABEL = ' '
else:
INSTALL_LABEL = ' '
INSTALL_LABEL2 = ' '
STARTING_LABEL = ' '
def _merge_deps(
file_dict,
project,
dev=False,
requirements=False,
ignore_hashes=False,
blocking=False,
only=False,
):
"""
Given a file_dict, merges dependencies and converts them to pip dependency lists.
:param dict file_dict: The result of calling :func:`pipenv.utils.split_file`
:param :class:`pipenv.project.Project` project: Pipenv project
:param bool dev=False: Flag indicating whether dev dependencies are to be installed
:param bool requirements=False: Flag indicating whether to use a requirements file
:param bool ignore_hashes=False:
:param bool blocking=False:
:param bool only=False:
:return: Pip-converted 3-tuples of [deps, requirements_deps]
"""
deps = []
requirements_deps = []
for section in list(file_dict.keys()):
# Turn develop-vcs into ['develop', 'vcs']
section_name, suffix = section.rsplit(
'-', 1
) if '-' in section and not section == 'dev-packages' else (
section, None
)
if not file_dict[section] or section_name not in (
'dev-packages', 'packages', 'default', 'develop'
):
continue
is_dev = section_name in ('dev-packages', 'develop')
if is_dev and not dev:
continue
if ignore_hashes:
for k, v in file_dict[section]:
if 'hash' in v:
del v['hash']
# Block and ignore hashes for all suffixed sections (vcs/editable)
no_hashes = True if suffix else ignore_hashes
block = True if suffix else blocking
include_index = True if not suffix else False
converted = convert_deps_to_pip(
file_dict[section], project, r=False, include_index=include_index
)
deps.extend((d, no_hashes, block) for d in converted)
if dev and is_dev and requirements:
requirements_deps.extend((d, no_hashes, block) for d in converted)
return deps, requirements_deps
def _split_argument(req, short=None, long_=None, num=-1):
"""Split an argument from a string (finds None if not present).
Uses -short <arg>, --long <arg>, and --long=arg as permutations.
returns string, index
"""
index_entries = []
import re
if long_:
index_entries.append('--{0}'.format(long_))
if short:
index_entries.append('-{0}'.format(short))
match_string = '|'.join(index_entries)
matches = re.findall('(?<=\s)({0})([\s=])(\S+)'.format(match_string), req)
remove_strings = []
match_values = []
for match in matches:
match_values.append(match[-1])
remove_strings.append(''.join(match))
for string_to_remove in remove_strings:
req = req.replace(' {0}'.format(string_to_remove), '')
if not match_values:
return req, None
if num == 1:
return req, match_values[0]
if num == -1:
return req, match_values
return req, match_values[:num]
def _format_pip_output(out, r=None):
def gen(out):
for line in out.split('\n'):
# Remove requirements file information from pip9 output.
if '(from -r' in line:
yield line[: line.index('(from -r')]
else:
yield line
out = '\n'.join([l for l in gen(out)])
return out
def _format_pip_error(error):
error = error.replace(
'Expected', str(crayons.green('Expected', bold=True))
)
error = error.replace('Got', str(crayons.red('Got', bold=True)))
error = error.replace(
'THESE PACKAGES DO NOT MATCH THE HASHES FROM THE REQUIREMENTS FILE',
str(
crayons.red(
'THESE PACKAGES DO NOT MATCH THE HASHES FROM Pipfile.lock!',
bold=True,
)
),
)
error = error.replace(
'someone may have tampered with them',
str(crayons.red('someone may have tampered with them')),
)
error = error.replace(
'option to pip install', 'option to \'pipenv install\''
)
return error
def _pip_install(
package_name=None,
r=None,
allow_global=False,
ignore_hashes=False,
no_deps=True,
verbose=False,
block=True,
index=None,
pre=False,
selective_upgrade=False,
requirements_dir=None,
extra_indexes=None,
pypi_mirror=None,
):
from notpip._internal import logger as piplogger
from notpip._vendor.pyparsing import ParseException
if verbose:
click.echo(
crayons.normal('Installing {0!r}'.format(package_name), bold=True),
err=True,
)
piplogger.setLevel(logging.INFO)
# Create files for hash mode.
if not package_name.startswith('-e ') and (not ignore_hashes) and (
r is None
):
fd, r = tempfile.mkstemp(
prefix='pipenv-', suffix='-requirement.txt', dir=requirements_dir
)
with os.fdopen(fd, 'w') as f:
f.write(package_name)
# Install dependencies when a package is a VCS dependency.
try:
req = requirementslib.Requirement.from_line(
package_name.split('--hash')[0].split('--trusted-host')[0]
).vcs
except (ParseException, ValueError) as e:
click.echo('{0}: {1}'.format(crayons.red('WARNING'), e), err=True)
click.echo(
'{0}... You will have to reinstall any packages that failed to install.'.format(
crayons.red('ABORTING INSTALL')
),
err=True,
)
click.echo(
'You may have to manually run {0} when you are finished.'.format(
crayons.normal('pipenv lock', bold=True)
)
)
sys.exit(1)
if req:
no_deps = False
# Don't specify a source directory when using --system.
if not allow_global and ('PIP_SRC' not in os.environ):
src = '--src {0}'.format(
escape_grouped_arguments(project.virtualenv_src_location)
)
else:
src = ''
else:
src = ''
# Try installing for each source in project.sources.
if index:
if not is_valid_url(index):
index = project.find_source(index).get('url')
sources = [{'url': index}]
if extra_indexes:
if isinstance(extra_indexes, six.string_types):
extra_indexes = [extra_indexes]
for idx in extra_indexes:
try:
extra_src = project.find_source(idx).get('url')
except SourceNotFound:
extra_src = idx
if extra_src != index:
sources.append({'url': extra_src})
else:
for idx in project.pipfile_sources:
if idx['url'] != sources[0]['url']:
sources.append({'url': idx['url']})
else:
sources = project.pipfile_sources
if pypi_mirror:
sources = [create_mirror_source(pypi_mirror) if is_pypi_url(source['url']) else source for source in sources]
if package_name.startswith('-e '):
install_reqs = ' -e "{0}"'.format(package_name.split('-e ')[1])
elif r:
install_reqs = ' -r {0}'.format(escape_grouped_arguments(r))
else:
install_reqs = ' "{0}"'.format(package_name)
# Skip hash-checking mode, when appropriate.
if r:
with open(r) as f:
if '--hash' not in f.read():
ignore_hashes = True
else:
if '--hash' not in install_reqs:
ignore_hashes = True
verbose_flag = '--verbose' if verbose else ''
if not ignore_hashes:
install_reqs += ' --require-hashes'
no_deps = '--no-deps' if no_deps else ''
pre = '--pre' if pre else ''
quoted_pip = which_pip(allow_global=allow_global)
quoted_pip = escape_grouped_arguments(quoted_pip)
upgrade_strategy = '--upgrade --upgrade-strategy=only-if-needed' if selective_upgrade else ''
pip_command = '{0} install {4} {5} {6} {7} {3} {1} {2} --exists-action w'.format(
quoted_pip,
install_reqs,
' '.join(prepare_pip_source_args(sources)),
no_deps,
pre,
src,
verbose_flag,
upgrade_strategy,
)
if verbose:
click.echo('$ {0}'.format(pip_command), err=True)
cache_dir = Path(PIPENV_CACHE_DIR)
pip_config = {
'PIP_CACHE_DIR': fs_str(cache_dir.as_posix()),
'PIP_WHEEL_DIR': fs_str(cache_dir.joinpath('wheels').as_posix()),
'PIP_DESTINATION_DIR': fs_str(cache_dir.joinpath('pkgs').as_posix()),
}
c = delegator.run(pip_command, block=block, env=pip_config)
return c
def do_install_dependencies(
dev=False,
only=False,
bare=False,
requirements=False,
allow_global=False,
ignore_hashes=False,
skip_lock=False,
verbose=False,
concurrent=True,
requirements_dir=None,
pypi_mirror=False,
):
""""Executes the install functionality.
If requirements is True, simply spits out a requirements format to stdout.
"""
def cleanup_procs(procs, concurrent):
for c in procs:
if concurrent:
c.block()
if 'Ignoring' in c.out:
click.echo(crayons.yellow(c.out.strip()))
if verbose:
click.echo(crayons.blue(c.out or c.err))
# The Installation failed...
if c.return_code != 0:
# Save the Failed Dependency for later.
failed_deps_list.append((c.dep, c.ignore_hash))
# Alert the user.
click.echo(
'{0} {1}! Will try again.'.format(
crayons.red('An error occurred while installing'),
crayons.green(c.dep.split('--hash')[0].strip()),
)
)
if requirements:
bare = True
blocking = (not concurrent)
# Load the lockfile if it exists, or if only is being used (e.g. lock is being used).
if skip_lock or only or not project.lockfile_exists:
if not bare:
click.echo(
crayons.normal(
u'Installing dependencies from Pipfile...', bold=True
)
)
lockfile = split_file(project._lockfile)
else:
with open(project.lockfile_location) as f:
lockfile = split_file(json.load(f))
if not bare:
click.echo(
crayons.normal(
u'Installing dependencies from Pipfile.lock ({0})...'.format(
lockfile['_meta'].get('hash', {}).get('sha256')[-6:]
),
bold=True,
)
)
# Allow pip to resolve dependencies when in skip-lock mode.
no_deps = (not skip_lock)
deps_list, dev_deps_list = _merge_deps(
lockfile,
project,
dev=dev,
requirements=requirements,
ignore_hashes=ignore_hashes,
blocking=blocking,
only=only,
)
failed_deps_list = []
if requirements:
# Comment out packages that shouldn't be included in
# requirements.txt, for pip9.
# Additional package selectors, specific to pip's --hash checking mode.
for l in (deps_list, dev_deps_list):
for i, dep in enumerate(l):
l[i] = list(l[i])
if '--hash' in l[i][0]:
l[i][0] = (l[i][0].split('--hash')[0].strip())
index_args = prepare_pip_source_args(project.sources)
index_args = ' '.join(index_args).replace(' -', '\n-')
# Output only default dependencies
click.echo(index_args)
if not dev:
click.echo('\n'.join(d[0] for d in sorted(deps_list)))
sys.exit(0)
# Output only dev dependencies
if dev:
click.echo('\n'.join(d[0] for d in sorted(dev_deps_list)))
sys.exit(0)
procs = []
deps_list_bar = progress.bar(
deps_list, label=INSTALL_LABEL if os.name != 'nt' else ''
)
for dep, ignore_hash, block in deps_list_bar:
if len(procs) < PIPENV_MAX_SUBPROCESS:
# Use a specific index, if specified.
dep, index = _split_argument(dep, short='i', long_='index', num=1)
dep, extra_indexes = _split_argument(dep, long_='extra-index-url')
# Install the module.
c = _pip_install(
dep,
ignore_hashes=ignore_hash,
allow_global=allow_global,
no_deps=no_deps,
verbose=verbose,
block=block,
index=index,
requirements_dir=requirements_dir,
extra_indexes=extra_indexes,
pypi_mirror=pypi_mirror,
)
c.dep = dep
c.ignore_hash = ignore_hash
procs.append(c)
if len(procs) >= PIPENV_MAX_SUBPROCESS or len(procs) == len(deps_list):
cleanup_procs(procs, concurrent)
procs = []
cleanup_procs(procs, concurrent)
# Iterate over the hopefully-poorly-packaged dependencies...
if failed_deps_list:
click.echo(
crayons.normal(
u'Installing initially failed dependencies...', bold=True
)
)
for dep, ignore_hash in progress.bar(
failed_deps_list, label=INSTALL_LABEL2
):
# Use a specific index, if specified.
dep, index = _split_argument(dep, short='i', long_='index', num=1)
dep, extra_indexes = _split_argument(dep, long_='extra-index-url')
# Install the module.
c = _pip_install(
dep,
ignore_hashes=ignore_hash,
allow_global=allow_global,
no_deps=no_deps,
verbose=verbose,
index=index,
requirements_dir=requirements_dir,
extra_indexes=extra_indexes,
)
# The Installation failed...
if c.return_code != 0:
# We echo both c.out and c.err because pip returns error details on out.
click.echo(crayons.blue(_format_pip_output(c.out)))
click.echo(crayons.blue(_format_pip_error(c.err)), err=True)
# Return the subprocess' return code.
sys.exit(c.return_code)
else:
click.echo(
'{0} {1}{2}'.format(
crayons.green('Success installing'),
crayons.green(dep.split('--hash')[0].strip()),
crayons.green('!'),
)
)
from .init import do_init
def _import_from_code(path='.'):
@@ -680,7 +231,7 @@ def do_install(
if selective_upgrade:
for i, package_name in enumerate(package_names[:]):
section = project.packages if not dev else project.dev_packages
package = Requirement.from_line(package_name)
package = requirementslib.Requirement.from_line(package_name)
package__name, package__val = package.pipfile_entry
try:
if not is_star(section[package__name]) and is_star(
@@ -745,7 +296,7 @@ def do_install(
)
# Warn if --editable wasn't passed.
try:
converted = Requirement.from_line(package_name)
converted = requirementslib.Requirement.from_line(package_name)
except ValueError as e:
click.echo('{0}: {1}'.format(crayons.red('WARNING'), e))
requirements_directory.cleanup()