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