diff --git a/.travis.yml b/.travis.yml index 4dc2d48..bf15f21 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,17 @@ language: python -python: 2.7 -env: - - TOX_ENV=py33 - - TOX_ENV=py27 - - TOX_ENV=pypy +sudo: false +cache: pip + +matrix: + include: + - python: 2.7 + env: TOX_ENV=py27 + - python: 3.4 + env: TOX_ENV=py34 + - python: 3.5 + env: TOX_ENV=py35 + - python: pypy + env: TOX_ENV=pypy install: - pip install tox==2.0.2 script: diff --git a/libpip2pi/commands.py b/libpip2pi/commands.py index 3079b50..28c0769 100644 --- a/libpip2pi/commands.py +++ b/libpip2pi/commands.py @@ -19,10 +19,42 @@ except ImportError: has_wheel = False + +def try_int(x): + try: + return int(x) + except ValueError: + return x + + try: - import pip + pip_pkg_info = pkg_resources.get_distribution('pip') + pip_version = tuple(try_int(x) for x in pip_pkg_info.version.split(".")) + has_pip = True except ImportError: - pip = None + pip_version = None + has_pip = False + pip_download_command = '' + pip_no_binary_command = '' + + +if pip_version: + if pip_version >= (10, 0, 0): + from pip._internal import main as pip_main + pip_download_command = 'download --dest' + pip_no_binary_command = '--no-binary=:all:' + elif pip_version >= (8, 0, 0): + from pip import main as pip_main + pip_download_command = 'download --dest' + pip_no_binary_command = '--no-binary=:all:' + elif pip_version >= (7, 0, 0): + from pip import main as pip_main + pip_download_command = 'install --download' + pip_no_binary_command = '--no-binary=:all:' + else: + from pip import main as pip_main + pip_download_command = 'install --download' + pip_no_binary_command = '--no-use-wheel' class PipError(Exception): pass @@ -130,18 +162,9 @@ def file_to_package(file, basedir=None): return (to_safe_name(split[0]), to_safe_rest(split[1])) -def try_int(x): - try: - return int(x) - except ValueError: - return x - -def pip_get_version(): - pip_dist = pkg_resources.get_distribution("pip") - return tuple(try_int(x) for x in pip_dist.version.split(".")) def pip_run_command(pip_args): - if pip is None: + if not has_pip: print("===== WARNING =====") print("Cannot `import pip` - falling back to the pip executable.") print("This will be deprecated in a future release.") @@ -151,11 +174,14 @@ def pip_run_command(pip_args): check_call(["pip"] + pip_args) return - version = pip_get_version() - if version < (1, 1): + if pip_version < (1, 1): raise RuntimeError("pip >= 1.1 required, but %s is installed" - %(version, )) - res = pip.main(pip_args) + %(pip_version, )) + # TODO: Remove this once + # pip._internal.req.req_tracker.RequirementTracker.cleanup() does it + # already. + os.environ.pop('PIP_REQ_TRACKER', None) + res = pip_main(pip_args) if res != 0: raise PipError("pip failed with status %s while running: %s" %(res, pip_args)) @@ -381,7 +407,7 @@ def pip2tgz(argv=sys.argv): description=dedent(""" Where PACKAGES are any names accepted by pip (ex, `foo`, `foo==1.2`, `-r requirements.txt`), and [PIP_OPTIONS] can be any - options accepted by `pip install -d`. + options accepted by `pip %s`. pip2tgz will download all packages required to install PACKAGES and save them to sanely-named tarballs or wheel files in OUTPUT_DIRECTORY. @@ -390,10 +416,10 @@ def pip2tgz(argv=sys.argv): $ pip2tgz /var/www/packages/ -r requirements.txt foo==1.2 baz/ $ pip2tgz /var/www/packages/ \\ - --no-use-wheel \\ + %s \\ --index-url https://example.com/simple \\ bar==3.1 - """)) + """ % (pip_download_command, pip_no_binary_command))) option, argv = parser.parse_args(argv) if len(argv) < 3: @@ -410,7 +436,10 @@ def pip2tgz(argv=sys.argv): pkg_file_set = lambda: set(globall(full_glob_paths)) old_pkgs = pkg_file_set() - pip_run_command(['install', '-d', outdir] + argv[2:]) + if pip_version >= (8, 0, 0): + pip_run_command(pip_download_command.split() + [outdir] + argv[2:]) + else: + pip_run_command(pip_download_command.split() + [outdir] + argv[2:]) os.chdir(outdir) new_pkgs = pkg_file_set() - old_pkgs @@ -436,7 +465,6 @@ def handle_new_wheels(outdir, new_wheels): if not new_wheels: return 0 - pip_version = pip_get_version() if pip_version >= (1, 5, 3): return 0 @@ -485,8 +513,8 @@ def pip2pi(argv=sys.argv): package index will be built locally and rsync will be used to copy it to the remote host. - PIP_OPTIONS can be any options accepted by `pip install -d`, like - `--index-url` or `--no-use-wheel`. + PIP_OPTIONS can be any options accepted by `pip %s`, like + `--index-url` or `%s`. For example, to create a remote index: @@ -499,13 +527,13 @@ def pip2pi(argv=sys.argv): To pass arguments to pip: $ pip2pi ~/Sites/packages/ \\ - --no-use-wheel \\ + %s \\ --index-url https://example.com/simple \\ -r requirements-base.txt \\ -r requirements-dev.txt \\ bar==3.1 - """)) + """ % (pip_download_command, pip_no_binary_command, pip_no_binary_command))) parser.add_index_options() option, argv = parser.parse_args(argv) @@ -530,7 +558,7 @@ def pip2pi(argv=sys.argv): return res if option.get_source: subcmd_argv_source = subcmd_argv[:] - subcmd_argv_source.insert(2, '--no-use-wheel') + subcmd_argv_source.insert(2, pip_no_binary_command) res = pip2tgz(subcmd_argv_source) if res: print("pip2tgz returned an error; aborting.") diff --git a/tox.ini b/tox.ini index 5ebbba0..a4af9c5 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py{27,35}-pip{6,7,8} +envlist = py{27,34,35}-pip{6,7,8}, pypy [testenv] deps =