1# -*- coding=utf-8 -*-
2from __future__ import absolute_import, print_function
3
4import io
5import json as simplejson
6import logging
7import os
8import sys
9import time
10import warnings
11
12import click
13import six
14
15import delegator
16import dotenv
17import pipfile
18import vistir
19
20from click_completion import init as init_completion
21
22from . import environments, exceptions, pep508checker, progress
23from ._compat import decode_for_output, fix_utf8
24from .cmdparse import Script
25from .environments import (
26    PIP_EXISTS_ACTION, PIPENV_CACHE_DIR, PIPENV_COLORBLIND,
27    PIPENV_DEFAULT_PYTHON_VERSION, PIPENV_DONT_USE_PYENV, PIPENV_DONT_USE_ASDF,
28    PIPENV_HIDE_EMOJIS, PIPENV_MAX_SUBPROCESS, PIPENV_PYUP_API_KEY,
29    PIPENV_RESOLVE_VCS, PIPENV_SHELL_FANCY, PIPENV_SKIP_VALIDATION, PIPENV_YES,
30    SESSION_IS_INTERACTIVE, is_type_checking
31)
32from .patched import crayons
33from .project import Project
34from .utils import (
35    convert_deps_to_pip, create_spinner, download_file,
36    escape_grouped_arguments, find_python, find_windows_executable,
37    get_canonical_names, get_source_list, interrupt_handled_subprocess,
38    is_pinned, is_python_command, is_required_version, is_star, is_valid_url,
39    parse_indexes, pep423_name, prepare_pip_source_args, proper_case,
40    python_version, run_command, venv_resolve_deps
41)
42
43
44if is_type_checking():
45    from typing import Dict, List, Optional, Union, Text
46    from pipenv.vendor.requirementslib.models.requirements import Requirement
47    TSourceDict = Dict[Text, Union[Text, bool]]
48
49
50# Packages that should be ignored later.
51BAD_PACKAGES = (
52    "distribute",
53    "packaging",
54    "pip",
55    "pkg-resources",
56    "setuptools",
57    "wheel",
58)
59
60FIRST_PACKAGES = ("cython",)
61# Are we using the default Python?
62USING_DEFAULT_PYTHON = True
63if not PIPENV_HIDE_EMOJIS:
64    now = time.localtime()
65    # Halloween easter-egg.
66    if ((now.tm_mon == 10) and (now.tm_mday == 30)) or (
67        (now.tm_mon == 10) and (now.tm_mday == 31)
68    ):
69        INSTALL_LABEL = "��   "
70    # Christmas easter-egg.
71    elif ((now.tm_mon == 12) and (now.tm_mday == 24)) or (
72        (now.tm_mon == 12) and (now.tm_mday == 25)
73    ):
74        INSTALL_LABEL = "��   "
75    else:
76        INSTALL_LABEL = "��   "
77    INSTALL_LABEL2 = crayons.normal("☤  ", bold=True)
78    STARTING_LABEL = "    "
79else:
80    INSTALL_LABEL = "   "
81    INSTALL_LABEL2 = "   "
82    STARTING_LABEL = "   "
83# Enable shell completion.
84init_completion()
85# Disable colors, for the color blind and others who do not prefer colors.
86if PIPENV_COLORBLIND:
87    crayons.disable()
88
89
90def which(command, location=None, allow_global=False):
91    if not allow_global and location is None:
92        if project.virtualenv_exists:
93            location = project.virtualenv_location
94        else:
95            location = os.environ.get("VIRTUAL_ENV", None)
96    if not (location and os.path.exists(location)) and not allow_global:
97        raise RuntimeError("location not created nor specified")
98
99    version_str = "python{0}".format(".".join([str(v) for v in sys.version_info[:2]]))
100    is_python = command in ("python", os.path.basename(sys.executable), version_str)
101    if not allow_global:
102        if os.name == "nt":
103            p = find_windows_executable(os.path.join(location, "Scripts"), command)
104        else:
105            p = os.path.join(location, "bin", command)
106    else:
107        if is_python:
108            p = sys.executable
109    if not os.path.exists(p):
110        if is_python:
111            p = sys.executable or system_which("python")
112        else:
113            p = system_which(command)
114    return p
115
116
117project = Project(which=which)
118
119
120def do_clear():
121    click.echo(crayons.normal(fix_utf8("Clearing caches..."), bold=True))
122    try:
123        from pip._internal import locations
124    except ImportError:  # pip 9.
125        from pip import locations
126
127    try:
128        vistir.path.rmtree(PIPENV_CACHE_DIR, onerror=vistir.path.handle_remove_readonly)
129        # Other processes may be writing into this directory simultaneously.
130        vistir.path.rmtree(
131            locations.USER_CACHE_DIR,
132            ignore_errors=environments.PIPENV_IS_CI,
133            onerror=vistir.path.handle_remove_readonly
134        )
135    except OSError as e:
136        # Ignore FileNotFoundError. This is needed for Python 2.7.
137        import errno
138
139        if e.errno == errno.ENOENT:
140            pass
141        raise
142
143
144def load_dot_env():
145    """Loads .env file into sys.environ."""
146    if not environments.PIPENV_DONT_LOAD_ENV:
147        # If the project doesn't exist yet, check current directory for a .env file
148        project_directory = project.project_directory or "."
149        dotenv_file = environments.PIPENV_DOTENV_LOCATION or os.sep.join(
150            [project_directory, ".env"]
151        )
152
153        if os.path.isfile(dotenv_file):
154            click.echo(
155                crayons.normal(fix_utf8("Loading .env environment variables..."), bold=True),
156                err=True,
157            )
158        else:
159            if environments.PIPENV_DOTENV_LOCATION:
160                click.echo(
161                    "{0}: file {1}={2} does not exist!!\n{3}".format(
162                        crayons.red("Warning", bold=True),
163                        crayons.normal("PIPENV_DOTENV_LOCATION", bold=True),
164                        crayons.normal(environments.PIPENV_DOTENV_LOCATION, bold=True),
165                        crayons.red("Not loading environment variables.", bold=True),
166                    ),
167                    err=True,
168                )
169        dotenv.load_dotenv(dotenv_file, override=True)
170        six.moves.reload_module(environments)
171
172
173def add_to_path(p):
174    """Adds a given path to the PATH."""
175    if p not in os.environ["PATH"]:
176        os.environ["PATH"] = "{0}{1}{2}".format(p, os.pathsep, os.environ["PATH"])
177
178
179def cleanup_virtualenv(bare=True):
180    """Removes the virtualenv directory from the system."""
181    if not bare:
182        click.echo(crayons.red("Environment creation aborted."))
183    try:
184        # Delete the virtualenv.
185        vistir.path.rmtree(project.virtualenv_location)
186    except OSError as e:
187        click.echo(
188            "{0} An error occurred while removing {1}!".format(
189                crayons.red("Error: ", bold=True),
190                crayons.green(project.virtualenv_location),
191            ),
192            err=True,
193        )
194        click.echo(crayons.cyan(e), err=True)
195
196
197def import_requirements(r=None, dev=False):
198    from .patched.notpip._vendor import requests as pip_requests
199    from .vendor.pip_shims.shims import parse_requirements
200
201    # Parse requirements.txt file with Pip's parser.
202    # Pip requires a `PipSession` which is a subclass of requests.Session.
203    # Since we're not making any network calls, it's initialized to nothing.
204    if r:
205        assert os.path.isfile(r)
206    # Default path, if none is provided.
207    if r is None:
208        r = project.requirements_location
209    with open(r, "r") as f:
210        contents = f.read()
211    indexes = []
212    trusted_hosts = []
213    # Find and add extra indexes.
214    for line in contents.split("\n"):
215        line_indexes, _trusted_hosts, _ = parse_indexes(line.strip())
216        indexes.extend(line_indexes)
217        trusted_hosts.extend(_trusted_hosts)
218    indexes = sorted(set(indexes))
219    trusted_hosts = sorted(set(trusted_hosts))
220    reqs = [f for f in parse_requirements(r, session=pip_requests)]
221    for package in reqs:
222        if package.name not in BAD_PACKAGES:
223            if package.link is not None:
224                package_string = (
225                    "-e {0}".format(package.link)
226                    if package.editable
227                    else str(package.link)
228                )
229                project.add_package_to_pipfile(package_string, dev=dev)
230            else:
231                project.add_package_to_pipfile(str(package.req), dev=dev)
232    for index in indexes:
233        trusted = index in trusted_hosts
234        project.add_index_to_pipfile(index, verify_ssl=trusted)
235    project.recase_pipfile()
236
237
238def ensure_environment():
239    # Skip this on Windows...
240    if os.name != "nt":
241        if "LANG" not in os.environ:
242            click.echo(
243                "{0}: the environment variable {1} is not set!"
244                "\nWe recommend setting this in {2} (or equivalent) for "
245                "proper expected behavior.".format(
246                    crayons.red("Warning", bold=True),
247                    crayons.normal("LANG", bold=True),
248                    crayons.green("~/.profile"),
249                ),
250                err=True,
251            )
252
253
254def import_from_code(path="."):
255    from pipreqs import pipreqs
256
257    rs = []
258    try:
259        for r in pipreqs.get_all_imports(
260            path, encoding="utf-8", extra_ignore_dirs=[".venv"]
261        ):
262            if r not in BAD_PACKAGES:
263                rs.append(r)
264        pkg_names = pipreqs.get_pkg_names(rs)
265        return [proper_case(r) for r in pkg_names]
266
267    except Exception:
268        return []
269
270
271def ensure_pipfile(validate=True, skip_requirements=False, system=False):
272    """Creates a Pipfile for the project, if it doesn't exist."""
273    from .environments import PIPENV_VIRTUALENV
274
275    # Assert Pipfile exists.
276    python = which("python") if not (USING_DEFAULT_PYTHON or system) else None
277    if project.pipfile_is_empty:
278        # Show an error message and exit if system is passed and no pipfile exists
279        if system and not PIPENV_VIRTUALENV:
280            raise exceptions.PipenvOptionsError(
281                "--system",
282                "--system is intended to be used for pre-existing Pipfile "
283                "installation, not installation of specific packages. Aborting."
284            )
285        # If there's a requirements file, but no Pipfile...
286        if project.requirements_exists and not skip_requirements:
287            click.echo(
288                crayons.normal(
289                    fix_utf8("requirements.txt found, instead of Pipfile! Converting..."),
290                    bold=True,
291                )
292            )
293            # Create a Pipfile...
294            project.create_pipfile(python=python)
295            with create_spinner("Importing requirements...") as sp:
296                # Import requirements.txt.
297                try:
298                    import_requirements()
299                except Exception:
300                    sp.fail(environments.PIPENV_SPINNER_FAIL_TEXT.format("Failed..."))
301                else:
302                    sp.ok(environments.PIPENV_SPINNER_OK_TEXT.format("Success!"))
303            # Warn the user of side-effects.
304            click.echo(
305                u"{0}: Your {1} now contains pinned versions, if your {2} did. \n"
306                "We recommend updating your {1} to specify the {3} version, instead."
307                "".format(
308                    crayons.red("Warning", bold=True),
309                    crayons.normal("Pipfile", bold=True),
310                    crayons.normal("requirements.txt", bold=True),
311                    crayons.normal('"*"', bold=True),
312                )
313            )
314        else:
315            click.echo(
316                crayons.normal(fix_utf8("Creating a Pipfile for this project..."), bold=True),
317                err=True,
318            )
319            # Create the pipfile if it doesn't exist.
320            project.create_pipfile(python=python)
321    # Validate the Pipfile's contents.
322    if validate and project.virtualenv_exists and not PIPENV_SKIP_VALIDATION:
323        # Ensure that Pipfile is using proper casing.
324        p = project.parsed_pipfile
325        changed = project.ensure_proper_casing()
326        # Write changes out to disk.
327        if changed:
328            click.echo(
329                crayons.normal(u"Fixing package names in Pipfile...", bold=True), err=True
330            )
331            project.write_toml(p)
332
333
334def find_a_system_python(line):
335    """Find a Python installation from a given line.
336
337    This tries to parse the line in various of ways:
338
339    * Looks like an absolute path? Use it directly.
340    * Looks like a py.exe call? Use py.exe to get the executable.
341    * Starts with "py" something? Looks like a python command. Try to find it
342      in PATH, and use it directly.
343    * Search for "python" and "pythonX.Y" executables in PATH to find a match.
344    * Nothing fits, return None.
345    """
346
347    from .vendor.pythonfinder import Finder
348    finder = Finder(system=False, global_search=True)
349    if not line:
350        return next(iter(finder.find_all_python_versions()), None)
351    # Use the windows finder executable
352    if (line.startswith("py ") or line.startswith("py.exe ")) and os.name == "nt":
353        line = line.split(" ", 1)[1].lstrip("-")
354    python_entry = find_python(finder, line)
355    return python_entry
356
357
358def ensure_python(three=None, python=None):
359    # Runtime import is necessary due to the possibility that the environments module may have been reloaded.
360    from .environments import PIPENV_PYTHON, PIPENV_YES
361
362    if PIPENV_PYTHON and python is False and three is None:
363        python = PIPENV_PYTHON
364
365    def abort(msg=''):
366        click.echo(
367            "{0}\nYou can specify specific versions of Python with:\n{1}".format(
368                crayons.red(msg),
369                crayons.yellow(
370                    "$ pipenv --python {0}".format(
371                        os.sep.join(("path", "to", "python"))
372                    )
373                )
374            ),
375            err=True,
376        )
377        sys.exit(1)
378
379    global USING_DEFAULT_PYTHON
380    USING_DEFAULT_PYTHON = three is None and not python
381    # Find out which python is desired.
382    if not python:
383        python = convert_three_to_python(three, python)
384    if not python:
385        python = project.required_python_version
386    if not python:
387        python = PIPENV_DEFAULT_PYTHON_VERSION
388    path_to_python = find_a_system_python(python)
389    if environments.is_verbose():
390        click.echo(u"Using python: {0}".format(python), err=True)
391        click.echo(u"Path to python: {0}".format(path_to_python), err=True)
392    if not path_to_python and python is not None:
393        # We need to install Python.
394        click.echo(
395            u"{0}: Python {1} {2}".format(
396                crayons.red("Warning", bold=True),
397                crayons.cyan(python),
398                fix_utf8("was not found on your system..."),
399            ),
400            err=True,
401        )
402        # check for python installers
403        from .installers import Pyenv, Asdf, InstallerError, InstallerNotFound
404
405        # prefer pyenv if both pyenv and asdf are installed as it's
406        # dedicated to python installs so probably the preferred
407        # method of the user for new python installs.
408        installer = None
409        if not PIPENV_DONT_USE_PYENV:
410            try:
411                installer = Pyenv()
412            except InstallerNotFound:
413                pass
414        if installer is None and not PIPENV_DONT_USE_ASDF:
415            try:
416                installer = Asdf()
417            except InstallerNotFound:
418                pass
419
420        if not installer:
421            abort("Neither 'pyenv' nor 'asdf' could be found to install Python.")
422        else:
423            if SESSION_IS_INTERACTIVE or PIPENV_YES:
424                try:
425                    version = installer.find_version_to_install(python)
426                except ValueError:
427                    abort()
428                except InstallerError as e:
429                    abort('Something went wrong while installing Python:\n{}'.format(e.err))
430                s = "{0} {1} {2}".format(
431                    "Would you like us to install",
432                    crayons.green("CPython {0}".format(version)),
433                    "with {0}?".format(installer),
434                )
435                # Prompt the user to continue...
436                if not (PIPENV_YES or click.confirm(s, default=True)):
437                    abort()
438                else:
439                    # Tell the user we're installing Python.
440                    click.echo(
441                        u"{0} {1} {2} {3}{4}".format(
442                            crayons.normal(u"Installing", bold=True),
443                            crayons.green(u"CPython {0}".format(version), bold=True),
444                            crayons.normal(u"with {0}".format(installer.cmd), bold=True),
445                            crayons.normal(u"(this may take a few minutes)"),
446                            crayons.normal(u"...", bold=True),
447                        )
448                    )
449                    with create_spinner("Installing python...") as sp:
450                        try:
451                            c = installer.install(version)
452                        except InstallerError as e:
453                            sp.fail(environments.PIPENV_SPINNER_FAIL_TEXT.format(
454                                "Failed...")
455                            )
456                            click.echo(fix_utf8("Something went wrong..."), err=True)
457                            click.echo(crayons.cyan(e.err), err=True)
458                        else:
459                            sp.ok(environments.PIPENV_SPINNER_OK_TEXT.format("Success!"))
460                            # Print the results, in a beautiful blue...
461                            click.echo(crayons.cyan(c.out), err=True)
462                            # Clear the pythonfinder caches
463                            from .vendor.pythonfinder import Finder
464                            finder = Finder(system=False, global_search=True)
465                            finder.find_python_version.cache_clear()
466                            finder.find_all_python_versions.cache_clear()
467                    # Find the newly installed Python, hopefully.
468                    version = str(version)
469                    path_to_python = find_a_system_python(version)
470                    try:
471                        assert python_version(path_to_python) == version
472                    except AssertionError:
473                        click.echo(
474                            "{0}: The Python you just installed is not available on your {1}, apparently."
475                            "".format(
476                                crayons.red("Warning", bold=True),
477                                crayons.normal("PATH", bold=True),
478                            ),
479                            err=True,
480                        )
481                        sys.exit(1)
482    return path_to_python
483
484
485def ensure_virtualenv(three=None, python=None, site_packages=None, pypi_mirror=None):
486    """Creates a virtualenv, if one doesn't exist."""
487    from .environments import PIPENV_USE_SYSTEM
488
489    def abort():
490        sys.exit(1)
491
492    global USING_DEFAULT_PYTHON
493    if not project.virtualenv_exists:
494        try:
495            # Ensure environment variables are set properly.
496            ensure_environment()
497            # Ensure Python is available.
498            python = ensure_python(three=three, python=python)
499            if python is not None and not isinstance(python, six.string_types):
500                python = python.path.as_posix()
501            # Create the virtualenv.
502            # Abort if --system (or running in a virtualenv).
503            if PIPENV_USE_SYSTEM:
504                click.echo(
505                    crayons.red(
506                        "You are attempting to re–create a virtualenv that "
507                        "Pipenv did not create. Aborting."
508                    )
509                )
510                sys.exit(1)
511            do_create_virtualenv(
512                python=python, site_packages=site_packages, pypi_mirror=pypi_mirror
513            )
514        except KeyboardInterrupt:
515            # If interrupted, cleanup the virtualenv.
516            cleanup_virtualenv(bare=False)
517            sys.exit(1)
518    # If --three, --two, or --python were passed...
519    elif (python) or (three is not None) or (site_packages is not None):
520        USING_DEFAULT_PYTHON = False
521        # Ensure python is installed before deleting existing virtual env
522        python = ensure_python(three=three, python=python)
523        if python is not None and not isinstance(python, six.string_types):
524            python = python.path.as_posix()
525
526        click.echo(crayons.red("Virtualenv already exists!"), err=True)
527        # If VIRTUAL_ENV is set, there is a possibility that we are
528        # going to remove the active virtualenv that the user cares
529        # about, so confirm first.
530        if "VIRTUAL_ENV" in os.environ:
531            if not (
532                PIPENV_YES or click.confirm("Remove existing virtualenv?", default=True)
533            ):
534                abort()
535        click.echo(
536            crayons.normal(fix_utf8("Removing existing virtualenv..."), bold=True), err=True
537        )
538        # Remove the virtualenv.
539        cleanup_virtualenv(bare=True)
540        # Call this function again.
541        ensure_virtualenv(
542            three=three,
543            python=python,
544            site_packages=site_packages,
545            pypi_mirror=pypi_mirror,
546        )
547
548
549def ensure_project(
550    three=None,
551    python=None,
552    validate=True,
553    system=False,
554    warn=True,
555    site_packages=None,
556    deploy=False,
557    skip_requirements=False,
558    pypi_mirror=None,
559    clear=False,
560):
561    """Ensures both Pipfile and virtualenv exist for the project."""
562    from .environments import PIPENV_USE_SYSTEM
563
564    # Clear the caches, if appropriate.
565    if clear:
566        print("clearing")
567        sys.exit(1)
568
569    # Automatically use an activated virtualenv.
570    if PIPENV_USE_SYSTEM:
571        system = True
572    if not project.pipfile_exists and deploy:
573        raise exceptions.PipfileNotFound
574    # Skip virtualenv creation when --system was used.
575    if not system:
576        ensure_virtualenv(
577            three=three,
578            python=python,
579            site_packages=site_packages,
580            pypi_mirror=pypi_mirror,
581        )
582        if warn:
583            # Warn users if they are using the wrong version of Python.
584            if project.required_python_version:
585                path_to_python = which("python") or which("py")
586                if path_to_python and project.required_python_version not in (
587                    python_version(path_to_python) or ""
588                ):
589                    click.echo(
590                        "{0}: Your Pipfile requires {1} {2}, "
591                        "but you are using {3} ({4}).".format(
592                            crayons.red("Warning", bold=True),
593                            crayons.normal("python_version", bold=True),
594                            crayons.cyan(project.required_python_version),
595                            crayons.cyan(python_version(path_to_python) or "unknown"),
596                            crayons.green(shorten_path(path_to_python)),
597                        ),
598                        err=True,
599                    )
600                    click.echo(
601                        "  {0} and rebuilding the virtual environment "
602                        "may resolve the issue.".format(crayons.green("$ pipenv --rm")),
603                        err=True,
604                    )
605                    if not deploy:
606                        click.echo(
607                            "  {0} will surely fail."
608                            "".format(crayons.yellow("$ pipenv check")),
609                            err=True,
610                        )
611                    else:
612                        raise exceptions.DeployException
613    # Ensure the Pipfile exists.
614    ensure_pipfile(
615        validate=validate, skip_requirements=skip_requirements, system=system
616    )
617
618
619def shorten_path(location, bold=False):
620    """Returns a visually shorter representation of a given system path."""
621    original = location
622    short = os.sep.join(
623        [s[0] if len(s) > (len("2long4")) else s for s in location.split(os.sep)]
624    )
625    short = short.split(os.sep)
626    short[-1] = original.split(os.sep)[-1]
627    if bold:
628        short[-1] = str(crayons.normal(short[-1], bold=True))
629    return os.sep.join(short)
630
631
632# return short
633def do_where(virtualenv=False, bare=True):
634    """Executes the where functionality."""
635    if not virtualenv:
636        if not project.pipfile_exists:
637            click.echo(
638                "No Pipfile present at project home. Consider running "
639                "{0} first to automatically generate a Pipfile for you."
640                "".format(crayons.green("`pipenv install`")),
641                err=True,
642            )
643            return
644        location = project.pipfile_location
645        # Shorten the virtual display of the path to the virtualenv.
646        if not bare:
647            location = shorten_path(location)
648            click.echo(
649                "Pipfile found at {0}.\n  Considering this to be the project home."
650                "".format(crayons.green(location)),
651                err=True,
652            )
653        else:
654            click.echo(project.project_directory)
655    else:
656        location = project.virtualenv_location
657        if not bare:
658            click.echo(
659                "Virtualenv location: {0}".format(crayons.green(location)), err=True
660            )
661        else:
662            click.echo(location)
663
664
665def _cleanup_procs(procs, failed_deps_queue, retry=True):
666    while not procs.empty():
667        c = procs.get()
668        if not c.blocking:
669            c.block()
670        failed = False
671        if c.return_code != 0:
672            failed = True
673        if "Ignoring" in c.out:
674            click.echo(crayons.yellow(c.out.strip()))
675        elif environments.is_verbose():
676            click.echo(crayons.cyan(c.out.strip() or c.err.strip()))
677        # The Installation failed...
678        if failed:
679            # If there is a mismatch in installed locations or the install fails
680            # due to wrongful disabling of pep517, we should allow for
681            # additional passes at installation
682            if "does not match installed location" in c.err:
683                project.environment.expand_egg_links()
684                click.echo("{0}".format(
685                    crayons.yellow(
686                        "Failed initial installation: Failed to overwrite existing "
687                        "package, likely due to path aliasing. Expanding and trying "
688                        "again!"
689                    )
690                ))
691                dep = c.dep.copy()
692                dep.use_pep517 = True
693            elif "Disabling PEP 517 processing is invalid" in c.err:
694                dep = c.dep.copy()
695                dep.use_pep517 = True
696            elif not retry:
697                # The Installation failed...
698                # We echo both c.out and c.err because pip returns error details on out.
699                err = c.err.strip().splitlines() if c.err else []
700                out = c.out.strip().splitlines() if c.out else []
701                err_lines = [line for message in [out, err] for line in message]
702                # Return the subprocess' return code.
703                raise exceptions.InstallError(c.dep.name, extra=err_lines)
704            else:
705                # Alert the user.
706                dep = c.dep.copy()
707                dep.use_pep517 = False
708                click.echo(
709                    "{0} {1}! Will try again.".format(
710                        crayons.red("An error occurred while installing"),
711                        crayons.green(dep.as_line()),
712                    ), err=True
713                )
714            # Save the Failed Dependency for later.
715            failed_deps_queue.put(dep)
716
717
718def batch_install(deps_list, procs, failed_deps_queue,
719                  requirements_dir, no_deps=True, ignore_hashes=False,
720                  allow_global=False, blocking=False, pypi_mirror=None,
721                  retry=True, sequential_deps=None):
722    from .vendor.requirementslib.models.utils import strip_extras_markers_from_requirement
723    if sequential_deps is None:
724        sequential_deps = []
725    failed = (not retry)
726    install_deps = not no_deps
727    if not failed:
728        label = INSTALL_LABEL if not PIPENV_HIDE_EMOJIS else ""
729    else:
730        label = INSTALL_LABEL2
731
732    deps_to_install = deps_list[:]
733    deps_to_install.extend(sequential_deps)
734    deps_to_install = [
735        dep for dep in deps_to_install if not project.environment.is_satisfied(dep)
736    ]
737    sequential_dep_names = [d.name for d in sequential_deps]
738
739    deps_list_bar = progress.bar(
740        deps_to_install, width=32,
741        label=label
742    )
743
744    trusted_hosts = []
745    # Install these because
746    for dep in deps_list_bar:
747        extra_indexes = []
748        if dep.req.req:
749            dep.req.req = strip_extras_markers_from_requirement(dep.req.req)
750        if dep.markers:
751            dep.markers = str(strip_extras_markers_from_requirement(dep.get_markers()))
752        # Install the module.
753        is_artifact = False
754        if dep.is_file_or_url and (dep.is_direct_url or any(
755            dep.req.uri.endswith(ext) for ext in ["zip", "tar.gz"]
756        )):
757            is_artifact = True
758        elif dep.is_vcs:
759            is_artifact = True
760        if not PIPENV_RESOLVE_VCS and is_artifact and not dep.editable:
761            install_deps = True
762            no_deps = False
763
764        with vistir.contextmanagers.temp_environ():
765            if not allow_global:
766                os.environ["PIP_USER"] = vistir.compat.fs_str("0")
767                if "PYTHONHOME" in os.environ:
768                    del os.environ["PYTHONHOME"]
769            if "GIT_CONFIG" in os.environ and dep.is_vcs:
770                del os.environ["GIT_CONFIG"]
771            use_pep517 = True
772            if failed and not dep.is_vcs:
773                use_pep517 = getattr(dep, "use_pep517", False)
774
775            c = pip_install(
776                dep,
777                ignore_hashes=any([ignore_hashes, dep.editable, dep.is_vcs]),
778                allow_global=allow_global,
779                no_deps=not install_deps,
780                block=any([dep.editable, dep.is_vcs, blocking]),
781                index=dep.index,
782                requirements_dir=requirements_dir,
783                pypi_mirror=pypi_mirror,
784                trusted_hosts=trusted_hosts,
785                extra_indexes=extra_indexes,
786                use_pep517=use_pep517,
787            )
788            c.dep = dep
789            # if dep.is_vcs or dep.editable:
790            is_sequential = sequential_deps and dep.name in sequential_dep_names
791            if is_sequential:
792                c.block()
793
794            procs.put(c)
795            if procs.full() or procs.qsize() == len(deps_list) or is_sequential:
796                _cleanup_procs(procs, failed_deps_queue, retry=retry)
797
798
799def do_install_dependencies(
800    dev=False,
801    dev_only=False,
802    bare=False,
803    emit_requirements=False,
804    allow_global=False,
805    ignore_hashes=False,
806    skip_lock=False,
807    concurrent=True,
808    requirements_dir=None,
809    pypi_mirror=None,
810):
811    """"
812    Executes the install functionality.
813
814    If emit_requirements is True, simply spits out a requirements format to stdout.
815    """
816
817    from six.moves import queue
818    if emit_requirements:
819        bare = True
820    # Load the lockfile if it exists, or if dev_only is being used.
821    if skip_lock or not project.lockfile_exists:
822        if not bare:
823            click.echo(
824                crayons.normal(fix_utf8("Installing dependencies from Pipfile..."), bold=True)
825            )
826        # skip_lock should completely bypass the lockfile (broken in 4dac1676)
827        lockfile = project.get_or_create_lockfile(from_pipfile=True)
828    else:
829        lockfile = project.get_or_create_lockfile()
830        if not bare:
831            click.echo(
832                crayons.normal(
833                    fix_utf8("Installing dependencies from Pipfile.lock ({0})...".format(
834                        lockfile["_meta"].get("hash", {}).get("sha256")[-6:]
835                    )),
836                    bold=True,
837                )
838            )
839    # Allow pip to resolve dependencies when in skip-lock mode.
840    no_deps = not skip_lock  # skip_lock true, no_deps False, pip resolves deps
841    dev = dev or dev_only
842    deps_list = list(lockfile.get_requirements(dev=dev, only=dev_only))
843    if emit_requirements:
844        index_args = prepare_pip_source_args(
845            get_source_list(pypi_mirror=pypi_mirror, project=project)
846        )
847        index_args = " ".join(index_args).replace(" -", "\n-")
848        deps = [
849            req.as_line(sources=False, include_hashes=False) for req in deps_list
850        ]
851        click.echo(index_args)
852        click.echo("\n".join(sorted(deps)))
853        sys.exit(0)
854    if concurrent:
855        nprocs = PIPENV_MAX_SUBPROCESS
856    else:
857        nprocs = 1
858    procs = queue.Queue(maxsize=nprocs)
859    failed_deps_queue = queue.Queue()
860    if skip_lock:
861        ignore_hashes = True
862    editable_or_vcs_deps = [dep for dep in deps_list if (dep.editable or dep.vcs)]
863    normal_deps = [dep for dep in deps_list if not (dep.editable or dep.vcs)]
864    install_kwargs = {
865        "no_deps": no_deps, "ignore_hashes": ignore_hashes, "allow_global": allow_global,
866        "blocking": not concurrent, "pypi_mirror": pypi_mirror,
867        "sequential_deps": editable_or_vcs_deps
868    }
869
870    batch_install(
871        normal_deps, procs, failed_deps_queue, requirements_dir, **install_kwargs
872    )
873
874    if not procs.empty():
875        _cleanup_procs(procs, failed_deps_queue)
876
877    # click.echo(crayons.normal(
878    #     decode_for_output("Installing editable and vcs dependencies..."), bold=True
879    # ))
880
881    # install_kwargs.update({"blocking": True})
882    # # XXX: All failed and editable/vcs deps should be installed in sequential mode!
883    # procs = queue.Queue(maxsize=1)
884    # batch_install(
885    #     editable_or_vcs_deps, procs, failed_deps_queue, requirements_dir,
886    #     **install_kwargs
887    # )
888
889    # Iterate over the hopefully-poorly-packaged dependencies...
890    if not failed_deps_queue.empty():
891        click.echo(
892            crayons.normal(fix_utf8("Installing initially failed dependencies..."), bold=True)
893        )
894        retry_list = []
895        while not failed_deps_queue.empty():
896            failed_dep = failed_deps_queue.get()
897            retry_list.append(failed_dep)
898        install_kwargs.update({"retry": False})
899        batch_install(
900            retry_list, procs, failed_deps_queue, requirements_dir, **install_kwargs
901        )
902    if not procs.empty():
903        _cleanup_procs(procs, failed_deps_queue, retry=False)
904
905
906def convert_three_to_python(three, python):
907    """Converts a Three flag into a Python flag, and raises customer warnings
908    in the process, if needed.
909    """
910    if not python:
911        if three is False:
912            return "2"
913
914        elif three is True:
915            return "3"
916
917    else:
918        return python
919
920
921def do_create_virtualenv(python=None, site_packages=None, pypi_mirror=None):
922    """Creates a virtualenv."""
923
924    click.echo(
925        crayons.normal(fix_utf8("Creating a virtualenv for this project..."), bold=True), err=True
926    )
927    click.echo(
928        u"Pipfile: {0}".format(crayons.yellow(project.pipfile_location, bold=True)),
929        err=True,
930    )
931
932    # Default to using sys.executable, if Python wasn't provided.
933    using_string = u"Using"
934    if not python:
935        python = sys.executable
936        using_string = "Using default python from"
937    click.echo(
938        u"{0} {1} {3} {2}".format(
939            crayons.normal(using_string, bold=True),
940            crayons.yellow(python, bold=True),
941            crayons.normal(fix_utf8("to create virtualenv..."), bold=True),
942            crayons.green("({0})".format(python_version(python))),
943        ),
944        err=True,
945    )
946
947    cmd = [
948        vistir.compat.Path(sys.executable).absolute().as_posix(),
949        "-m",
950        "virtualenv",
951        "--prompt=({0}) ".format(project.name),
952        "--python={0}".format(python),
953        project.get_location_for_virtualenv(),
954    ]
955
956    # Pass site-packages flag to virtualenv, if desired...
957    if site_packages:
958        click.echo(
959            crayons.normal(fix_utf8("Making site-packages available..."), bold=True), err=True
960        )
961        cmd.append("--system-site-packages")
962
963    if pypi_mirror:
964        pip_config = {"PIP_INDEX_URL": vistir.misc.fs_str(pypi_mirror)}
965    else:
966        pip_config = {}
967
968    # Actually create the virtualenv.
969    error = None
970    with create_spinner(u"Creating virtual environment...") as sp:
971        with interrupt_handled_subprocess(cmd, combine_stderr=False, env=pip_config) as c:
972            click.echo(crayons.cyan(u"{0}".format(c.out)), err=True)
973            if c.returncode != 0:
974                error = c.err if environments.is_verbose() else exceptions.prettify_exc(c.err)
975                sp.fail(environments.PIPENV_SPINNER_FAIL_TEXT.format(u"Failed creating virtual environment"))
976            else:
977                sp.green.ok(environments.PIPENV_SPINNER_OK_TEXT.format(u"Successfully created virtual environment!"))
978    if error is not None:
979        raise exceptions.VirtualenvCreationException(
980            extra=crayons.red("{0}".format(error))
981        )
982
983    # Associate project directory with the environment.
984    # This mimics Pew's "setproject".
985    project_file_name = os.path.join(project.virtualenv_location, ".project")
986    with open(project_file_name, "w") as f:
987        f.write(vistir.misc.fs_str(project.project_directory))
988    from .environment import Environment
989    sources = project.pipfile_sources
990    # project.get_location_for_virtualenv is only for if we are creating a new virtualenv
991    # whereas virtualenv_location is for the current path to the runtime
992    project._environment = Environment(
993        prefix=project.virtualenv_location,
994        is_venv=True,
995        sources=sources,
996        pipfile=project.parsed_pipfile,
997        project=project
998    )
999    project._environment.add_dist("pipenv")
1000    # Say where the virtualenv is.
1001    do_where(virtualenv=True, bare=False)
1002
1003
1004def parse_download_fname(fname, name):
1005    fname, fextension = os.path.splitext(fname)
1006    if fextension == ".whl":
1007        fname = "-".join(fname.split("-")[:-3])
1008    if fname.endswith(".tar"):
1009        fname, _ = os.path.splitext(fname)
1010    # Substring out package name (plus dash) from file name to get version.
1011    version = fname[len(name) + 1 :]
1012    # Ignore implicit post releases in version number.
1013    if "-" in version and version.split("-")[1].isdigit():
1014        version = version.split("-")[0]
1015    return version
1016
1017
1018def get_downloads_info(names_map, section):
1019    from .vendor.requirementslib.models.requirements import Requirement
1020
1021    info = []
1022    p = project.parsed_pipfile
1023    for fname in os.listdir(project.download_location):
1024        # Get name from filename mapping.
1025        name = Requirement.from_line(names_map[fname]).name
1026        # Get the version info from the filenames.
1027        version = parse_download_fname(fname, name)
1028        # Get the hash of each file.
1029        cmd = '{0} hash "{1}"'.format(
1030            escape_grouped_arguments(which_pip()),
1031            os.sep.join([project.download_location, fname]),
1032        )
1033        c = delegator.run(cmd)
1034        hash = c.out.split("--hash=")[1].strip()
1035        # Verify we're adding the correct version from Pipfile
1036        # and not one from a dependency.
1037        specified_version = p[section].get(name, "")
1038        if is_required_version(version, specified_version):
1039            info.append(dict(name=name, version=version, hash=hash))
1040    return info
1041
1042
1043def overwrite_dev(prod, dev):
1044    dev_keys = set(list(dev.keys()))
1045    prod_keys = set(list(prod.keys()))
1046    for pkg in dev_keys & prod_keys:
1047        dev[pkg] = prod[pkg]
1048    return dev
1049
1050
1051def do_lock(
1052    ctx=None,
1053    system=False,
1054    clear=False,
1055    pre=False,
1056    keep_outdated=False,
1057    write=True,
1058    pypi_mirror=None,
1059):
1060    """Executes the freeze functionality."""
1061
1062    cached_lockfile = {}
1063    if not pre:
1064        pre = project.settings.get("allow_prereleases")
1065    if keep_outdated:
1066        if not project.lockfile_exists:
1067            raise exceptions.PipenvOptionsError(
1068                "--keep-outdated", ctx=ctx,
1069                message="Pipfile.lock must exist to use --keep-outdated!"
1070            )
1071        cached_lockfile = project.lockfile_content
1072    # Create the lockfile.
1073    lockfile = project._lockfile
1074    # Cleanup lockfile.
1075    for section in ("default", "develop"):
1076        for k, v in lockfile[section].copy().items():
1077            if not hasattr(v, "keys"):
1078                del lockfile[section][k]
1079    # Ensure that develop inherits from default.
1080    dev_packages = project.dev_packages.copy()
1081    dev_packages = overwrite_dev(project.packages, dev_packages)
1082    # Resolve dev-package dependencies, with pip-tools.
1083    for is_dev in [True, False]:
1084        pipfile_section = "dev-packages" if is_dev else "packages"
1085        if project.pipfile_exists:
1086            packages = project.parsed_pipfile.get(pipfile_section, {})
1087        else:
1088            packages = getattr(project, pipfile_section.replace("-", "_"))
1089
1090        if write:
1091            # Alert the user of progress.
1092            click.echo(
1093                u"{0} {1} {2}".format(
1094                    crayons.normal(u"Locking"),
1095                    crayons.yellow(u"[{0}]".format(pipfile_section.replace("_", "-"))),
1096                    crayons.normal(fix_utf8("dependencies...")),
1097                ),
1098                err=True,
1099            )
1100
1101        # Mutates the lockfile
1102        venv_resolve_deps(
1103            packages,
1104            which=which,
1105            project=project,
1106            dev=is_dev,
1107            clear=clear,
1108            pre=pre,
1109            allow_global=system,
1110            pypi_mirror=pypi_mirror,
1111            pipfile=packages,
1112            lockfile=lockfile,
1113            keep_outdated=keep_outdated
1114        )
1115
1116    # Support for --keep-outdated...
1117    if keep_outdated:
1118        from pipenv.vendor.packaging.utils import canonicalize_name
1119        for section_name, section in (
1120            ("default", project.packages),
1121            ("develop", project.dev_packages),
1122        ):
1123            for package_specified in section.keys():
1124                if not is_pinned(section[package_specified]):
1125                    canonical_name = canonicalize_name(package_specified)
1126                    if canonical_name in cached_lockfile[section_name]:
1127                        lockfile[section_name][canonical_name] = cached_lockfile[
1128                            section_name
1129                        ][canonical_name].copy()
1130            for key in ["default", "develop"]:
1131                packages = set(cached_lockfile[key].keys())
1132                new_lockfile = set(lockfile[key].keys())
1133                missing = packages - new_lockfile
1134                for missing_pkg in missing:
1135                    lockfile[key][missing_pkg] = cached_lockfile[key][missing_pkg].copy()
1136    # Overwrite any develop packages with default packages.
1137    lockfile["develop"].update(overwrite_dev(lockfile.get("default", {}), lockfile["develop"]))
1138    if write:
1139        project.write_lockfile(lockfile)
1140        click.echo(
1141            "{0}".format(
1142                crayons.normal(
1143                    "Updated Pipfile.lock ({0})!".format(
1144                        lockfile["_meta"].get("hash", {}).get("sha256")[-6:]
1145                    ),
1146                    bold=True,
1147                )
1148            ),
1149            err=True,
1150        )
1151    else:
1152        return lockfile
1153
1154
1155def do_purge(bare=False, downloads=False, allow_global=False):
1156    """Executes the purge functionality."""
1157
1158    if downloads:
1159        if not bare:
1160            click.echo(crayons.normal(fix_utf8("Clearing out downloads directory..."), bold=True))
1161        vistir.path.rmtree(project.download_location)
1162        return
1163
1164    # Remove comments from the output, if any.
1165    installed = set([
1166        pep423_name(pkg.project_name) for pkg in project.environment.get_installed_packages()
1167    ])
1168    bad_pkgs = set([pep423_name(pkg) for pkg in BAD_PACKAGES])
1169    # Remove setuptools, pip, etc from targets for removal
1170    to_remove = installed - bad_pkgs
1171
1172    # Skip purging if there is no packages which needs to be removed
1173    if not to_remove:
1174        if not bare:
1175            click.echo("Found 0 installed package, skip purging.")
1176            click.echo(crayons.green("Environment now purged and fresh!"))
1177        return installed
1178
1179    if not bare:
1180        click.echo(
1181            fix_utf8("Found {0} installed package(s), purging...".format(len(to_remove)))
1182        )
1183
1184    command = "{0} uninstall {1} -y".format(
1185        escape_grouped_arguments(which_pip(allow_global=allow_global)),
1186        " ".join(to_remove),
1187    )
1188    if environments.is_verbose():
1189        click.echo("$ {0}".format(command))
1190    c = delegator.run(command)
1191    if c.return_code != 0:
1192        raise exceptions.UninstallError(installed, command, c.out + c.err, c.return_code)
1193    if not bare:
1194        click.echo(crayons.cyan(c.out))
1195        click.echo(crayons.green("Environment now purged and fresh!"))
1196    return installed
1197
1198
1199def do_init(
1200    dev=False,
1201    dev_only=False,
1202    emit_requirements=False,
1203    allow_global=False,
1204    ignore_pipfile=False,
1205    skip_lock=False,
1206    system=False,
1207    concurrent=True,
1208    deploy=False,
1209    pre=False,
1210    keep_outdated=False,
1211    requirements_dir=None,
1212    pypi_mirror=None,
1213):
1214    """Executes the init functionality."""
1215    from .environments import (
1216        PIPENV_VIRTUALENV, PIPENV_DEFAULT_PYTHON_VERSION, PIPENV_PYTHON, PIPENV_USE_SYSTEM
1217    )
1218    python = None
1219    if PIPENV_PYTHON is not None:
1220        python = PIPENV_PYTHON
1221    elif PIPENV_DEFAULT_PYTHON_VERSION is not None:
1222        python = PIPENV_DEFAULT_PYTHON_VERSION
1223
1224    if not system and not PIPENV_USE_SYSTEM:
1225        if not project.virtualenv_exists:
1226            try:
1227                do_create_virtualenv(python=python, three=None, pypi_mirror=pypi_mirror)
1228            except KeyboardInterrupt:
1229                cleanup_virtualenv(bare=False)
1230                sys.exit(1)
1231    # Ensure the Pipfile exists.
1232    if not deploy:
1233        ensure_pipfile(system=system)
1234    if not requirements_dir:
1235        requirements_dir = vistir.path.create_tracked_tempdir(
1236            suffix="-requirements", prefix="pipenv-"
1237        )
1238    # Write out the lockfile if it doesn't exist, but not if the Pipfile is being ignored
1239    if (project.lockfile_exists and not ignore_pipfile) and not skip_lock:
1240        old_hash = project.get_lockfile_hash()
1241        new_hash = project.calculate_pipfile_hash()
1242        if new_hash != old_hash:
1243            if deploy:
1244                click.echo(
1245                    crayons.red(
1246                        "Your Pipfile.lock ({0}) is out of date. Expected: ({1}).".format(
1247                            old_hash[-6:], new_hash[-6:]
1248                        )
1249                    )
1250                )
1251                raise exceptions.DeployException
1252                sys.exit(1)
1253            elif (system or allow_global) and not (PIPENV_VIRTUALENV):
1254                click.echo(
1255                    crayons.yellow(fix_utf8(
1256                        "Pipfile.lock ({0}) out of date, but installation "
1257                        "uses {1} re-building lockfile must happen in "
1258                        "isolation. Please rebuild lockfile in a virtualenv. "
1259                        "Continuing anyway...".format(
1260                            old_hash[-6:], "--system"
1261                        ))
1262                    ),
1263                    err=True,
1264                )
1265            else:
1266                if old_hash:
1267                    msg = fix_utf8("Pipfile.lock ({0}) out of date, updating to ({1})...")
1268                else:
1269                    msg = fix_utf8("Pipfile.lock is corrupted, replaced with ({1})...")
1270                click.echo(
1271                    crayons.yellow(msg.format(old_hash[-6:], new_hash[-6:]), bold=True),
1272                    err=True,
1273                )
1274                do_lock(
1275                    system=system,
1276                    pre=pre,
1277                    keep_outdated=keep_outdated,
1278                    write=True,
1279                    pypi_mirror=pypi_mirror,
1280                )
1281    # Write out the lockfile if it doesn't exist.
1282    if not project.lockfile_exists and not skip_lock:
1283        # Unless we're in a virtualenv not managed by pipenv, abort if we're
1284        # using the system's python.
1285        if (system or allow_global) and not (PIPENV_VIRTUALENV):
1286            raise exceptions.PipenvOptionsError(
1287                "--system",
1288                "--system is intended to be used for Pipfile installation, "
1289                "not installation of specific packages. Aborting.\n"
1290                "See also: --deploy flag."
1291            )
1292        else:
1293            click.echo(
1294                crayons.normal(fix_utf8("Pipfile.lock not found, creating..."), bold=True),
1295                err=True,
1296            )
1297            do_lock(
1298                system=system,
1299                pre=pre,
1300                keep_outdated=keep_outdated,
1301                write=True,
1302                pypi_mirror=pypi_mirror,
1303            )
1304    do_install_dependencies(
1305        dev=dev,
1306        dev_only=dev_only,
1307        emit_requirements=emit_requirements,
1308        allow_global=allow_global,
1309        skip_lock=skip_lock,
1310        concurrent=concurrent,
1311        requirements_dir=requirements_dir,
1312        pypi_mirror=pypi_mirror,
1313    )
1314
1315    # Hint the user what to do to activate the virtualenv.
1316    if not allow_global and not deploy and "PIPENV_ACTIVE" not in os.environ:
1317        click.echo(
1318            "To activate this project's virtualenv, run {0}.\n"
1319            "Alternatively, run a command "
1320            "inside the virtualenv with {1}.".format(
1321                crayons.yellow("pipenv shell"), crayons.yellow("pipenv run")
1322            )
1323        )
1324
1325
1326def get_pip_args(
1327    pre=False,  # type: bool
1328    verbose=False,  # type: bool,
1329    upgrade=False,  # type: bool,
1330    require_hashes=False,  # type: bool,
1331    no_build_isolation=False,  # type: bool,
1332    no_use_pep517=False,  # type: bool,
1333    no_deps=False,  # type: bool,
1334    selective_upgrade=False,  # type: bool
1335    src_dir=None,  # type: Optional[str]
1336):
1337    # type: (...) -> List[str]
1338    from .vendor.packaging.version import parse as parse_version
1339    arg_map = {
1340        "pre": ["--pre"],
1341        "verbose": ["--verbose"],
1342        "upgrade": ["--upgrade"],
1343        "require_hashes": ["--require-hashes"],
1344        "no_build_isolation": ["--no-build-isolation"],
1345        "no_use_pep517": [],
1346        "no_deps": ["--no-deps"],
1347        "selective_upgrade": [
1348            "--upgrade-strategy=only-if-needed",
1349            "--exists-action={0}".format(PIP_EXISTS_ACTION or "i")
1350        ],
1351        "src_dir": src_dir,
1352    }
1353    if project.environment.pip_version >= parse_version("19.0"):
1354        arg_map["no_use_pep517"].append("--no-use-pep517")
1355    if project.environment.pip_version < parse_version("19.1"):
1356        arg_map["no_use_pep517"].append("--no-build-isolation")
1357    arg_set = []
1358    for key in arg_map.keys():
1359        if key in locals() and locals().get(key):
1360            arg_set.extend(arg_map.get(key))
1361        elif key == "selective_upgrade" and not locals().get(key):
1362            arg_set.append("--exists-action=i")
1363    return list(vistir.misc.dedup(arg_set))
1364
1365
1366def get_requirement_line(
1367    requirement,  # type: Requirement
1368    src_dir=None,  # type: Optional[str]
1369    include_hashes=True,  # type: bool
1370    format_for_file=False,  # type: bool
1371):
1372    # type: (...) -> Union[List[str], str]
1373    line = None
1374    if requirement.vcs or requirement.is_file_or_url:
1375        if src_dir and requirement.line_instance.wheel_kwargs:
1376            requirement.line_instance._wheel_kwargs.update({
1377                "src_dir": src_dir
1378            })
1379        requirement.line_instance.vcsrepo
1380        line = requirement.line_instance.line
1381        if requirement.line_instance.markers:
1382            line = '{0}; {1}'.format(line, requirement.line_instance.markers)
1383            if not format_for_file:
1384                line = '"{0}"'.format(line)
1385        if requirement.editable:
1386            if not format_for_file:
1387                return ["-e", line]
1388            return '-e {0}'.format(line)
1389        if not format_for_file:
1390            return [line]
1391        return line
1392    return requirement.as_line(include_hashes=include_hashes, as_list=not format_for_file)
1393
1394
1395def write_requirement_to_file(
1396    requirement,  # type: Requirement
1397    requirements_dir=None,  # type: Optional[str]
1398    src_dir=None,  # type: Optional[str]
1399    include_hashes=True  # type: bool
1400):
1401    # type: (...) -> str
1402    if not requirements_dir:
1403        requirements_dir = vistir.path.create_tracked_tempdir(
1404            prefix="pipenv", suffix="requirements")
1405    line = requirement.line_instance.get_line(
1406        with_prefix=True, with_hashes=include_hashes, with_markers=True, as_list=False
1407    )
1408
1409    f = vistir.compat.NamedTemporaryFile(
1410        prefix="pipenv-", suffix="-requirement.txt", dir=requirements_dir,
1411        delete=False
1412    )
1413    if environments.is_verbose():
1414        click.echo(
1415            "Writing supplied requirement line to temporary file: {0!r}".format(line),
1416            err=True
1417        )
1418    f.write(vistir.misc.to_bytes(line))
1419    r = f.name
1420    f.close()
1421    return r
1422
1423
1424def pip_install(
1425    requirement=None,
1426    r=None,
1427    allow_global=False,
1428    ignore_hashes=False,
1429    no_deps=None,
1430    block=True,
1431    index=None,
1432    pre=False,
1433    selective_upgrade=False,
1434    requirements_dir=None,
1435    extra_indexes=None,
1436    pypi_mirror=None,
1437    trusted_hosts=None,
1438    use_pep517=True
1439):
1440    piplogger = logging.getLogger("pipenv.patched.notpip._internal.commands.install")
1441    src_dir = None
1442    if not trusted_hosts:
1443        trusted_hosts = []
1444
1445    trusted_hosts.extend(os.environ.get("PIP_TRUSTED_HOSTS", []))
1446    if not allow_global:
1447        src_dir = os.getenv("PIP_SRC", os.getenv("PIP_SRC_DIR", project.virtualenv_src_location))
1448    else:
1449        src_dir = os.getenv("PIP_SRC", os.getenv("PIP_SRC_DIR"))
1450    if requirement:
1451        if requirement.editable or not requirement.hashes:
1452            ignore_hashes = True
1453        elif not (requirement.is_vcs or requirement.editable or requirement.vcs):
1454            ignore_hashes = False
1455    line = None
1456    # Try installing for each source in project.sources.
1457    if not index and requirement.index:
1458        index = requirement.index
1459    if index and not extra_indexes:
1460        extra_indexes = list(project.sources)
1461    if requirement and requirement.vcs or requirement.editable:
1462        requirement.index = None
1463        # Install dependencies when a package is a non-editable VCS dependency.
1464        # Don't specify a source directory when using --system.
1465        if not requirement.editable and no_deps is not True:
1466            # Leave this off becauase old lockfiles don't have all deps included
1467            # TODO: When can it be turned back on?
1468            no_deps = False
1469        elif requirement.editable and no_deps is None:
1470            no_deps = True
1471
1472    r = write_requirement_to_file(
1473        requirement, requirements_dir=requirements_dir, src_dir=src_dir,
1474        include_hashes=not ignore_hashes
1475    )
1476    sources = get_source_list(
1477        index, extra_indexes=extra_indexes, trusted_hosts=trusted_hosts,
1478        pypi_mirror=pypi_mirror
1479    )
1480    if r:
1481        with io.open(r, "r") as fh:
1482            if "--hash" not in fh.read():
1483                ignore_hashes = True
1484    if environments.is_verbose():
1485        piplogger.setLevel(logging.WARN)
1486        if requirement:
1487            click.echo(
1488                crayons.normal("Installing {0!r}".format(requirement.name), bold=True),
1489                err=True,
1490            )
1491
1492    pip_command = [which_pip(allow_global=allow_global), "install"]
1493    pip_args = get_pip_args(
1494        pre=pre, verbose=environments.is_verbose(), upgrade=True,
1495        selective_upgrade=selective_upgrade, no_use_pep517=not use_pep517,
1496        no_deps=no_deps, require_hashes=not ignore_hashes,
1497    )
1498    pip_command.extend(pip_args)
1499    if r:
1500        pip_command.extend(["-r", vistir.path.normalize_path(r)])
1501    elif line:
1502        pip_command.extend(line)
1503    pip_command.extend(prepare_pip_source_args(sources))
1504    if environments.is_verbose():
1505        click.echo("$ {0}".format(pip_command), err=True)
1506    cache_dir = vistir.compat.Path(PIPENV_CACHE_DIR)
1507    DEFAULT_EXISTS_ACTION = "w"
1508    if selective_upgrade:
1509        DEFAULT_EXISTS_ACTION = "i"
1510    exists_action = vistir.misc.fs_str(PIP_EXISTS_ACTION or DEFAULT_EXISTS_ACTION)
1511    pip_config = {
1512        "PIP_CACHE_DIR": vistir.misc.fs_str(cache_dir.as_posix()),
1513        "PIP_WHEEL_DIR": vistir.misc.fs_str(cache_dir.joinpath("wheels").as_posix()),
1514        "PIP_DESTINATION_DIR": vistir.misc.fs_str(
1515            cache_dir.joinpath("pkgs").as_posix()
1516        ),
1517        "PIP_EXISTS_ACTION": exists_action,
1518        "PATH": vistir.misc.fs_str(os.environ.get("PATH")),
1519    }
1520    if src_dir:
1521        if environments.is_verbose():
1522            click.echo("Using source directory: {0!r}".format(src_dir), err=True)
1523        pip_config.update(
1524            {"PIP_SRC": vistir.misc.fs_str(src_dir)}
1525        )
1526    cmd = Script.parse(pip_command)
1527    pip_command = cmd.cmdify()
1528    c = None
1529    c = delegator.run(pip_command, block=block, env=pip_config)
1530    c.env = pip_config
1531    return c
1532
1533
1534def pip_download(package_name):
1535    cache_dir = vistir.compat.Path(PIPENV_CACHE_DIR)
1536    pip_config = {
1537        "PIP_CACHE_DIR": vistir.misc.fs_str(cache_dir.as_posix()),
1538        "PIP_WHEEL_DIR": vistir.misc.fs_str(cache_dir.joinpath("wheels").as_posix()),
1539        "PIP_DESTINATION_DIR": vistir.misc.fs_str(
1540            cache_dir.joinpath("pkgs").as_posix()
1541        ),
1542    }
1543    for source in project.sources:
1544        cmd = '{0} download "{1}" -i {2} -d {3}'.format(
1545            escape_grouped_arguments(which_pip()),
1546            package_name,
1547            source["url"],
1548            project.download_location,
1549        )
1550        c = delegator.run(cmd, env=pip_config)
1551        if c.return_code == 0:
1552            break
1553
1554    return c
1555
1556
1557def fallback_which(command, location=None, allow_global=False, system=False):
1558    """
1559    A fallback implementation of the `which` utility command that relies exclusively on
1560    searching the path for commands.
1561
1562    :param str command: The command to search for, optional
1563    :param str location: The search location to prioritize (prepend to path), defaults to None
1564    :param bool allow_global: Whether to search the global path, defaults to False
1565    :param bool system: Whether to use the system python instead of pipenv's python, defaults to False
1566    :raises ValueError: Raised if no command is provided
1567    :raises TypeError: Raised if the command provided is not a string
1568    :return: A path to the discovered command location
1569    :rtype: str
1570    """
1571
1572    from .vendor.pythonfinder import Finder
1573    if not command:
1574        raise ValueError("fallback_which: Must provide a command to search for...")
1575    if not isinstance(command, six.string_types):
1576        raise TypeError("Provided command must be a string, received {0!r}".format(command))
1577    global_search = system or allow_global
1578    if location is None:
1579        global_search = True
1580    finder = Finder(system=False, global_search=global_search, path=location)
1581    if is_python_command(command):
1582        result = find_python(finder, command)
1583        if result:
1584            return result
1585    result = finder.which(command)
1586    if result:
1587        return result.path.as_posix()
1588    return ""
1589
1590
1591def which_pip(allow_global=False):
1592    """Returns the location of virtualenv-installed pip."""
1593
1594    location = None
1595    if "VIRTUAL_ENV" in os.environ:
1596        location = os.environ["VIRTUAL_ENV"]
1597    if allow_global:
1598        if location:
1599            pip = which("pip", location=location)
1600            if pip:
1601                return pip
1602
1603        for p in ("pip", "pip3", "pip2"):
1604            where = system_which(p)
1605            if where:
1606                return where
1607
1608    pip = which("pip")
1609    if not pip:
1610        pip = fallback_which("pip", allow_global=allow_global, location=location)
1611    return pip
1612
1613
1614def system_which(command, mult=False):
1615    """Emulates the system's which. Returns None if not found."""
1616    _which = "where" if os.name == "nt" else "which -a"
1617    os.environ.update({
1618        vistir.compat.fs_str(k): vistir.compat.fs_str(val)
1619        for k, val in os.environ.items()
1620    })
1621    result = None
1622    try:
1623        c = delegator.run("{0} {1}".format(_which, command))
1624        try:
1625            # Which Not found...
1626            if c.return_code == 127:
1627                click.echo(
1628                    "{}: the {} system utility is required for Pipenv to find Python installations properly."
1629                    "\n  Please install it.".format(
1630                        crayons.red("Warning", bold=True), crayons.yellow(_which)
1631                    ),
1632                    err=True,
1633                )
1634            assert c.return_code == 0
1635        except AssertionError:
1636            result = fallback_which(command, allow_global=True)
1637    except TypeError:
1638        if not result:
1639            result = fallback_which(command, allow_global=True)
1640    else:
1641        if not result:
1642            result = next(iter([c.out, c.err]), "").split("\n")
1643            result = next(iter(result)) if not mult else result
1644            return result
1645        if not result:
1646            result = fallback_which(command, allow_global=True)
1647    result = [result] if mult else result
1648    return result
1649
1650
1651def format_help(help):
1652    """Formats the help string."""
1653    help = help.replace("Options:", str(crayons.normal("Options:", bold=True)))
1654    help = help.replace(
1655        "Usage: pipenv", str("Usage: {0}".format(crayons.normal("pipenv", bold=True)))
1656    )
1657    help = help.replace("  check", str(crayons.red("  check", bold=True)))
1658    help = help.replace("  clean", str(crayons.red("  clean", bold=True)))
1659    help = help.replace("  graph", str(crayons.red("  graph", bold=True)))
1660    help = help.replace("  install", str(crayons.magenta("  install", bold=True)))
1661    help = help.replace("  lock", str(crayons.green("  lock", bold=True)))
1662    help = help.replace("  open", str(crayons.red("  open", bold=True)))
1663    help = help.replace("  run", str(crayons.yellow("  run", bold=True)))
1664    help = help.replace("  shell", str(crayons.yellow("  shell", bold=True)))
1665    help = help.replace("  scripts", str(crayons.yellow("  scripts", bold=True)))
1666    help = help.replace("  sync", str(crayons.green("  sync", bold=True)))
1667    help = help.replace("  uninstall", str(crayons.magenta("  uninstall", bold=True)))
1668    help = help.replace("  update", str(crayons.green("  update", bold=True)))
1669    additional_help = """
1670Usage Examples:
1671   Create a new project using Python 3.7, specifically:
1672   $ {1}
1673
1674   Remove project virtualenv (inferred from current directory):
1675   $ {9}
1676
1677   Install all dependencies for a project (including dev):
1678   $ {2}
1679
1680   Create a lockfile containing pre-releases:
1681   $ {6}
1682
1683   Show a graph of your installed dependencies:
1684   $ {4}
1685
1686   Check your installed dependencies for security vulnerabilities:
1687   $ {7}
1688
1689   Install a local setup.py into your virtual environment/Pipfile:
1690   $ {5}
1691
1692   Use a lower-level pip command:
1693   $ {8}
1694
1695Commands:""".format(
1696        crayons.yellow("pipenv --three"),
1697        crayons.yellow("pipenv --python 3.7"),
1698        crayons.yellow("pipenv install --dev"),
1699        crayons.yellow("pipenv lock"),
1700        crayons.yellow("pipenv graph"),
1701        crayons.yellow("pipenv install -e ."),
1702        crayons.yellow("pipenv lock --pre"),
1703        crayons.yellow("pipenv check"),
1704        crayons.yellow("pipenv run pip freeze"),
1705        crayons.yellow("pipenv --rm"),
1706    )
1707    help = help.replace("Commands:", additional_help)
1708    return help
1709
1710
1711def format_pip_error(error):
1712    error = error.replace("Expected", str(crayons.green("Expected", bold=True)))
1713    error = error.replace("Got", str(crayons.red("Got", bold=True)))
1714    error = error.replace(
1715        "THESE PACKAGES DO NOT MATCH THE HASHES FROM THE REQUIREMENTS FILE",
1716        str(
1717            crayons.red(
1718                "THESE PACKAGES DO NOT MATCH THE HASHES FROM Pipfile.lock!", bold=True
1719            )
1720        ),
1721    )
1722    error = error.replace(
1723        "someone may have tampered with them",
1724        str(crayons.red("someone may have tampered with them")),
1725    )
1726    error = error.replace("option to pip install", "option to 'pipenv install'")
1727    return error
1728
1729
1730def format_pip_output(out, r=None):
1731    def gen(out):
1732        for line in out.split("\n"):
1733            # Remove requirements file information from pip9 output.
1734            if "(from -r" in line:
1735                yield line[: line.index("(from -r")]
1736
1737            else:
1738                yield line
1739
1740    out = "\n".join([l for l in gen(out)])
1741    return out
1742
1743
1744def warn_in_virtualenv():
1745    # Only warn if pipenv isn't already active.
1746    if environments.is_in_virtualenv() and not environments.is_quiet():
1747        click.echo(
1748            "{0}: Pipenv found itself running within a virtual environment, "
1749            "so it will automatically use that environment, instead of "
1750            "creating its own for any project. You can set "
1751            "{1} to force pipenv to ignore that environment and create "
1752            "its own instead. You can set {2} to suppress this "
1753            "warning.".format(
1754                crayons.green("Courtesy Notice"),
1755                crayons.normal("PIPENV_IGNORE_VIRTUALENVS=1", bold=True),
1756                crayons.normal("PIPENV_VERBOSITY=-1", bold=True),
1757            ),
1758            err=True,
1759        )
1760
1761
1762def ensure_lockfile(keep_outdated=False, pypi_mirror=None):
1763    """Ensures that the lockfile is up-to-date."""
1764    if not keep_outdated:
1765        keep_outdated = project.settings.get("keep_outdated")
1766    # Write out the lockfile if it doesn't exist, but not if the Pipfile is being ignored
1767    if project.lockfile_exists:
1768        old_hash = project.get_lockfile_hash()
1769        new_hash = project.calculate_pipfile_hash()
1770        if new_hash != old_hash:
1771            click.echo(
1772                crayons.yellow(
1773                    fix_utf8("Pipfile.lock ({0}) out of date, updating to ({1})...".format(
1774                        old_hash[-6:], new_hash[-6:]
1775                    )),
1776                    bold=True,
1777                ),
1778                err=True,
1779            )
1780            do_lock(keep_outdated=keep_outdated, pypi_mirror=pypi_mirror)
1781    else:
1782        do_lock(keep_outdated=keep_outdated, pypi_mirror=pypi_mirror)
1783
1784
1785def do_py(system=False):
1786    if not project.virtualenv_exists:
1787        click.echo(
1788            "{}({}){}".format(
1789                crayons.red("No virtualenv has been created for this project "),
1790                crayons.yellow(project.project_directory, bold=True),
1791                crayons.red(" yet!")
1792            ),
1793            err=True,
1794        )
1795        return
1796
1797    try:
1798        click.echo(which("python", allow_global=system))
1799    except AttributeError:
1800        click.echo(crayons.red("No project found!"))
1801
1802
1803def do_outdated(pypi_mirror=None, pre=False, clear=False):
1804    # TODO: Allow --skip-lock here?
1805    from .vendor.requirementslib.models.requirements import Requirement
1806    from .vendor.requirementslib.models.utils import get_version
1807    from .vendor.packaging.utils import canonicalize_name
1808    from .vendor.vistir.compat import Mapping
1809    from collections import namedtuple
1810
1811    packages = {}
1812    package_info = namedtuple("PackageInfo", ["name", "installed", "available"])
1813
1814    installed_packages = project.environment.get_installed_packages()
1815    outdated_packages = {
1816        canonicalize_name(pkg.project_name): package_info
1817        (pkg.project_name, pkg.parsed_version, pkg.latest_version)
1818        for pkg in project.environment.get_outdated_packages()
1819    }
1820    reverse_deps = {
1821        canonicalize_name(name): deps
1822        for name, deps in project.environment.reverse_dependencies().items()
1823    }
1824    for result in installed_packages:
1825        dep = Requirement.from_line(str(result.as_requirement()))
1826        packages.update(dep.as_pipfile())
1827    updated_packages = {}
1828    lockfile = do_lock(clear=clear, pre=pre, write=False, pypi_mirror=pypi_mirror)
1829    for section in ("develop", "default"):
1830        for package in lockfile[section]:
1831            try:
1832                updated_packages[package] = lockfile[section][package]["version"]
1833            except KeyError:
1834                pass
1835    outdated = []
1836    skipped = []
1837    for package in packages:
1838        norm_name = pep423_name(package)
1839        if norm_name in updated_packages:
1840            if updated_packages[norm_name] != packages[package]:
1841                outdated.append(
1842                    package_info(package, updated_packages[norm_name], packages[package])
1843                )
1844            elif canonicalize_name(package) in outdated_packages:
1845                skipped.append(outdated_packages[canonicalize_name(package)])
1846    for package, old_version, new_version in skipped:
1847        name_in_pipfile = project.get_package_name_in_pipfile(package)
1848        pipfile_version_text = ""
1849        required = ""
1850        version = None
1851        if name_in_pipfile:
1852            version = get_version(project.packages[name_in_pipfile])
1853            rdeps = reverse_deps.get(canonicalize_name(package))
1854            if isinstance(rdeps, Mapping) and "required" in rdeps:
1855                required = " {0} required".format(rdeps["required"])
1856            if version:
1857                pipfile_version_text = " ({0} set in Pipfile)".format(version)
1858            else:
1859                pipfile_version_text = " (Unpinned in Pipfile)"
1860        click.echo(
1861            crayons.yellow(
1862                "Skipped Update of Package {0!s}: {1!s} installed,{2!s}{3!s}, "
1863                "{4!s} available.".format(
1864                    package, old_version, required, pipfile_version_text, new_version
1865                )
1866            ), err=True
1867        )
1868    if not outdated:
1869        click.echo(crayons.green("All packages are up to date!", bold=True))
1870        sys.exit(0)
1871    for package, new_version, old_version in outdated:
1872        click.echo(
1873            "Package {0!r} out-of-date: {1!r} installed, {2!r} available.".format(
1874                package, old_version, new_version
1875            )
1876        )
1877    sys.exit(bool(outdated))
1878
1879
1880def do_install(
1881    packages=False,
1882    editable_packages=False,
1883    index_url=False,
1884    extra_index_url=False,
1885    dev=False,
1886    three=False,
1887    python=False,
1888    pypi_mirror=None,
1889    system=False,
1890    lock=True,
1891    ignore_pipfile=False,
1892    skip_lock=False,
1893    requirementstxt=False,
1894    sequential=False,
1895    pre=False,
1896    code=False,
1897    deploy=False,
1898    keep_outdated=False,
1899    selective_upgrade=False,
1900    site_packages=None,
1901):
1902    from .environments import PIPENV_VIRTUALENV, PIPENV_USE_SYSTEM
1903    from .vendor.pip_shims.shims import PipError
1904
1905    requirements_directory = vistir.path.create_tracked_tempdir(
1906        suffix="-requirements", prefix="pipenv-"
1907    )
1908    warnings.filterwarnings("default", category=vistir.compat.ResourceWarning)
1909    if selective_upgrade:
1910        keep_outdated = True
1911    packages = packages if packages else []
1912    editable_packages = editable_packages if editable_packages else []
1913    package_args = [p for p in packages if p] + [p for p in editable_packages if p]
1914    skip_requirements = False
1915    # Don't search for requirements.txt files if the user provides one
1916    if requirementstxt or package_args or project.pipfile_exists:
1917        skip_requirements = True
1918    concurrent = not sequential
1919    # Ensure that virtualenv is available and pipfile are available
1920    ensure_project(
1921        three=three,
1922        python=python,
1923        system=system,
1924        warn=True,
1925        deploy=deploy,
1926        skip_requirements=skip_requirements,
1927        pypi_mirror=pypi_mirror,
1928        site_packages=site_packages,
1929    )
1930    # Don't attempt to install develop and default packages if Pipfile is missing
1931    if not project.pipfile_exists and not (package_args or dev) and not code:
1932        if not (ignore_pipfile or deploy):
1933            raise exceptions.PipfileNotFound(project.path_to("Pipfile"))
1934        elif ((skip_lock and deploy) or ignore_pipfile) and not project.lockfile_exists:
1935            raise exceptions.LockfileNotFound(project.path_to("Pipfile.lock"))
1936    # Load the --pre settings from the Pipfile.
1937    if not pre:
1938        pre = project.settings.get("allow_prereleases")
1939    if not keep_outdated:
1940        keep_outdated = project.settings.get("keep_outdated")
1941    remote = requirementstxt and is_valid_url(requirementstxt)
1942    # Warn and exit if --system is used without a pipfile.
1943    if (system and package_args) and not (PIPENV_VIRTUALENV):
1944        raise exceptions.SystemUsageError
1945    # Automatically use an activated virtualenv.
1946    if PIPENV_USE_SYSTEM:
1947        system = True
1948    if system:
1949        os.environ["PIPENV_USE_SYSTEM"] = "1"
1950    # Check if the file is remote or not
1951    if remote:
1952        click.echo(
1953            crayons.normal(
1954                fix_utf8("Remote requirements file provided! Downloading..."), bold=True
1955            ),
1956            err=True,
1957        )
1958        fd = vistir.path.create_tracked_tempfile(
1959            prefix="pipenv-", suffix="-requirement.txt", dir=requirements_directory
1960        )
1961        temp_reqs = fd.name
1962        requirements_url = requirementstxt
1963        # Download requirements file
1964        try:
1965            download_file(requirements_url, temp_reqs)
1966        except IOError:
1967            fd.close()
1968            os.unlink(temp_reqs)
1969            click.echo(
1970                crayons.red(
1971                    u"Unable to find requirements file at {0}.".format(
1972                        crayons.normal(requirements_url)
1973                    )
1974                ),
1975                err=True,
1976            )
1977            sys.exit(1)
1978        finally:
1979            fd.close()
1980        # Replace the url with the temporary requirements file
1981        requirementstxt = temp_reqs
1982        remote = True
1983    if requirementstxt:
1984        error, traceback = None, None
1985        click.echo(
1986            crayons.normal(
1987                fix_utf8("Requirements file provided! Importing into Pipfile..."), bold=True
1988            ),
1989            err=True,
1990        )
1991        try:
1992            import_requirements(r=project.path_to(requirementstxt), dev=dev)
1993        except (UnicodeDecodeError, PipError) as e:
1994            # Don't print the temp file path if remote since it will be deleted.
1995            req_path = requirements_url if remote else project.path_to(requirementstxt)
1996            error = (
1997                u"Unexpected syntax in {0}. Are you sure this is a "
1998                "requirements.txt style file?".format(req_path)
1999            )
2000            traceback = e
2001        except AssertionError as e:
2002            error = (
2003                u"Requirements file doesn't appear to exist. Please ensure the file exists in your "
2004                "project directory or you provided the correct path."
2005            )
2006            traceback = e
2007        finally:
2008            # If requirements file was provided by remote url delete the temporary file
2009            if remote:
2010                fd.close()  # Close for windows to allow file cleanup.
2011                os.remove(temp_reqs)
2012            if error and traceback:
2013                click.echo(crayons.red(error))
2014                click.echo(crayons.yellow(str(traceback)), err=True)
2015                sys.exit(1)
2016    if code:
2017        click.echo(
2018            crayons.normal(fix_utf8("Discovering imports from local codebase..."), bold=True)
2019        )
2020        for req in import_from_code(code):
2021            click.echo("  Found {0}!".format(crayons.green(req)))
2022            project.add_package_to_pipfile(req)
2023    # Allow more than one package to be provided.
2024    package_args = [p for p in packages] + [
2025        "-e {0}".format(pkg) for pkg in editable_packages
2026    ]
2027    # Support for --selective-upgrade.
2028    # We should do this part first to make sure that we actually do selectively upgrade
2029    # the items specified
2030    if selective_upgrade:
2031        from .vendor.requirementslib.models.requirements import Requirement
2032
2033        for i, package in enumerate(package_args[:]):
2034            section = project.packages if not dev else project.dev_packages
2035            package = Requirement.from_line(package)
2036            package__name, package__val = package.pipfile_entry
2037            try:
2038                if not is_star(section[package__name]) and is_star(package__val):
2039                    # Support for VCS dependencies.
2040                    package_args[i] = convert_deps_to_pip(
2041                        {package__name: section[package__name]}, project=project, r=False
2042                    )[0]
2043            except KeyError:
2044                pass
2045    # Install all dependencies, if none was provided.
2046    # This basically ensures that we have a pipfile and lockfile, then it locks and
2047    # installs from the lockfile
2048    if not packages and not editable_packages:
2049        # Update project settings with pre preference.
2050        if pre:
2051            project.update_settings({"allow_prereleases": pre})
2052        do_init(
2053            dev=dev,
2054            allow_global=system,
2055            ignore_pipfile=ignore_pipfile,
2056            system=system,
2057            skip_lock=skip_lock,
2058            concurrent=concurrent,
2059            deploy=deploy,
2060            pre=pre,
2061            requirements_dir=requirements_directory,
2062            pypi_mirror=pypi_mirror,
2063            keep_outdated=keep_outdated
2064        )
2065
2066    # This is for if the user passed in dependencies, then we want to make sure we
2067    else:
2068        from .vendor.requirementslib.models.requirements import Requirement
2069
2070        # make a tuple of (display_name, entry)
2071        pkg_list = packages + ['-e {0}'.format(pkg) for pkg in editable_packages]
2072        if not system and not project.virtualenv_exists:
2073            do_init(
2074                dev=dev,
2075                system=system,
2076                allow_global=system,
2077                concurrent=concurrent,
2078                keep_outdated=keep_outdated,
2079                requirements_dir=requirements_directory,
2080                deploy=deploy,
2081                pypi_mirror=pypi_mirror,
2082                skip_lock=skip_lock,
2083            )
2084        pip_shims_module = os.environ.pop("PIP_SHIMS_BASE_MODULE", None)
2085        for pkg_line in pkg_list:
2086            click.echo(
2087                crayons.normal(
2088                    fix_utf8("Installing {0}...".format(crayons.green(pkg_line, bold=True))),
2089                    bold=True,
2090                )
2091            )
2092            # pip install:
2093            with vistir.contextmanagers.temp_environ(), create_spinner("Installing...") as sp:
2094                if not system:
2095                    os.environ["PIP_USER"] = vistir.compat.fs_str("0")
2096                    if "PYTHONHOME" in os.environ:
2097                        del os.environ["PYTHONHOME"]
2098                sp.text = "Resolving {0}...".format(pkg_line)
2099                try:
2100                    pkg_requirement = Requirement.from_line(pkg_line)
2101                except ValueError as e:
2102                    sp.write_err(vistir.compat.fs_str("{0}: {1}".format(crayons.red("WARNING"), e)))
2103                    sp.red.fail(environments.PIPENV_SPINNER_FAIL_TEXT.format("Installation Failed"))
2104                    sys.exit(1)
2105                if index_url:
2106                    pkg_requirement.index = index_url
2107                no_deps = False
2108                sp.text = "Installing..."
2109                try:
2110                    sp.text = "Installing {0}...".format(pkg_requirement.name)
2111                    if environments.is_verbose():
2112                        sp.hide_and_write("Installing package: {0}".format(pkg_requirement.as_line(include_hashes=False)))
2113                    c = pip_install(
2114                        pkg_requirement,
2115                        ignore_hashes=True,
2116                        allow_global=system,
2117                        selective_upgrade=selective_upgrade,
2118                        no_deps=no_deps,
2119                        pre=pre,
2120                        requirements_dir=requirements_directory,
2121                        index=index_url,
2122                        extra_indexes=extra_index_url,
2123                        pypi_mirror=pypi_mirror,
2124                    )
2125                    if not c.ok:
2126                        sp.write_err(
2127                            u"{0} An error occurred while installing {1}!".format(
2128                                crayons.red(u"Error: ", bold=True), crayons.green(pkg_line)
2129                            ),
2130                        )
2131                        sp.write_err(
2132                            vistir.compat.fs_str(u"Error text: {0}".format(c.out))
2133                        )
2134                        sp.write_err(crayons.cyan(vistir.compat.fs_str(format_pip_error(c.err))))
2135                        if environments.is_verbose():
2136                            sp.write_err(crayons.cyan(vistir.compat.fs_str(format_pip_output(c.out))))
2137                        if "setup.py egg_info" in c.err:
2138                            sp.write_err(vistir.compat.fs_str(
2139                                "This is likely caused by a bug in {0}. "
2140                                "Report this to its maintainers.".format(
2141                                    crayons.green(pkg_requirement.name)
2142                                )
2143                            ))
2144                        sp.red.fail(environments.PIPENV_SPINNER_FAIL_TEXT.format("Installation Failed"))
2145                        sys.exit(1)
2146                except (ValueError, RuntimeError) as e:
2147                    sp.write_err(vistir.compat.fs_str(
2148                        "{0}: {1}".format(crayons.red("WARNING"), e),
2149                    ))
2150                    sp.red.fail(environments.PIPENV_SPINNER_FAIL_TEXT.format(
2151                        "Installation Failed",
2152                    ))
2153                    sys.exit(1)
2154                # Warn if --editable wasn't passed.
2155                if pkg_requirement.is_vcs and not pkg_requirement.editable and not PIPENV_RESOLVE_VCS:
2156                    sp.write_err(
2157                        "{0}: You installed a VCS dependency in non-editable mode. "
2158                        "This will work fine, but sub-dependencies will not be resolved by {1}."
2159                        "\n  To enable this sub-dependency functionality, specify that this dependency is editable."
2160                        "".format(
2161                            crayons.red("Warning", bold=True),
2162                            crayons.yellow("$ pipenv lock"),
2163                        )
2164                    )
2165                sp.write(vistir.compat.fs_str(
2166                    u"{0} {1} {2} {3}{4}".format(
2167                        crayons.normal(u"Adding", bold=True),
2168                        crayons.green(u"{0}".format(pkg_requirement.name), bold=True),
2169                        crayons.normal(u"to Pipfile's", bold=True),
2170                        crayons.yellow(u"[dev-packages]" if dev else u"[packages]", bold=True),
2171                        crayons.normal(fix_utf8("..."), bold=True),
2172                    )
2173                ))
2174                # Add the package to the Pipfile.
2175                try:
2176                    project.add_package_to_pipfile(pkg_requirement, dev)
2177                except ValueError:
2178                    import traceback
2179                    sp.write_err(
2180                        "{0} {1}".format(
2181                            crayons.red("Error:", bold=True), traceback.format_exc()
2182                        )
2183                    )
2184                    sp.fail(environments.PIPENV_SPINNER_FAIL_TEXT.format(
2185                        "Failed adding package to Pipfile"
2186                    ))
2187                sp.ok(environments.PIPENV_SPINNER_OK_TEXT.format("Installation Succeeded"))
2188            # Update project settings with pre preference.
2189            if pre:
2190                project.update_settings({"allow_prereleases": pre})
2191        if pip_shims_module:
2192            os.environ["PIP_SHIMS_BASE_MODULE"] = pip_shims_module
2193        do_init(
2194            dev=dev,
2195            system=system,
2196            allow_global=system,
2197            concurrent=concurrent,
2198            keep_outdated=keep_outdated,
2199            requirements_dir=requirements_directory,
2200            deploy=deploy,
2201            pypi_mirror=pypi_mirror,
2202            skip_lock=skip_lock,
2203        )
2204    sys.exit(0)
2205
2206
2207def do_uninstall(
2208    packages=False,
2209    editable_packages=False,
2210    three=None,
2211    python=False,
2212    system=False,
2213    lock=False,
2214    all_dev=False,
2215    all=False,
2216    keep_outdated=False,
2217    pypi_mirror=None,
2218    ctx=None
2219):
2220    from .environments import PIPENV_USE_SYSTEM
2221    from .vendor.requirementslib.models.requirements import Requirement
2222    from .vendor.packaging.utils import canonicalize_name
2223
2224    # Automatically use an activated virtualenv.
2225    if PIPENV_USE_SYSTEM:
2226        system = True
2227    # Ensure that virtualenv is available.
2228    # TODO: We probably shouldn't ensure a project exists if the outcome will be to just
2229    # install things in order to remove them... maybe tell the user to install first?
2230    ensure_project(three=three, python=python, pypi_mirror=pypi_mirror)
2231    # Un-install all dependencies, if --all was provided.
2232    if not any([packages, editable_packages, all_dev, all]):
2233        raise exceptions.PipenvUsageError("No package provided!", ctx=ctx)
2234    editable_pkgs = [
2235        Requirement.from_line("-e {0}".format(p)).name for p in editable_packages if p
2236    ]
2237    packages += editable_pkgs
2238    package_names = set(p for p in packages if p)
2239    package_map = {
2240        canonicalize_name(p): p for p in packages if p
2241    }
2242    installed_package_names = project.installed_package_names
2243    # Intelligently detect if --dev should be used or not.
2244    lockfile_packages = set()
2245    if project.lockfile_exists:
2246        project_pkg_names = project.lockfile_package_names
2247    else:
2248        project_pkg_names = project.pipfile_package_names
2249    pipfile_remove = True
2250    # Uninstall [dev-packages], if --dev was provided.
2251    if all_dev:
2252        if "dev-packages" not in project.parsed_pipfile and not project_pkg_names["dev"]:
2253            click.echo(
2254                crayons.normal(
2255                    "No {0} to uninstall.".format(crayons.yellow("[dev-packages]")),
2256                    bold=True,
2257                )
2258            )
2259            return
2260        click.echo(
2261            crayons.normal(
2262                fix_utf8("Un-installing {0}...".format(crayons.yellow("[dev-packages]"))), bold=True
2263            )
2264        )
2265        package_names = set(project_pkg_names["dev"]) - set(project_pkg_names["default"])
2266
2267    # Remove known "bad packages" from the list.
2268    bad_pkgs = get_canonical_names(BAD_PACKAGES)
2269    ignored_packages = bad_pkgs & set(list(package_map.keys()))
2270    for ignored_pkg in ignored_packages:
2271        if environments.is_verbose():
2272            click.echo("Ignoring {0}.".format(ignored_pkg), err=True)
2273        package_names.discard(package_map[ignored_pkg])
2274
2275    used_packages = project_pkg_names["combined"] & installed_package_names
2276    failure = False
2277    if all:
2278        click.echo(
2279            crayons.normal(
2280                fix_utf8("Un-installing all {0} and {1}...".format(
2281                    crayons.yellow("[dev-packages]"),
2282                    crayons.yellow("[packages]"),
2283                )), bold=True
2284            )
2285        )
2286        do_purge(bare=False, allow_global=system)
2287        sys.exit(0)
2288
2289    selected_pkg_map = {
2290        canonicalize_name(p): p for p in package_names
2291    }
2292    packages_to_remove = [
2293        p for normalized, p in selected_pkg_map.items()
2294        if normalized in (used_packages - bad_pkgs)
2295    ]
2296    pip_path = None
2297    for normalized, package_name in selected_pkg_map.items():
2298        click.echo(
2299            crayons.normal(
2300                fix_utf8("Uninstalling {0}...".format(crayons.green(package_name))), bold=True
2301            )
2302        )
2303        # Uninstall the package.
2304        if package_name in packages_to_remove:
2305            with project.environment.activated():
2306                if pip_path is None:
2307                    pip_path = which_pip(allow_global=system)
2308                cmd = [pip_path, "uninstall", package_name, "-y"]
2309                c = run_command(cmd)
2310                click.echo(crayons.cyan(c.out))
2311                if c.return_code != 0:
2312                    failure = True
2313        if not failure and pipfile_remove:
2314            in_packages = project.get_package_name_in_pipfile(package_name, dev=False)
2315            in_dev_packages = project.get_package_name_in_pipfile(
2316                package_name, dev=True
2317            )
2318            if normalized in lockfile_packages:
2319                click.echo("{0} {1} {2} {3}".format(
2320                    crayons.cyan("Removing"),
2321                    crayons.green(package_name),
2322                    crayons.cyan("from"),
2323                    crayons.white(fix_utf8("Pipfile.lock...")))
2324                )
2325                lockfile = project.get_or_create_lockfile()
2326                if normalized in lockfile.default:
2327                    del lockfile.default[normalized]
2328                if normalized in lockfile.develop:
2329                    del lockfile.develop[normalized]
2330                lockfile.write()
2331            if not (in_dev_packages or in_packages):
2332                if normalized in lockfile_packages:
2333                    continue
2334                click.echo(
2335                    "No package {0} to remove from Pipfile.".format(
2336                        crayons.green(package_name)
2337                    )
2338                )
2339                continue
2340
2341            click.echo(
2342                fix_utf8("Removing {0} from Pipfile...".format(crayons.green(package_name)))
2343            )
2344            # Remove package from both packages and dev-packages.
2345            if in_dev_packages:
2346                project.remove_package_from_pipfile(package_name, dev=True)
2347            if in_packages:
2348                project.remove_package_from_pipfile(package_name, dev=False)
2349    if lock:
2350        do_lock(system=system, keep_outdated=keep_outdated, pypi_mirror=pypi_mirror)
2351    sys.exit(int(failure))
2352
2353
2354def do_shell(three=None, python=False, fancy=False, shell_args=None, pypi_mirror=None):
2355    # Ensure that virtualenv is available.
2356    ensure_project(
2357        three=three, python=python, validate=False, pypi_mirror=pypi_mirror,
2358    )
2359
2360    # Support shell compatibility mode.
2361    if PIPENV_SHELL_FANCY:
2362        fancy = True
2363
2364    from .shells import choose_shell
2365
2366    shell = choose_shell()
2367    click.echo(fix_utf8("Launching subshell in virtual environment..."), err=True)
2368
2369    fork_args = (
2370        project.virtualenv_location,
2371        project.project_directory,
2372        shell_args,
2373    )
2374
2375    # Set an environment variable, so we know we're in the environment.
2376    # Only set PIPENV_ACTIVE after finishing reading virtualenv_location
2377    # otherwise its value will be changed
2378    os.environ["PIPENV_ACTIVE"] = vistir.misc.fs_str("1")
2379
2380    os.environ.pop("PIP_SHIMS_BASE_MODULE", None)
2381
2382    if fancy:
2383        shell.fork(*fork_args)
2384        return
2385
2386    try:
2387        shell.fork_compat(*fork_args)
2388    except (AttributeError, ImportError):
2389        click.echo(fix_utf8(
2390            "Compatibility mode not supported. "
2391            "Trying to continue as well-configured shell..."),
2392            err=True,
2393        )
2394        shell.fork(*fork_args)
2395
2396
2397def _inline_activate_virtualenv():
2398    try:
2399        activate_this = which("activate_this.py")
2400        if not activate_this or not os.path.exists(activate_this):
2401            raise exceptions.VirtualenvActivationException()
2402        with open(activate_this) as f:
2403            code = compile(f.read(), activate_this, "exec")
2404            exec(code, dict(__file__=activate_this))
2405    # Catch all errors, just in case.
2406    except Exception:
2407        click.echo(
2408            u"{0}: There was an unexpected error while activating your "
2409            u"virtualenv. Continuing anyway...".format(
2410                crayons.red("Warning", bold=True)
2411            ),
2412            err=True,
2413        )
2414
2415
2416def _inline_activate_venv():
2417    """Built-in venv doesn't have activate_this.py, but doesn't need it anyway.
2418
2419    As long as we find the correct executable, built-in venv sets up the
2420    environment automatically.
2421
2422    See: https://bugs.python.org/issue21496#msg218455
2423    """
2424    components = []
2425    for name in ("bin", "Scripts"):
2426        bindir = os.path.join(project.virtualenv_location, name)
2427        if os.path.exists(bindir):
2428            components.append(bindir)
2429    if "PATH" in os.environ:
2430        components.append(os.environ["PATH"])
2431    os.environ["PATH"] = os.pathsep.join(components)
2432
2433
2434def inline_activate_virtual_environment():
2435    root = project.virtualenv_location
2436    if os.path.exists(os.path.join(root, "pyvenv.cfg")):
2437        _inline_activate_venv()
2438    else:
2439        _inline_activate_virtualenv()
2440    if "VIRTUAL_ENV" not in os.environ:
2441        os.environ["VIRTUAL_ENV"] = vistir.misc.fs_str(root)
2442
2443
2444def _launch_windows_subprocess(script):
2445    import subprocess
2446
2447    command = system_which(script.command)
2448    options = {"universal_newlines": True}
2449
2450    # Command not found, maybe this is a shell built-in?
2451    if not command:
2452        return subprocess.Popen(script.cmdify(), shell=True, **options)
2453
2454    # Try to use CreateProcess directly if possible. Specifically catch
2455    # Windows error 193 "Command is not a valid Win32 application" to handle
2456    # a "command" that is non-executable. See pypa/pipenv#2727.
2457    try:
2458        return subprocess.Popen([command] + script.args, **options)
2459    except WindowsError as e:
2460        if e.winerror != 193:
2461            raise
2462
2463    # Try shell mode to use Windows's file association for file launch.
2464    return subprocess.Popen(script.cmdify(), shell=True, **options)
2465
2466
2467def do_run_nt(script):
2468    p = _launch_windows_subprocess(script)
2469    p.communicate()
2470    sys.exit(p.returncode)
2471
2472
2473def do_run_posix(script, command):
2474    command_path = system_which(script.command)
2475    if not command_path:
2476        if project.has_script(command):
2477            click.echo(
2478                "{0}: the command {1} (from {2}) could not be found within {3}."
2479                "".format(
2480                    crayons.red("Error", bold=True),
2481                    crayons.yellow(script.command),
2482                    crayons.normal(command, bold=True),
2483                    crayons.normal("PATH", bold=True),
2484                ),
2485                err=True,
2486            )
2487        else:
2488            click.echo(
2489                "{0}: the command {1} could not be found within {2} or Pipfile's {3}."
2490                "".format(
2491                    crayons.red("Error", bold=True),
2492                    crayons.yellow(command),
2493                    crayons.normal("PATH", bold=True),
2494                    crayons.normal("[scripts]", bold=True),
2495                ),
2496                err=True,
2497            )
2498        sys.exit(1)
2499    os.execl(
2500        command_path, command_path, *[os.path.expandvars(arg) for arg in script.args]
2501    )
2502
2503
2504def do_run(command, args, three=None, python=False, pypi_mirror=None):
2505    """Attempt to run command either pulling from project or interpreting as executable.
2506
2507    Args are appended to the command in [scripts] section of project if found.
2508    """
2509    from .cmdparse import ScriptEmptyError
2510
2511    # Ensure that virtualenv is available.
2512    ensure_project(
2513        three=three, python=python, validate=False, pypi_mirror=pypi_mirror,
2514    )
2515
2516    load_dot_env()
2517
2518    previous_pip_shims_module = os.environ.pop("PIP_SHIMS_BASE_MODULE", None)
2519
2520    # Activate virtualenv under the current interpreter's environment
2521    inline_activate_virtual_environment()
2522
2523    # Set an environment variable, so we know we're in the environment.
2524    # Only set PIPENV_ACTIVE after finishing reading virtualenv_location
2525    # such as in inline_activate_virtual_environment
2526    # otherwise its value will be changed
2527    previous_pipenv_active_value = os.environ.get("PIPENV_ACTIVE")
2528    os.environ["PIPENV_ACTIVE"] = vistir.misc.fs_str("1")
2529
2530    os.environ.pop("PIP_SHIMS_BASE_MODULE", None)
2531
2532    try:
2533        script = project.build_script(command, args)
2534        cmd_string = ' '.join([script.command] + script.args)
2535        if environments.is_verbose():
2536            click.echo(crayons.normal("$ {0}".format(cmd_string)), err=True)
2537    except ScriptEmptyError:
2538        click.echo("Can't run script {0!r}-it's empty?", err=True)
2539    run_args = [script]
2540    run_kwargs = {}
2541    if os.name == "nt":
2542        run_fn = do_run_nt
2543    else:
2544        run_fn = do_run_posix
2545        run_kwargs = {"command": command}
2546    try:
2547        run_fn(*run_args, **run_kwargs)
2548    finally:
2549        os.environ.pop("PIPENV_ACTIVE", None)
2550        if previous_pipenv_active_value is not None:
2551            os.environ["PIPENV_ACTIVE"] = previous_pipenv_active_value
2552        if previous_pip_shims_module is not None:
2553            os.environ["PIP_SHIMS_BASE_MODULE"] = previous_pip_shims_module
2554
2555
2556def do_check(
2557    three=None,
2558    python=False,
2559    system=False,
2560    unused=False,
2561    db=False,
2562    ignore=None,
2563    output="default",
2564    key=None,
2565    quiet=False,
2566    args=None,
2567    pypi_mirror=None
2568):
2569    from pipenv.vendor.vistir.compat import JSONDecodeError
2570    from pipenv.vendor.first import first
2571
2572    if not system:
2573        # Ensure that virtualenv is available.
2574        ensure_project(
2575            three=three,
2576            python=python,
2577            validate=False,
2578            warn=False,
2579            pypi_mirror=pypi_mirror,
2580        )
2581    if not args:
2582        args = []
2583    if unused:
2584        deps_required = [k.lower() for k in project.packages.keys()]
2585        deps_needed = [k.lower() for k in import_from_code(unused)]
2586        for dep in deps_needed:
2587            try:
2588                deps_required.remove(dep)
2589            except ValueError:
2590                pass
2591        if deps_required:
2592            if not quiet and not environments.is_quiet():
2593                click.echo(
2594                    crayons.normal(
2595                        "The following dependencies appear unused, and may be safe for removal:"
2596                    )
2597                )
2598                for dep in deps_required:
2599                    click.echo("  - {0}".format(crayons.green(dep)))
2600                sys.exit(1)
2601        else:
2602            sys.exit(0)
2603    if not quiet and not environments.is_quiet():
2604        click.echo(crayons.normal(decode_for_output("Checking PEP 508 requirements..."), bold=True))
2605    pep508checker_path = pep508checker.__file__.rstrip("cdo")
2606    safety_path = os.path.join(
2607        os.path.dirname(os.path.abspath(__file__)), "patched", "safety"
2608    )
2609    if not system:
2610        python = which("python")
2611    else:
2612        python = first(system_which(p) for p in ("python", "python3", "python2"))
2613    if not python:
2614        click.echo(crayons.red("The Python interpreter can't be found."), err=True)
2615        sys.exit(1)
2616    _cmd = [vistir.compat.Path(python).as_posix()]
2617    # Run the PEP 508 checker in the virtualenv.
2618    cmd = _cmd + [vistir.compat.Path(pep508checker_path).as_posix()]
2619    c = run_command(cmd)
2620    if c.return_code is not None:
2621        try:
2622            results = simplejson.loads(c.out.strip())
2623        except JSONDecodeError:
2624            click.echo("{0}\n{1}\n{2}".format(
2625                crayons.white(decode_for_output("Failed parsing pep508 results: "), bold=True),
2626                c.out.strip(),
2627                c.err.strip()
2628            ))
2629            sys.exit(1)
2630    # Load the pipfile.
2631    p = pipfile.Pipfile.load(project.pipfile_location)
2632    failed = False
2633    # Assert each specified requirement.
2634    for marker, specifier in p.data["_meta"]["requires"].items():
2635        if marker in results:
2636            try:
2637                assert results[marker] == specifier
2638            except AssertionError:
2639                failed = True
2640                click.echo(
2641                    "Specifier {0} does not match {1} ({2})."
2642                    "".format(
2643                        crayons.green(marker),
2644                        crayons.cyan(specifier),
2645                        crayons.yellow(results[marker]),
2646                    ),
2647                    err=True,
2648                )
2649    if failed:
2650        click.echo(crayons.red("Failed!"), err=True)
2651        sys.exit(1)
2652    else:
2653        if not quiet and not environments.is_quiet():
2654            click.echo(crayons.green("Passed!"))
2655    if not quiet and not environments.is_quiet():
2656        click.echo(crayons.normal(
2657            decode_for_output("Checking installed package safety..."), bold=True)
2658        )
2659    if ignore:
2660        if not isinstance(ignore, (tuple, list)):
2661            ignore = [ignore]
2662        ignored = [["--ignore", cve] for cve in ignore]
2663        if not quiet and not environments.is_quiet():
2664            click.echo(
2665                crayons.normal(
2666                    "Notice: Ignoring CVE(s) {0}".format(crayons.yellow(", ".join(ignore)))
2667                ),
2668                err=True,
2669            )
2670    else:
2671        ignored = []
2672
2673    switch = output
2674    if output == "default":
2675        switch = "json"
2676
2677    cmd = _cmd + [safety_path, "check", "--{0}".format(switch)]
2678    if db:
2679        if not quiet and not environments.is_quiet():
2680            click.echo(crayons.normal("Using local database {}".format(db)))
2681        cmd.append("--db={0}".format(db))
2682    elif key or PIPENV_PYUP_API_KEY:
2683        cmd = cmd + ["--key={0}".format(key or PIPENV_PYUP_API_KEY)]
2684    if ignored:
2685        for cve in ignored:
2686            cmd += cve
2687    c = run_command(cmd, catch_exceptions=False)
2688    if output == "default":
2689        try:
2690            results = simplejson.loads(c.out)
2691        except (ValueError, JSONDecodeError):
2692            raise exceptions.JSONParseError(c.out, c.err)
2693        except Exception:
2694            raise exceptions.PipenvCmdError(c.cmd, c.out, c.err, c.return_code)
2695        for (package, resolved, installed, description, vuln) in results:
2696            click.echo(
2697                "{0}: {1} {2} resolved ({3} installed)!".format(
2698                    crayons.normal(vuln, bold=True),
2699                    crayons.green(package),
2700                    crayons.yellow(resolved, bold=False),
2701                    crayons.yellow(installed, bold=True),
2702                )
2703            )
2704            click.echo("{0}".format(description))
2705            click.echo()
2706        if c.ok:
2707            click.echo(crayons.green("All good!"))
2708            sys.exit(0)
2709        else:
2710            sys.exit(1)
2711    else:
2712        click.echo(c.out)
2713        sys.exit(c.return_code)
2714
2715
2716def do_graph(bare=False, json=False, json_tree=False, reverse=False):
2717    from pipenv.vendor.vistir.compat import JSONDecodeError
2718    import pipdeptree
2719    pipdeptree_path = pipdeptree.__file__.rstrip("cdo")
2720    try:
2721        python_path = which("python")
2722    except AttributeError:
2723        click.echo(
2724            u"{0}: {1}".format(
2725                crayons.red("Warning", bold=True),
2726                u"Unable to display currently-installed dependency graph information here. "
2727                u"Please run within a Pipenv project.",
2728            ),
2729            err=True,
2730        )
2731        sys.exit(1)
2732    except RuntimeError:
2733        pass
2734    else:
2735        if not os.name == 'nt':    # bugfix #4388
2736            python_path = vistir.compat.Path(python_path).as_posix()
2737            pipdeptree_path = vistir.compat.Path(pipdeptree_path).as_posix()
2738
2739    if reverse and json:
2740        click.echo(
2741            u"{0}: {1}".format(
2742                crayons.red("Warning", bold=True),
2743                u"Using both --reverse and --json together is not supported. "
2744                u"Please select one of the two options.",
2745            ),
2746            err=True,
2747        )
2748        sys.exit(1)
2749    if reverse and json_tree:
2750        click.echo(
2751            u"{0}: {1}".format(
2752                crayons.red("Warning", bold=True),
2753                u"Using both --reverse and --json-tree together is not supported. "
2754                u"Please select one of the two options.",
2755            ),
2756            err=True,
2757        )
2758        sys.exit(1)
2759    if json and json_tree:
2760        click.echo(
2761            u"{0}: {1}".format(
2762                crayons.red("Warning", bold=True),
2763                u"Using both --json and --json-tree together is not supported. "
2764                u"Please select one of the two options.",
2765            ),
2766            err=True,
2767        )
2768        sys.exit(1)
2769    flag = ""
2770    if json:
2771        flag = "--json"
2772    if json_tree:
2773        flag = "--json-tree"
2774    if reverse:
2775        flag = "--reverse"
2776    if not project.virtualenv_exists:
2777        click.echo(
2778            u"{0}: No virtualenv has been created for this project yet! Consider "
2779            u"running {1} first to automatically generate one for you or see "
2780            u"{2} for further instructions.".format(
2781                crayons.red("Warning", bold=True),
2782                crayons.green("`pipenv install`"),
2783                crayons.green("`pipenv install --help`"),
2784            ),
2785            err=True,
2786        )
2787        sys.exit(1)
2788    cmd_args = [python_path, pipdeptree_path, flag, "-l"]
2789    c = run_command(cmd_args)
2790    # Run dep-tree.
2791    if not bare:
2792        if json:
2793            data = []
2794            try:
2795                parsed = simplejson.loads(c.out.strip())
2796            except JSONDecodeError:
2797                raise exceptions.JSONParseError(c.out, c.err)
2798            else:
2799                for d in parsed:
2800                    if d["package"]["key"] not in BAD_PACKAGES:
2801                        data.append(d)
2802            click.echo(simplejson.dumps(data, indent=4))
2803            sys.exit(0)
2804        elif json_tree:
2805
2806            def traverse(obj):
2807                if isinstance(obj, list):
2808                    return [
2809                        traverse(package)
2810                        for package in obj
2811                        if package["key"] not in BAD_PACKAGES
2812                    ]
2813                else:
2814                    obj["dependencies"] = traverse(obj["dependencies"])
2815                    return obj
2816
2817            try:
2818                parsed = simplejson.loads(c.out.strip())
2819            except JSONDecodeError:
2820                raise exceptions.JSONParseError(c.out, c.err)
2821            else:
2822                data = traverse(parsed)
2823                click.echo(simplejson.dumps(data, indent=4))
2824                sys.exit(0)
2825        else:
2826            for line in c.out.strip().split("\n"):
2827                # Ignore bad packages as top level.
2828                # TODO: This should probably be a "==" in + line.partition
2829                if line.split("==")[0] in BAD_PACKAGES and not reverse:
2830                    continue
2831
2832                # Bold top-level packages.
2833                if not line.startswith(" "):
2834                    click.echo(crayons.normal(line, bold=True))
2835                # Echo the rest.
2836                else:
2837                    click.echo(crayons.normal(line, bold=False))
2838    else:
2839        click.echo(c.out)
2840    if c.return_code != 0:
2841        click.echo(
2842            "{0} {1}".format(
2843                crayons.red("ERROR: ", bold=True),
2844                crayons.white("{0}".format(c.err, bold=True)),
2845            ),
2846            err=True,
2847        )
2848    # Return its return code.
2849    sys.exit(c.return_code)
2850
2851
2852def do_sync(
2853    ctx,
2854    dev=False,
2855    three=None,
2856    python=None,
2857    bare=False,
2858    dont_upgrade=False,
2859    user=False,
2860    clear=False,
2861    unused=False,
2862    sequential=False,
2863    pypi_mirror=None,
2864    system=False,
2865    deploy=False,
2866):
2867    # The lock file needs to exist because sync won't write to it.
2868    if not project.lockfile_exists:
2869        raise exceptions.LockfileNotFound("Pipfile.lock")
2870
2871    # Ensure that virtualenv is available if not system.
2872    ensure_project(
2873        three=three,
2874        python=python,
2875        validate=False,
2876        deploy=deploy,
2877        pypi_mirror=pypi_mirror,
2878    )
2879
2880    # Install everything.
2881    requirements_dir = vistir.path.create_tracked_tempdir(
2882        suffix="-requirements", prefix="pipenv-"
2883    )
2884    do_init(
2885        dev=dev,
2886        allow_global=system,
2887        concurrent=(not sequential),
2888        requirements_dir=requirements_dir,
2889        ignore_pipfile=True,  # Don't check if Pipfile and lock match.
2890        pypi_mirror=pypi_mirror,
2891        deploy=deploy,
2892        system=system,
2893    )
2894    if not bare:
2895        click.echo(crayons.green("All dependencies are now up-to-date!"))
2896
2897
2898def do_clean(
2899    ctx, three=None, python=None, dry_run=False, bare=False, pypi_mirror=None,
2900    system=False
2901):
2902    # Ensure that virtualenv is available.
2903    from packaging.utils import canonicalize_name
2904    ensure_project(three=three, python=python, validate=False, pypi_mirror=pypi_mirror)
2905    ensure_lockfile(pypi_mirror=pypi_mirror)
2906    # Make sure that the virtualenv's site packages are configured correctly
2907    # otherwise we may end up removing from the global site packages directory
2908    installed_package_names = project.installed_package_names.copy()
2909    # Remove known "bad packages" from the list.
2910    for bad_package in BAD_PACKAGES:
2911        if canonicalize_name(bad_package) in installed_package_names:
2912            if environments.is_verbose():
2913                click.echo("Ignoring {0}.".format(bad_package), err=True)
2914            installed_package_names.remove(canonicalize_name(bad_package))
2915    # Intelligently detect if --dev should be used or not.
2916    locked_packages = {
2917        canonicalize_name(pkg) for pkg in project.lockfile_package_names["combined"]
2918    }
2919    for used_package in locked_packages:
2920        if used_package in installed_package_names:
2921            installed_package_names.remove(used_package)
2922    failure = False
2923    cmd = [which_pip(allow_global=system), "uninstall", "-y", "-qq"]
2924    for apparent_bad_package in installed_package_names:
2925        if dry_run and not bare:
2926            click.echo(apparent_bad_package)
2927        else:
2928            if not bare:
2929                click.echo(
2930                    crayons.white(
2931                        fix_utf8("Uninstalling {0}...".format(apparent_bad_package)), bold=True
2932                    )
2933                )
2934            # Uninstall the package.
2935            cmd = [which_pip(), "uninstall", apparent_bad_package, "-y"]
2936            c = run_command(cmd)
2937            if c.return_code != 0:
2938                failure = True
2939    sys.exit(int(failure))
2940