Skip to content

Commit

Permalink
Add support for PyPI mirrors
Browse files Browse the repository at this point in the history
Adds support for the --pypi-mirror command line parameter and the
PIPENV_PYPI_MIRROR environment variable for most pipenv operations.
This permits pipenv to function without pypi.org, which is necessary for
users:

    1. behind restrictive networks
    2. facing strict artifact sourcing policies
    3. experiencing poor performance connecting to pypi.org
    4. who've configured a local cache for performance reasons

When specified, the value of this parameter replaces all instances of
pypi.org and pypi.python.org within pipenv operations without modifying
or requring the modification of Pipfiles.

- Resolves #2075
  • Loading branch information
JacobHenner committed Jun 7, 2018
1 parent e937d85 commit 18f8a69
Show file tree
Hide file tree
Showing 10 changed files with 265 additions and 20 deletions.
17 changes: 17 additions & 0 deletions docs/advanced.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,23 @@ If you'd like a specific package to be installed with a specific package index,

Very fancy.

☤ Using a PyPI Mirror
----------------------------

If you'd like to override the default PyPI index urls with the url for a PyPI mirror, you can use the following::

$ pipenv install --pypi-mirror <mirror_url>

$ pipenv update --pypi-mirror <mirror_url>

$ pipenv sync --pypi-mirror <mirror_url>

$ pipenv lock --pypi-mirror <mirror_url>

$ pipenv uninstall --pypi-mirror <mirror_url>

Alternatively, you can set the ``PIPENV_PYPI_MIRROR`` environment variable.

☤ Injecting credentials into Pipfiles via environment variables
-----------------------------------------------------------------

Expand Down
61 changes: 55 additions & 6 deletions pipenv/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

from . import environments
from .environments import *
from .utils import is_valid_url

# Enable shell completion.
init_completion()
Expand Down Expand Up @@ -79,7 +80,10 @@ def validate_python_path(ctx, param, value):
raise BadParameter('Expected Python at path %s does not exist' % value)
return value


def validate_pypi_mirror(ctx, param, value):
if value and not is_valid_url(value):
raise BadParameter('Invalid PyPI mirror URL: %s' % value)
return value
@group(
cls=PipenvGroup,
invoke_without_command=True,
Expand Down Expand Up @@ -302,6 +306,13 @@ def cli(
callback=validate_python_path,
help="Specify which version of Python virtualenv should use.",
)
@option(
'--pypi-mirror',
default=PIPENV_PYPI_MIRROR,
nargs=1,
callback=validate_pypi_mirror,
help="Specify a PyPI mirror.",
)
@option(
'--system', is_flag=True, default=False, help="System pip management."
)
Expand Down Expand Up @@ -368,6 +379,7 @@ def install(
dev=False,
three=False,
python=False,
pypi_mirror=None,
system=False,
lock=True,
ignore_pipfile=False,
Expand All @@ -389,6 +401,7 @@ def install(
dev=dev,
three=three,
python=python,
pypi_mirror=pypi_mirror,
system=system,
lock=lock,
ignore_pipfile=ignore_pipfile,
Expand Down Expand Up @@ -452,6 +465,13 @@ def install(
default=False,
help=u"Keep out–dated dependencies from being updated in Pipfile.lock.",
)
@option(
'--pypi-mirror',
default=PIPENV_PYPI_MIRROR,
nargs=1,
callback=validate_pypi_mirror,
help="Specify a PyPI mirror.",
)
def uninstall(
package_name=False,
more_packages=False,
Expand All @@ -463,6 +483,7 @@ def uninstall(
all=False,
verbose=False,
keep_outdated=False,
pypi_mirror=None,
):
from .core import do_uninstall

Expand All @@ -477,6 +498,7 @@ def uninstall(
all=all,
verbose=verbose,
keep_outdated=keep_outdated,
pypi_mirror=pypi_mirror,
)


Expand All @@ -494,6 +516,13 @@ def uninstall(
callback=validate_python_path,
help="Specify which version of Python virtualenv should use.",
)
@option(
'--pypi-mirror',
default=PIPENV_PYPI_MIRROR,
nargs=1,
callback=validate_pypi_mirror,
help="Specify a PyPI mirror.",
)
@option(
'--verbose',
'-v',
Expand Down Expand Up @@ -531,6 +560,7 @@ def uninstall(
def lock(
three=None,
python=False,
pypi_mirror=None,
verbose=False,
requirements=False,
dev=False,
Expand All @@ -543,9 +573,9 @@ def lock(
# Ensure that virtualenv is available.
ensure_project(three=three, python=python)
if requirements:
do_init(dev=dev, requirements=requirements)
do_init(dev=dev, requirements=requirements, pypi_mirror=pypi_mirror)
do_lock(
verbose=verbose, clear=clear, pre=pre, keep_outdated=keep_outdated
verbose=verbose, clear=clear, pre=pre, keep_outdated=keep_outdated, pypi_mirror=pypi_mirror
)


Expand Down Expand Up @@ -695,6 +725,13 @@ def check(
callback=validate_python_path,
help="Specify which version of Python virtualenv should use.",
)
@option(
'--pypi-mirror',
default=PIPENV_PYPI_MIRROR,
nargs=1,
callback=validate_pypi_mirror,
help="Specify a PyPI mirror.",
)
@option(
'--verbose',
'-v',
Expand Down Expand Up @@ -747,6 +784,7 @@ def update(
ctx,
three=None,
python=False,
pypi_mirror=None,
system=False,
verbose=False,
clear=False,
Expand Down Expand Up @@ -774,7 +812,7 @@ def update(
if not outdated:
outdated = bool(dry_run)
if outdated:
do_outdated()
do_outdated(pypi_mirror=pypi_mirror)
if not package:
echo(
'{0} {1} {2} {3}{4}'.format(
Expand All @@ -786,7 +824,7 @@ def update(
)
)
do_lock(
verbose=verbose, clear=clear, pre=pre, keep_outdated=keep_outdated
verbose=verbose, clear=clear, pre=pre, keep_outdated=keep_outdated, pypi_mirror=pypi_mirror
)
do_sync(
ctx=ctx,
Expand All @@ -801,6 +839,7 @@ def update(
clear=clear,
unused=False,
sequential=sequential,
pypi_mirror=pypi_mirror,
)
else:
for package in ([package] + list(more_packages) or []):
Expand All @@ -814,14 +853,15 @@ def update(
err=True,
)
sys.exit(1)
ensure_lockfile(keep_outdated=project.lockfile_exists)
ensure_lockfile(keep_outdated=project.lockfile_exists, pypi_mirror=pypi_mirror)
# Install the dependencies.
do_install(
package_name=package,
more_packages=more_packages,
dev=dev,
three=three,
python=python,
pypi_mirror=pypi_mirror,
system=system,
lock=True,
ignore_pipfile=False,
Expand Down Expand Up @@ -922,6 +962,13 @@ def run_open(module, three=None, python=None):
callback=validate_python_path,
help="Specify which version of Python virtualenv should use.",
)
@option(
'--pypi-mirror',
default=PIPENV_PYPI_MIRROR,
nargs=1,
callback=validate_pypi_mirror,
help="Specify a PyPI mirror.",
)
@option('--bare', is_flag=True, default=False, help="Minimal output.")
@option(
'--clear', is_flag=True, default=False, help="Clear the dependency cache."
Expand All @@ -946,6 +993,7 @@ def sync(
unused=False,
package_name=None,
sequential=False,
pypi_mirror=None,
):
from .core import do_sync

Expand All @@ -962,6 +1010,7 @@ def sync(
clear=clear,
unused=unused,
sequential=sequential,
pypi_mirror=pypi_mirror,
)


Expand Down
Loading

0 comments on commit 18f8a69

Please sign in to comment.