diff --git a/pipenv/cli.py b/pipenv/cli.py index 5e7b470b..bb41c103 100644 --- a/pipenv/cli.py +++ b/pipenv/cli.py @@ -145,6 +145,13 @@ def validate_pypi_mirror(ctx, param, value): default=False, help="Enable site-packages for the virtualenv.", ) +@option( + '--pypi-mirror', + default=environments.PIPENV_PYPI_MIRROR, + nargs=1, + callback=validate_pypi_mirror, + help="Specify a PyPI mirror.", +) @version_option( prog_name=crayons.normal('pipenv', bold=True), version=__version__ ) @@ -163,6 +170,7 @@ def cli( envs=False, man=False, completion=False, + pypi_mirror=None, ): if completion: # Handle this ASAP to make shell startup fast. from . import shells @@ -272,7 +280,7 @@ def cli( # --two / --three was passed... if (python or three is not None) or site_packages: ensure_project( - three=three, python=python, warn=True, site_packages=site_packages + three=three, python=python, warn=True, site_packages=site_packages, pypi_mirror=pypi_mirror ) # Check this again before exiting for empty ``pipenv`` command. elif ctx.invoked_subcommand is None: @@ -571,7 +579,7 @@ def lock( from .core import ensure_project, do_init, do_lock # Ensure that virtualenv is available. - ensure_project(three=three, python=python) + ensure_project(three=three, python=python, pypi_mirror=pypi_mirror) if requirements: do_init(dev=dev, requirements=requirements, pypi_mirror=pypi_mirror) do_lock( @@ -608,9 +616,16 @@ def lock( default=False, help="Always spawn a subshell, even if one is already spawned.", ) +@option( + '--pypi-mirror', + default=environments.PIPENV_PYPI_MIRROR, + nargs=1, + callback=validate_pypi_mirror, + help="Specify a PyPI mirror.", +) @argument('shell_args', nargs=-1) def shell( - three=None, python=False, fancy=False, shell_args=None, anyway=False + three=None, python=False, fancy=False, shell_args=None, anyway=False, pypi_mirror=None ): from .core import load_dot_env, do_shell # Prevent user from activating nested environments. @@ -635,7 +650,7 @@ def shell( if os.name == 'nt': fancy = True do_shell( - three=three, python=python, fancy=fancy, shell_args=shell_args + three=three, python=python, fancy=fancy, shell_args=shell_args, pypi_mirror=pypi_mirror ) @@ -663,9 +678,16 @@ def shell( callback=validate_python_path, help="Specify which version of Python virtualenv should use.", ) -def run(command, args, three=None, python=False): +@option( + '--pypi-mirror', + default=environments.PIPENV_PYPI_MIRROR, + nargs=1, + callback=validate_pypi_mirror, + help="Specify a PyPI mirror.", +) +def run(command, args, three=None, python=False, pypi_mirror=None): from .core import do_run - do_run(command=command, args=args, three=three, python=python) + do_run(command=command, args=args, three=three, python=python, pypi_mirror=pypi_mirror) @command( @@ -700,6 +722,13 @@ def run(command, args, three=None, python=False): multiple=True, help="Ignore specified vulnerability during safety checks." ) +@option( + '--pypi-mirror', + default=environments.PIPENV_PYPI_MIRROR, + nargs=1, + callback=validate_pypi_mirror, + help="Specify a PyPI mirror.", +) @argument('args', nargs=-1) def check( three=None, @@ -709,6 +738,7 @@ def check( style=False, ignore=None, args=None, + pypi_mirror=None, ): from .core import do_check do_check( @@ -717,7 +747,8 @@ def check( system=system, unused=unused, ignore=ignore, - args=args + args=args, + pypi_mirror=pypi_mirror ) @@ -819,7 +850,7 @@ def update( project, ) - ensure_project(three=three, python=python, warn=True) + ensure_project(three=three, python=python, warn=True, pypi_mirror=pypi_mirror) if not outdated: outdated = bool(dry_run) if outdated: @@ -894,12 +925,19 @@ def graph(bare=False, json=False, json_tree=False, reverse=False): callback=validate_python_path, help="Specify which version of Python virtualenv should use.", ) +@option( + '--pypi-mirror', + default=environments.PIPENV_PYPI_MIRROR, + nargs=1, + callback=validate_pypi_mirror, + help="Specify a PyPI mirror.", +) @argument('module', nargs=1) -def run_open(module, three=None, python=None): +def run_open(module, three=None, python=None, pypi_mirror=None): from .core import which, ensure_project # Ensure that virtualenv is available. - ensure_project(three=three, python=python, validate=False) + ensure_project(three=three, python=python, validate=False, pypi_mirror=pypi_mirror) c = delegator.run( '{0} -c "import {1}; print({1}.__file__);"'.format( which('python'), module diff --git a/pipenv/core.py b/pipenv/core.py index a7ed3575..494a1efc 100644 --- a/pipenv/core.py +++ b/pipenv/core.py @@ -548,7 +548,7 @@ def ensure_python(three=None, python=None): return path_to_python -def ensure_virtualenv(three=None, python=None, site_packages=False): +def ensure_virtualenv(three=None, python=None, site_packages=False, pypi_mirror=None): """Creates a virtualenv, if one doesn't exist.""" def abort(): @@ -571,7 +571,7 @@ def ensure_virtualenv(three=None, python=None, site_packages=False): ) ) sys.exit(1) - do_create_virtualenv(python=python, site_packages=site_packages) + do_create_virtualenv(python=python, site_packages=site_packages, pypi_mirror=pypi_mirror) except KeyboardInterrupt: # If interrupted, cleanup the virtualenv. cleanup_virtualenv(bare=False) @@ -599,7 +599,7 @@ def ensure_virtualenv(three=None, python=None, site_packages=False): cleanup_virtualenv(bare=True) # Call this function again. ensure_virtualenv( - three=three, python=python, site_packages=site_packages + three=three, python=python, site_packages=site_packages, pypi_mirror=pypi_mirror ) @@ -612,6 +612,7 @@ def ensure_project( site_packages=False, deploy=False, skip_requirements=False, + pypi_mirror=None, ): """Ensures both Pipfile and virtualenv exist for the project.""" # Automatically use an activated virtualenv. @@ -622,7 +623,7 @@ def ensure_project( # Skip virtualenv creation when --system was used. if not system: ensure_virtualenv( - three=three, python=python, site_packages=site_packages + three=three, python=python, site_packages=site_packages, pypi_mirror=pypi_mirror ) if warn: # Warn users if they are using the wrong version of Python. @@ -885,7 +886,7 @@ def convert_three_to_python(three, python): return python -def do_create_virtualenv(python=None, site_packages=False): +def do_create_virtualenv(python=None, site_packages=False, pypi_mirror=None): """Creates a virtualenv.""" click.echo( crayons.normal(u'Creating a virtualenv for this project...', bold=True), @@ -933,7 +934,8 @@ def do_create_virtualenv(python=None, site_packages=False): # Actually create the virtualenv. with spinner(): try: - c = delegator.run(cmd, block=False, timeout=PIPENV_TIMEOUT) + pip_config = {'PIP_INDEX_URL': fs_str(pypi_mirror)} if pypi_mirror else {} + c = delegator.run(cmd, block=False, timeout=PIPENV_TIMEOUT, env=pip_config) except OSError: click.echo( '{0}: it looks like {1} is not in your {2}. ' @@ -1264,7 +1266,7 @@ def do_init( if not system: if not project.virtualenv_exists: try: - do_create_virtualenv() + do_create_virtualenv(pypi_mirror=pypi_mirror) except KeyboardInterrupt: cleanup_virtualenv(bare=False) sys.exit(1) @@ -1789,6 +1791,7 @@ def do_install( warn=True, deploy=deploy, skip_requirements=skip_requirements, + pypi_mirror=pypi_mirror, ) # Load the --pre settings from the Pipfile. if not pre: @@ -2097,7 +2100,7 @@ def do_uninstall( if PIPENV_USE_SYSTEM: system = True # Ensure that virtualenv is available. - ensure_project(three=three, python=python) + ensure_project(three=three, python=python, pypi_mirror=pypi_mirror) package_names = (package_name,) + more_packages pipfile_remove = True # Un-install all dependencies, if --all was provided. @@ -2166,11 +2169,11 @@ def do_uninstall( do_lock(system=system, keep_outdated=keep_outdated, pypi_mirror=pypi_mirror) -def do_shell(three=None, python=False, fancy=False, shell_args=None): +def do_shell(three=None, python=False, fancy=False, shell_args=None, pypi_mirror=None): from .patched.pew import pew # Ensure that virtualenv is available. - ensure_project(three=three, python=python, validate=False) + ensure_project(three=three, python=python, validate=False, pypi_mirror=pypi_mirror) # Set an environment variable, so we know we're in the environment. os.environ['PIPENV_ACTIVE'] = '1' compat = (not fancy) @@ -2320,13 +2323,13 @@ def do_run_posix(script, command): os.execl(command_path, command_path, *script.args) -def do_run(command, args, three=None, python=False): +def do_run(command, args, three=None, python=False, pypi_mirror=None): """Attempt to run command either pulling from project or interpreting as executable. Args are appended to the command in [scripts] section of project if found. """ # Ensure that virtualenv is available. - ensure_project(three=three, python=python, validate=False) + ensure_project(three=three, python=python, validate=False, pypi_mirror=pypi_mirror) load_dot_env() # Activate virtualenv under the current interpreter's environment inline_activate_virtualenv() @@ -2340,10 +2343,10 @@ def do_run(command, args, three=None, python=False): do_run_posix(script, command=command) -def do_check(three=None, python=False, system=False, unused=False, ignore=None, args=None): +def do_check(three=None, python=False, system=False, unused=False, ignore=None, args=None, pypi_mirror=None): if not system: # Ensure that virtualenv is available. - ensure_project(three=three, python=python, validate=False, warn=False) + ensure_project(three=three, python=python, validate=False, warn=False, pypi_mirror=pypi_mirror) if not args: args = [] if unused: @@ -2586,7 +2589,7 @@ def do_sync( sys.exit(1) # Ensure that virtualenv is available if not system. - ensure_project(three=three, python=python, validate=False, deploy=deploy) + ensure_project(three=three, python=python, validate=False, deploy=deploy, pypi_mirror=pypi_mirror) # Install everything. requirements_dir = TemporaryDirectory( @@ -2610,7 +2613,7 @@ def do_clean( ctx, three=None, python=None, dry_run=False, bare=False, verbose=False, pypi_mirror=None ): # Ensure that virtualenv is available. - ensure_project(three=three, python=python, validate=False) + ensure_project(three=three, python=python, validate=False, pypi_mirror=pypi_mirror) ensure_lockfile(pypi_mirror=pypi_mirror) installed_package_names = []