mirror of https://github.com/pypa/pip
Remove the items deprecated for removal in 7.0
This commit is contained in:
parent
6ab5f586c1
commit
b7309c6bcc
16
CHANGES.txt
16
CHANGES.txt
|
@ -1,5 +1,21 @@
|
|||
**7.0.0 (unreleased)**
|
||||
|
||||
* **BACKWARD INCOMPATIBLE** Removed the deprecated ``--mirror``,
|
||||
``--use-mirrors``, and ``-M`` options.
|
||||
|
||||
* **BACKWARD INCOMPATIBLE** Removed the deprecated ``zip`` and ``unzip``
|
||||
commands.
|
||||
|
||||
* **BACKWARD INCOMPATIBLE** Removed the deprecated ``--no-install`` and
|
||||
``--no-download`` options.
|
||||
|
||||
* **BACKWARD INCOMPATIBLE** No longer implicitly support an insecure origin
|
||||
origin, and instead require insecure origins be explicitly trusted with the
|
||||
``--trusted-host`` option.
|
||||
|
||||
* **BACKWARD INCOMPATIBLE** Removed the deprecated link scraping that attempted
|
||||
to parse HTML comments for a specially formatted comment.
|
||||
|
||||
|
||||
**6.1.0 (2015-04-07)**
|
||||
|
||||
|
|
|
@ -213,23 +213,6 @@ find_links = OptionMaker(
|
|||
"If a local path or file:// url that's a directory, then look for "
|
||||
"archives in the directory listing.")
|
||||
|
||||
# TODO: Remove after 6.0
|
||||
use_mirrors = OptionMaker(
|
||||
'-M', '--use-mirrors',
|
||||
dest='use_mirrors',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help=SUPPRESS_HELP)
|
||||
|
||||
# TODO: Remove after 6.0
|
||||
mirrors = OptionMaker(
|
||||
'--mirrors',
|
||||
dest='mirrors',
|
||||
metavar='URL',
|
||||
action='append',
|
||||
default=[],
|
||||
help=SUPPRESS_HELP)
|
||||
|
||||
allow_external = OptionMaker(
|
||||
"--allow-external",
|
||||
dest="allow_external",
|
||||
|
@ -446,8 +429,6 @@ index_group = {
|
|||
extra_index_url,
|
||||
no_index,
|
||||
find_links,
|
||||
use_mirrors,
|
||||
mirrors,
|
||||
allow_external,
|
||||
allow_all_external,
|
||||
no_allow_external,
|
||||
|
|
|
@ -11,8 +11,6 @@ from pip.commands.search import SearchCommand
|
|||
from pip.commands.show import ShowCommand
|
||||
from pip.commands.install import InstallCommand
|
||||
from pip.commands.uninstall import UninstallCommand
|
||||
from pip.commands.unzip import UnzipCommand
|
||||
from pip.commands.zip import ZipCommand
|
||||
from pip.commands.wheel import WheelCommand
|
||||
|
||||
|
||||
|
@ -24,8 +22,6 @@ commands_dict = {
|
|||
ShowCommand.name: ShowCommand,
|
||||
InstallCommand.name: InstallCommand,
|
||||
UninstallCommand.name: UninstallCommand,
|
||||
UnzipCommand.name: UnzipCommand,
|
||||
ZipCommand.name: ZipCommand,
|
||||
ListCommand.name: ListCommand,
|
||||
WheelCommand.name: WheelCommand,
|
||||
}
|
||||
|
@ -39,8 +35,6 @@ commands_order = [
|
|||
ShowCommand,
|
||||
SearchCommand,
|
||||
WheelCommand,
|
||||
ZipCommand,
|
||||
UnzipCommand,
|
||||
HelpCommand,
|
||||
]
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ import shutil
|
|||
import warnings
|
||||
|
||||
from pip.req import InstallRequirement, RequirementSet, parse_requirements
|
||||
from pip.locations import build_prefix, virtualenv_no_global, distutils_scheme
|
||||
from pip.locations import virtualenv_no_global, distutils_scheme
|
||||
from pip.basecommand import Command
|
||||
from pip.index import PackageFinder
|
||||
from pip.exceptions import (
|
||||
|
@ -16,7 +16,7 @@ from pip.exceptions import (
|
|||
)
|
||||
from pip import cmdoptions
|
||||
from pip.utils.build import BuildDirectory
|
||||
from pip.utils.deprecation import RemovedInPip7Warning, RemovedInPip8Warning
|
||||
from pip.utils.deprecation import RemovedInPip8Warning
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -101,22 +101,6 @@ class InstallCommand(Command):
|
|||
|
||||
cmd_opts.add_option(cmdoptions.no_deps.make())
|
||||
|
||||
cmd_opts.add_option(
|
||||
'--no-install',
|
||||
dest='no_install',
|
||||
action='store_true',
|
||||
help="DEPRECATED. Download and unpack all packages, but don't "
|
||||
"actually install them."
|
||||
)
|
||||
|
||||
cmd_opts.add_option(
|
||||
'--no-download',
|
||||
dest='no_download',
|
||||
action="store_true",
|
||||
help="DEPRECATED. Don't download any packages, just install the "
|
||||
"ones already downloaded (completes an install run with "
|
||||
"--no-install).")
|
||||
|
||||
cmd_opts.add_option(cmdoptions.install_options.make())
|
||||
cmd_opts.add_option(cmdoptions.global_options.make())
|
||||
|
||||
|
@ -202,24 +186,7 @@ class InstallCommand(Command):
|
|||
|
||||
def run(self, options, args):
|
||||
|
||||
if (
|
||||
options.no_install or
|
||||
options.no_download
|
||||
):
|
||||
warnings.warn(
|
||||
"--no-install and --no-download are deprecated. "
|
||||
"See https://github.com/pypa/pip/issues/906.",
|
||||
RemovedInPip7Warning,
|
||||
)
|
||||
|
||||
# If we have --no-install or --no-download and no --build we use the
|
||||
# legacy static build dir
|
||||
if (options.build_dir is None and
|
||||
(options.no_install or options.no_download)):
|
||||
options.build_dir = build_prefix
|
||||
|
||||
if options.download_dir:
|
||||
options.no_install = True
|
||||
options.ignore_installed = True
|
||||
|
||||
if options.build_dir:
|
||||
|
@ -254,23 +221,6 @@ class InstallCommand(Command):
|
|||
logger.info('Ignoring indexes: %s', ','.join(index_urls))
|
||||
index_urls = []
|
||||
|
||||
if options.use_mirrors:
|
||||
warnings.warn(
|
||||
"--use-mirrors has been deprecated and will be removed in the "
|
||||
"future. Explicit uses of --index-url and/or --extra-index-url"
|
||||
" is suggested.",
|
||||
RemovedInPip7Warning,
|
||||
)
|
||||
|
||||
if options.mirrors:
|
||||
warnings.warn(
|
||||
"--mirrors has been deprecated and will be removed in the "
|
||||
"future. Explicit uses of --index-url and/or --extra-index-url"
|
||||
" is suggested.",
|
||||
RemovedInPip7Warning,
|
||||
)
|
||||
index_urls += options.mirrors
|
||||
|
||||
if options.download_cache:
|
||||
warnings.warn(
|
||||
"--download-cache has been deprecated and will be removed in "
|
||||
|
@ -338,14 +288,9 @@ class InstallCommand(Command):
|
|||
return
|
||||
|
||||
try:
|
||||
if not options.no_download:
|
||||
requirement_set.prepare_files(finder)
|
||||
else:
|
||||
# This is the only call site of locate_files. Nuke with
|
||||
# fire.
|
||||
requirement_set.locate_files()
|
||||
requirement_set.prepare_files(finder)
|
||||
|
||||
if not options.no_install:
|
||||
if not options.download_dir:
|
||||
requirement_set.install(
|
||||
install_options,
|
||||
global_options,
|
||||
|
@ -381,9 +326,7 @@ class InstallCommand(Command):
|
|||
raise
|
||||
finally:
|
||||
# Clean up
|
||||
if ((not options.no_clean) and
|
||||
((not options.no_install) or
|
||||
options.download_dir)):
|
||||
if not options.no_clean:
|
||||
requirement_set.cleanup_files()
|
||||
|
||||
if options.target_dir:
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
import warnings
|
||||
|
||||
from pip.basecommand import Command
|
||||
from pip.exceptions import DistributionNotFound
|
||||
from pip.index import PackageFinder
|
||||
from pip.req import InstallRequirement
|
||||
from pip.utils import get_installed_distributions, dist_is_editable
|
||||
from pip.utils.deprecation import RemovedInPip7Warning
|
||||
from pip.cmdoptions import make_option_group, index_group
|
||||
|
||||
|
||||
|
@ -113,23 +111,6 @@ class ListCommand(Command):
|
|||
logger.info('Ignoring indexes: %s', ','.join(index_urls))
|
||||
index_urls = []
|
||||
|
||||
if options.use_mirrors:
|
||||
warnings.warn(
|
||||
"--use-mirrors has been deprecated and will be removed in the "
|
||||
"future. Explicit uses of --index-url and/or --extra-index-url"
|
||||
" is suggested.",
|
||||
RemovedInPip7Warning,
|
||||
)
|
||||
|
||||
if options.mirrors:
|
||||
warnings.warn(
|
||||
"--mirrors has been deprecated and will be removed in the "
|
||||
"future. Explicit uses of --index-url and/or --extra-index-url"
|
||||
" is suggested.",
|
||||
RemovedInPip7Warning,
|
||||
)
|
||||
index_urls += options.mirrors
|
||||
|
||||
dependency_links = []
|
||||
for dist in get_installed_distributions(local_only=options.local,
|
||||
user_only=options.user):
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
from __future__ import absolute_import
|
||||
|
||||
from pip.commands.zip import ZipCommand
|
||||
|
||||
|
||||
class UnzipCommand(ZipCommand):
|
||||
"""Unzip individual packages."""
|
||||
name = 'unzip'
|
||||
summary = 'DEPRECATED. Unzip individual packages.'
|
|
@ -11,7 +11,7 @@ from pip.exceptions import CommandError, PreviousBuildDirError
|
|||
from pip.req import InstallRequirement, RequirementSet, parse_requirements
|
||||
from pip.utils import import_or_raise, normalize_path
|
||||
from pip.utils.build import BuildDirectory
|
||||
from pip.utils.deprecation import RemovedInPip7Warning, RemovedInPip8Warning
|
||||
from pip.utils.deprecation import RemovedInPip8Warning
|
||||
from pip.wheel import WheelBuilder
|
||||
from pip import cmdoptions
|
||||
|
||||
|
@ -128,23 +128,6 @@ class WheelCommand(Command):
|
|||
logger.info('Ignoring indexes: %s', ','.join(index_urls))
|
||||
index_urls = []
|
||||
|
||||
if options.use_mirrors:
|
||||
warnings.warn(
|
||||
"--use-mirrors has been deprecated and will be removed in the "
|
||||
"future. Explicit uses of --index-url and/or --extra-index-url"
|
||||
" is suggested.",
|
||||
RemovedInPip7Warning,
|
||||
)
|
||||
|
||||
if options.mirrors:
|
||||
warnings.warn(
|
||||
"--mirrors has been deprecated and will be removed in the "
|
||||
"future. Explicit uses of --index-url and/or --extra-index-url"
|
||||
" is suggested.",
|
||||
RemovedInPip7Warning,
|
||||
)
|
||||
index_urls += options.mirrors
|
||||
|
||||
if options.download_cache:
|
||||
warnings.warn(
|
||||
"--download-cache has been deprecated and will be removed in "
|
||||
|
|
|
@ -1,410 +0,0 @@
|
|||
from __future__ import absolute_import
|
||||
|
||||
import sys
|
||||
import re
|
||||
import fnmatch
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
import warnings
|
||||
import zipfile
|
||||
|
||||
from pip.utils import display_path, backup_dir, rmtree
|
||||
from pip.utils.deprecation import RemovedInPip7Warning
|
||||
from pip.utils.logging import indent_log
|
||||
from pip.exceptions import InstallationError
|
||||
from pip.basecommand import Command
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ZipCommand(Command):
|
||||
"""Zip individual packages."""
|
||||
name = 'zip'
|
||||
usage = """
|
||||
%prog [options] <package> ..."""
|
||||
summary = 'DEPRECATED. Zip individual packages.'
|
||||
|
||||
def __init__(self, *args, **kw):
|
||||
super(ZipCommand, self).__init__(*args, **kw)
|
||||
if self.name == 'zip':
|
||||
self.cmd_opts.add_option(
|
||||
'--unzip',
|
||||
action='store_true',
|
||||
dest='unzip',
|
||||
help='Unzip (rather than zip) a package.')
|
||||
else:
|
||||
self.cmd_opts.add_option(
|
||||
'--zip',
|
||||
action='store_false',
|
||||
dest='unzip',
|
||||
default=True,
|
||||
help='Zip (rather than unzip) a package.')
|
||||
self.cmd_opts.add_option(
|
||||
'--no-pyc',
|
||||
action='store_true',
|
||||
dest='no_pyc',
|
||||
help=(
|
||||
'Do not include .pyc files in zip files (useful on Google App '
|
||||
'Engine).'),
|
||||
)
|
||||
self.cmd_opts.add_option(
|
||||
'-l', '--list',
|
||||
action='store_true',
|
||||
dest='list',
|
||||
help='List the packages available, and their zip status.')
|
||||
self.cmd_opts.add_option(
|
||||
'--sort-files',
|
||||
action='store_true',
|
||||
dest='sort_files',
|
||||
help=('With --list, sort packages according to how many files they'
|
||||
' contain.'),
|
||||
)
|
||||
self.cmd_opts.add_option(
|
||||
'--path',
|
||||
action='append',
|
||||
dest='paths',
|
||||
help=('Restrict operations to the given paths (may include '
|
||||
'wildcards).'),
|
||||
)
|
||||
self.cmd_opts.add_option(
|
||||
'-n', '--simulate',
|
||||
action='store_true',
|
||||
help='Do not actually perform the zip/unzip operation.')
|
||||
|
||||
self.parser.insert_option_group(0, self.cmd_opts)
|
||||
|
||||
def paths(self):
|
||||
"""All the entries of sys.path, possibly restricted by --path"""
|
||||
if not self.select_paths:
|
||||
return sys.path
|
||||
result = []
|
||||
match_any = set()
|
||||
for path in sys.path:
|
||||
path = os.path.normcase(os.path.abspath(path))
|
||||
for match in self.select_paths:
|
||||
match = os.path.normcase(os.path.abspath(match))
|
||||
if '*' in match:
|
||||
if re.search(fnmatch.translate(match + '*'), path):
|
||||
result.append(path)
|
||||
match_any.add(match)
|
||||
break
|
||||
else:
|
||||
if path.startswith(match):
|
||||
result.append(path)
|
||||
match_any.add(match)
|
||||
break
|
||||
else:
|
||||
logger.debug(
|
||||
"Skipping path %s because it doesn't match %s",
|
||||
path,
|
||||
', '.join(self.select_paths),
|
||||
)
|
||||
for match in self.select_paths:
|
||||
if match not in match_any and '*' not in match:
|
||||
result.append(match)
|
||||
logger.debug(
|
||||
"Adding path %s because it doesn't match "
|
||||
"anything already on sys.path",
|
||||
match,
|
||||
)
|
||||
return result
|
||||
|
||||
def run(self, options, args):
|
||||
|
||||
warnings.warn(
|
||||
"'pip zip' and 'pip unzip` are deprecated, and will be removed in "
|
||||
"a future release.",
|
||||
RemovedInPip7Warning,
|
||||
)
|
||||
|
||||
self.select_paths = options.paths
|
||||
self.simulate = options.simulate
|
||||
if options.list:
|
||||
return self.list(options, args)
|
||||
if not args:
|
||||
raise InstallationError(
|
||||
'You must give at least one package to zip or unzip')
|
||||
packages = []
|
||||
for arg in args:
|
||||
module_name, filename = self.find_package(arg)
|
||||
if options.unzip and os.path.isdir(filename):
|
||||
raise InstallationError(
|
||||
'The module %s (in %s) is not a zip file; cannot be '
|
||||
'unzipped' % (module_name, filename)
|
||||
)
|
||||
elif not options.unzip and not os.path.isdir(filename):
|
||||
raise InstallationError(
|
||||
'The module %s (in %s) is not a directory; cannot be '
|
||||
'zipped' % (module_name, filename)
|
||||
)
|
||||
packages.append((module_name, filename))
|
||||
last_status = None
|
||||
for module_name, filename in packages:
|
||||
if options.unzip:
|
||||
last_status = self.unzip_package(module_name, filename)
|
||||
else:
|
||||
last_status = self.zip_package(
|
||||
module_name, filename, options.no_pyc
|
||||
)
|
||||
return last_status
|
||||
|
||||
def unzip_package(self, module_name, filename):
|
||||
zip_filename = os.path.dirname(filename)
|
||||
if (not os.path.isfile(zip_filename) and
|
||||
zipfile.is_zipfile(zip_filename)):
|
||||
raise InstallationError(
|
||||
'Module %s (in %s) isn\'t located in a zip file in %s'
|
||||
% (module_name, filename, zip_filename))
|
||||
package_path = os.path.dirname(zip_filename)
|
||||
if package_path not in self.paths():
|
||||
logger.warning(
|
||||
'Unpacking %s into %s, but %s is not on sys.path',
|
||||
display_path(zip_filename),
|
||||
display_path(package_path),
|
||||
display_path(package_path),
|
||||
)
|
||||
logger.info(
|
||||
'Unzipping %s (in %s)', module_name, display_path(zip_filename),
|
||||
)
|
||||
if self.simulate:
|
||||
logger.info(
|
||||
'Skipping remaining operations because of --simulate'
|
||||
)
|
||||
return
|
||||
|
||||
with indent_log():
|
||||
# FIXME: this should be undoable:
|
||||
zip = zipfile.ZipFile(zip_filename)
|
||||
to_save = []
|
||||
for info in zip.infolist():
|
||||
name = info.filename
|
||||
if name.startswith(module_name + os.path.sep):
|
||||
content = zip.read(name)
|
||||
dest = os.path.join(package_path, name)
|
||||
if not os.path.exists(os.path.dirname(dest)):
|
||||
os.makedirs(os.path.dirname(dest))
|
||||
if not content and dest.endswith(os.path.sep):
|
||||
if not os.path.exists(dest):
|
||||
os.makedirs(dest)
|
||||
else:
|
||||
with open(dest, 'wb') as f:
|
||||
f.write(content)
|
||||
else:
|
||||
to_save.append((name, zip.read(name)))
|
||||
zip.close()
|
||||
if not to_save:
|
||||
logger.debug(
|
||||
'Removing now-empty zip file %s',
|
||||
display_path(zip_filename)
|
||||
)
|
||||
os.unlink(zip_filename)
|
||||
self.remove_filename_from_pth(zip_filename)
|
||||
else:
|
||||
logger.debug(
|
||||
'Removing entries in %s/ from zip file %s',
|
||||
module_name,
|
||||
display_path(zip_filename),
|
||||
)
|
||||
zip = zipfile.ZipFile(zip_filename, 'w')
|
||||
for name, content in to_save:
|
||||
zip.writestr(name, content)
|
||||
zip.close()
|
||||
|
||||
def zip_package(self, module_name, filename, no_pyc):
|
||||
logger.info('Zip %s (in %s)', module_name, display_path(filename))
|
||||
|
||||
orig_filename = filename
|
||||
if filename.endswith('.egg'):
|
||||
dest_filename = filename
|
||||
else:
|
||||
dest_filename = filename + '.zip'
|
||||
|
||||
with indent_log():
|
||||
# FIXME: I think this needs to be undoable:
|
||||
if filename == dest_filename:
|
||||
filename = backup_dir(orig_filename)
|
||||
logger.info(
|
||||
'Moving %s aside to %s', orig_filename, filename,
|
||||
)
|
||||
if not self.simulate:
|
||||
shutil.move(orig_filename, filename)
|
||||
try:
|
||||
logger.debug(
|
||||
'Creating zip file in %s', display_path(dest_filename),
|
||||
)
|
||||
if not self.simulate:
|
||||
zip = zipfile.ZipFile(dest_filename, 'w')
|
||||
zip.writestr(module_name + '/', '')
|
||||
for dirpath, dirnames, filenames in os.walk(filename):
|
||||
if no_pyc:
|
||||
filenames = [f for f in filenames
|
||||
if not f.lower().endswith('.pyc')]
|
||||
for fns, is_dir in [
|
||||
(dirnames, True), (filenames, False)]:
|
||||
for fn in fns:
|
||||
full = os.path.join(dirpath, fn)
|
||||
dest = os.path.join(
|
||||
module_name,
|
||||
dirpath[len(filename):].lstrip(
|
||||
os.path.sep
|
||||
),
|
||||
fn,
|
||||
)
|
||||
if is_dir:
|
||||
zip.writestr(dest + '/', '')
|
||||
else:
|
||||
zip.write(full, dest)
|
||||
zip.close()
|
||||
logger.debug(
|
||||
'Removing old directory %s', display_path(filename),
|
||||
)
|
||||
if not self.simulate:
|
||||
rmtree(filename)
|
||||
except:
|
||||
# FIXME: need to do an undo here
|
||||
raise
|
||||
# FIXME: should also be undone:
|
||||
self.add_filename_to_pth(dest_filename)
|
||||
|
||||
def remove_filename_from_pth(self, filename):
|
||||
for pth in self.pth_files():
|
||||
with open(pth, 'r') as f:
|
||||
lines = f.readlines()
|
||||
new_lines = [
|
||||
l for l in lines if l.strip() != filename]
|
||||
if lines != new_lines:
|
||||
logger.debug(
|
||||
'Removing reference to %s from .pth file %s',
|
||||
display_path(filename),
|
||||
display_path(pth),
|
||||
)
|
||||
if not [line for line in new_lines if line]:
|
||||
logger.debug(
|
||||
'%s file would be empty: deleting', display_path(pth)
|
||||
)
|
||||
if not self.simulate:
|
||||
os.unlink(pth)
|
||||
else:
|
||||
if not self.simulate:
|
||||
with open(pth, 'wb') as f:
|
||||
f.writelines(new_lines)
|
||||
return
|
||||
logger.warning(
|
||||
'Cannot find a reference to %s in any .pth file',
|
||||
display_path(filename),
|
||||
)
|
||||
|
||||
def add_filename_to_pth(self, filename):
|
||||
path = os.path.dirname(filename)
|
||||
dest = filename + '.pth'
|
||||
if path not in self.paths():
|
||||
logger.warning(
|
||||
'Adding .pth file %s, but it is not on sys.path',
|
||||
display_path(dest),
|
||||
)
|
||||
if not self.simulate:
|
||||
if os.path.exists(dest):
|
||||
with open(dest) as f:
|
||||
lines = f.readlines()
|
||||
if lines and not lines[-1].endswith('\n'):
|
||||
lines[-1] += '\n'
|
||||
lines.append(filename + '\n')
|
||||
else:
|
||||
lines = [filename + '\n']
|
||||
with open(dest, 'wb') as f:
|
||||
f.writelines(lines)
|
||||
|
||||
def pth_files(self):
|
||||
for path in self.paths():
|
||||
if not os.path.exists(path) or not os.path.isdir(path):
|
||||
continue
|
||||
for filename in os.listdir(path):
|
||||
if filename.endswith('.pth'):
|
||||
yield os.path.join(path, filename)
|
||||
|
||||
def find_package(self, package):
|
||||
for path in self.paths():
|
||||
full = os.path.join(path, package)
|
||||
if os.path.exists(full):
|
||||
return package, full
|
||||
if not os.path.isdir(path) and zipfile.is_zipfile(path):
|
||||
zip = zipfile.ZipFile(path, 'r')
|
||||
try:
|
||||
zip.read(os.path.join(package, '__init__.py'))
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
zip.close()
|
||||
return package, full
|
||||
zip.close()
|
||||
# FIXME: need special error for package.py case:
|
||||
raise InstallationError(
|
||||
'No package with the name %s found' % package)
|
||||
|
||||
def list(self, options, args):
|
||||
if args:
|
||||
raise InstallationError(
|
||||
'You cannot give an argument with --list')
|
||||
for path in sorted(self.paths()):
|
||||
if not os.path.exists(path):
|
||||
continue
|
||||
basename = os.path.basename(path.rstrip(os.path.sep))
|
||||
if os.path.isfile(path) and zipfile.is_zipfile(path):
|
||||
if os.path.dirname(path) not in self.paths():
|
||||
logger.info('Zipped egg: %s', display_path(path))
|
||||
continue
|
||||
if (basename != 'site-packages' and
|
||||
basename != 'dist-packages' and not
|
||||
path.replace('\\', '/').endswith('lib/python')):
|
||||
continue
|
||||
logger.info('In %s:', display_path(path))
|
||||
|
||||
with indent_log():
|
||||
zipped = []
|
||||
unzipped = []
|
||||
|
||||
for filename in sorted(os.listdir(path)):
|
||||
ext = os.path.splitext(filename)[1].lower()
|
||||
if ext in ('.pth', '.egg-info', '.egg-link'):
|
||||
continue
|
||||
if ext == '.py':
|
||||
logger.debug(
|
||||
'Not displaying %s: not a package',
|
||||
display_path(filename)
|
||||
)
|
||||
continue
|
||||
full = os.path.join(path, filename)
|
||||
if os.path.isdir(full):
|
||||
unzipped.append((filename, self.count_package(full)))
|
||||
elif zipfile.is_zipfile(full):
|
||||
zipped.append(filename)
|
||||
else:
|
||||
logger.debug(
|
||||
'Unknown file: %s', display_path(filename),
|
||||
)
|
||||
if zipped:
|
||||
logger.info('Zipped packages:')
|
||||
with indent_log():
|
||||
for filename in zipped:
|
||||
logger.info(filename)
|
||||
else:
|
||||
logger.info('No zipped packages.')
|
||||
if unzipped:
|
||||
if options.sort_files:
|
||||
unzipped.sort(key=lambda x: -x[1])
|
||||
logger.info('Unzipped packages:')
|
||||
with indent_log():
|
||||
for filename, count in unzipped:
|
||||
logger.info('%s (%i files)', filename, count)
|
||||
else:
|
||||
logger.info('No unzipped packages.')
|
||||
|
||||
def count_package(self, path):
|
||||
total = 0
|
||||
for dirpath, dirnames, filenames in os.walk(path):
|
||||
filenames = [f for f in filenames
|
||||
if not f.lower().endswith('.pyc')]
|
||||
total += len(filenames)
|
||||
return total
|
97
pip/index.py
97
pip/index.py
|
@ -16,7 +16,7 @@ from pip._vendor.six.moves.urllib import request as urllib_request
|
|||
from pip.compat import ipaddress
|
||||
from pip.utils import (
|
||||
Inf, cached_property, normalize_name, splitext, normalize_path)
|
||||
from pip.utils.deprecation import RemovedInPip7Warning, RemovedInPip8Warning
|
||||
from pip.utils.deprecation import RemovedInPip8Warning
|
||||
from pip.utils.logging import indent_log
|
||||
from pip.exceptions import (
|
||||
DistributionNotFound, BestVersionAlreadyInstalled, InvalidWheelFilename,
|
||||
|
@ -134,7 +134,7 @@ class PackageFinder(object):
|
|||
warnings.warn(
|
||||
"Dependency Links processing has been deprecated and will be "
|
||||
"removed in a future release.",
|
||||
RemovedInPip7Warning,
|
||||
RemovedInPip8Warning,
|
||||
)
|
||||
self.dependency_links.extend(links)
|
||||
|
||||
|
@ -269,27 +269,22 @@ class PackageFinder(object):
|
|||
continue
|
||||
|
||||
# If we've gotten here, then this origin matches the current
|
||||
# secure origin and we should break out of the loop and continue
|
||||
# on.
|
||||
break
|
||||
else:
|
||||
# If the loop successfully completed without a break, that means
|
||||
# that the origin we are testing is not a secure origin.
|
||||
logger.warning(
|
||||
"This repository located at %s is not a trusted host, if "
|
||||
"this repository is available via HTTPS it is recommend to "
|
||||
"use HTTPS instead, otherwise you may silence this warning "
|
||||
"with '--trusted-host %s'.",
|
||||
parsed.hostname,
|
||||
parsed.hostname,
|
||||
)
|
||||
# secure origin and we should return True
|
||||
return True
|
||||
|
||||
warnings.warn(
|
||||
"Implicitly allowing locations which are not hosted at a "
|
||||
"secure origin is deprecated and will require the use of "
|
||||
"--trusted-host in the future.",
|
||||
RemovedInPip7Warning,
|
||||
)
|
||||
# If we've gotten to this point, then the origin isn't secure and we
|
||||
# will not accept it as a valid location to search. We will however
|
||||
# log a warning that we are ignoring it.
|
||||
logger.warning(
|
||||
"The repository located at %s is not a trusted or secure host and "
|
||||
"is being ignored. If this repository is available via HTTPS it "
|
||||
"is recommended to use HTTPS instead, otherwise you may silence "
|
||||
"this warning and allow it anyways with '--trusted-host %s'.",
|
||||
parsed.hostname,
|
||||
parsed.hostname,
|
||||
)
|
||||
|
||||
return False
|
||||
|
||||
def _get_index_urls_locations(self, project_name):
|
||||
"""Returns the locations found via self.index_urls
|
||||
|
@ -362,11 +357,17 @@ class PackageFinder(object):
|
|||
# We explicitly do not trust links that came from dependency_links
|
||||
locations.extend([Link(url) for url in _ulocations])
|
||||
|
||||
# We want to filter out any thing which does not have a secure origin.
|
||||
locations = [
|
||||
l for l in locations
|
||||
if self._validate_secure_origin(logger, l)
|
||||
]
|
||||
|
||||
logger.debug('%d location(s) to search for versions of %s:',
|
||||
len(locations), project_name)
|
||||
|
||||
for location in locations:
|
||||
logger.debug('* %s', location)
|
||||
self._validate_secure_origin(logger, location)
|
||||
|
||||
find_links_versions = list(self._package_versions(
|
||||
# We trust every directly linked archive in find_links
|
||||
|
@ -528,13 +529,6 @@ class PackageFinder(object):
|
|||
"%s is potentially insecure and unverifiable.", req.name,
|
||||
)
|
||||
|
||||
if selected_version._deprecated_regex:
|
||||
warnings.warn(
|
||||
"%s discovered using a deprecated method of parsing, in the "
|
||||
"future it will no longer be discovered." % req.name,
|
||||
RemovedInPip7Warning,
|
||||
)
|
||||
|
||||
return selected_version
|
||||
|
||||
def _find_url_name(self, index_url, url_name):
|
||||
|
@ -792,14 +786,6 @@ class PackageFinder(object):
|
|||
class HTMLPage(object):
|
||||
"""Represents one page, along with its URL"""
|
||||
|
||||
# FIXME: these regexes are horrible hacks:
|
||||
_homepage_re = re.compile(b'<th>\\s*home\\s*page', re.I)
|
||||
_download_re = re.compile(b'<th>\\s*download\\s+url', re.I)
|
||||
_href_re = re.compile(
|
||||
b'href=(?:"([^"]*)"|\'([^\']*)\'|([^>\\s\\n]*))',
|
||||
re.I | re.S
|
||||
)
|
||||
|
||||
def __init__(self, content, url, headers=None, trusted=None):
|
||||
# Determine if we have any encoding information in our headers
|
||||
encoding = None
|
||||
|
@ -982,13 +968,7 @@ class HTMLPage(object):
|
|||
|
||||
yield Link(url, self, internal=internal)
|
||||
|
||||
def rel_links(self):
|
||||
for url in self.explicit_rel_links():
|
||||
yield url
|
||||
for url in self.scraped_rel_links():
|
||||
yield url
|
||||
|
||||
def explicit_rel_links(self, rels=('homepage', 'download')):
|
||||
def rel_links(self, rels=('homepage', 'download')):
|
||||
"""Yields all links with the given relations"""
|
||||
rels = set(rels)
|
||||
|
||||
|
@ -1004,29 +984,6 @@ class HTMLPage(object):
|
|||
)
|
||||
yield Link(url, self, trusted=False)
|
||||
|
||||
def scraped_rel_links(self):
|
||||
# Can we get rid of this horrible horrible method?
|
||||
for regex in (self._homepage_re, self._download_re):
|
||||
match = regex.search(self.content)
|
||||
if not match:
|
||||
continue
|
||||
href_match = self._href_re.search(self.content, pos=match.end())
|
||||
if not href_match:
|
||||
continue
|
||||
url = (
|
||||
href_match.group(1) or
|
||||
href_match.group(2) or
|
||||
href_match.group(3)
|
||||
)
|
||||
if not url:
|
||||
continue
|
||||
try:
|
||||
url = url.decode("ascii")
|
||||
except UnicodeDecodeError:
|
||||
continue
|
||||
url = self.clean_link(urllib_parse.urljoin(self.base_url, url))
|
||||
yield Link(url, self, trusted=False, _deprecated_regex=True)
|
||||
|
||||
_clean_re = re.compile(r'[^a-z0-9$&+,/:;=?@.#%_\\|-]', re.I)
|
||||
|
||||
def clean_link(self, url):
|
||||
|
@ -1039,8 +996,7 @@ class HTMLPage(object):
|
|||
|
||||
class Link(object):
|
||||
|
||||
def __init__(self, url, comes_from=None, internal=None, trusted=None,
|
||||
_deprecated_regex=False):
|
||||
def __init__(self, url, comes_from=None, internal=None, trusted=None):
|
||||
|
||||
# url can be a UNC windows share
|
||||
if url != Inf and url.startswith('\\\\'):
|
||||
|
@ -1050,7 +1006,6 @@ class Link(object):
|
|||
self.comes_from = comes_from
|
||||
self.internal = internal
|
||||
self.trusted = trusted
|
||||
self._deprecated_regex = _deprecated_regex
|
||||
|
||||
def __str__(self):
|
||||
if self.comes_from:
|
||||
|
|
|
@ -309,52 +309,6 @@ class RequirementSet(object):
|
|||
if more_reqs:
|
||||
discovered_reqs.extend(more_reqs)
|
||||
|
||||
def locate_files(self):
|
||||
"""Remove in 7.0: used by --no-download"""
|
||||
self._walk_req_to_install(self._locate_file)
|
||||
|
||||
def _locate_file(self, req_to_install):
|
||||
install_needed = True
|
||||
if not self.ignore_installed and not req_to_install.editable:
|
||||
req_to_install.check_if_exists()
|
||||
if req_to_install.satisfied_by:
|
||||
if self.upgrade:
|
||||
# don't uninstall conflict if user install and
|
||||
# conflict is not user install
|
||||
if not (self.use_user_site and
|
||||
not dist_in_usersite(
|
||||
req_to_install.satisfied_by
|
||||
)):
|
||||
req_to_install.conflicts_with = \
|
||||
req_to_install.satisfied_by
|
||||
req_to_install.satisfied_by = None
|
||||
else:
|
||||
install_needed = False
|
||||
logger.info(
|
||||
'Requirement already satisfied (use --upgrade to '
|
||||
'upgrade): %s',
|
||||
req_to_install,
|
||||
)
|
||||
|
||||
if req_to_install.editable:
|
||||
if req_to_install.source_dir is None:
|
||||
req_to_install.source_dir = req_to_install.build_location(
|
||||
self.src_dir
|
||||
)
|
||||
elif install_needed:
|
||||
req_to_install.source_dir = req_to_install.build_location(
|
||||
self.build_dir,
|
||||
)
|
||||
|
||||
if (req_to_install.source_dir is not None and not
|
||||
os.path.isdir(req_to_install.source_dir)):
|
||||
raise InstallationError(
|
||||
'Could not install requirement %s because source folder %s'
|
||||
' does not exist (perhaps --no-download was used without '
|
||||
'first running an equivalent install with --no-install?)' %
|
||||
(req_to_install, req_to_install.source_dir)
|
||||
)
|
||||
|
||||
def prepare_files(self, finder):
|
||||
"""
|
||||
Prepare process. Create temp directories, download and/or unpack files.
|
||||
|
|
|
@ -11,10 +11,6 @@ class PipDeprecationWarning(Warning):
|
|||
pass
|
||||
|
||||
|
||||
class RemovedInPip7Warning(PipDeprecationWarning, DeprecationWarning):
|
||||
pass
|
||||
|
||||
|
||||
class RemovedInPip8Warning(PipDeprecationWarning, PendingDeprecationWarning):
|
||||
pass
|
||||
|
||||
|
@ -23,7 +19,7 @@ class RemovedInPip9Warning(PipDeprecationWarning, PendingDeprecationWarning):
|
|||
pass
|
||||
|
||||
|
||||
DEPRECATIONS = [RemovedInPip7Warning, RemovedInPip8Warning, RemovedInPip9Warning]
|
||||
DEPRECATIONS = [RemovedInPip8Warning, RemovedInPip9Warning]
|
||||
|
||||
|
||||
# Warnings <-> Logging Integration
|
||||
|
|
|
@ -72,12 +72,11 @@ def setup_completion(script, words, cword):
|
|||
|
||||
def test_completion_for_un_snippet(script):
|
||||
"""
|
||||
Test getting completion for ``un`` should return
|
||||
uninstall and unzip
|
||||
Test getting completion for ``un`` should return uninstall
|
||||
"""
|
||||
|
||||
res, env = setup_completion(script, 'pip un', '1')
|
||||
assert res.stdout.strip().split() == ['uninstall', 'unzip'], res.stdout
|
||||
assert res.stdout.strip().split() == ['uninstall'], res.stdout
|
||||
|
||||
|
||||
def test_completion_for_default_parameters(script):
|
||||
|
|
|
@ -128,87 +128,6 @@ def test_download_editable_to_custom_path(script, tmpdir):
|
|||
assert customdl_files_created
|
||||
|
||||
|
||||
@pytest.mark.network
|
||||
def test_editable_no_install_followed_by_no_download(script, tmpdir):
|
||||
"""
|
||||
Test installing an editable in two steps (first with --no-install, then
|
||||
with --no-download).
|
||||
"""
|
||||
result = script.pip(
|
||||
'install',
|
||||
'-e',
|
||||
'%s#egg=initools-dev' %
|
||||
local_checkout(
|
||||
'svn+http://svn.colorstudy.com/INITools/trunk',
|
||||
tmpdir.join("cache"),
|
||||
),
|
||||
'--no-install',
|
||||
expect_error=True,
|
||||
)
|
||||
result.assert_installed(
|
||||
'INITools', without_egg_link=True, with_files=['.svn'],
|
||||
)
|
||||
|
||||
result = script.pip(
|
||||
'install',
|
||||
'-e',
|
||||
'%s#egg=initools-dev' %
|
||||
local_checkout(
|
||||
'svn+http://svn.colorstudy.com/INITools/trunk',
|
||||
tmpdir.join("cache"),
|
||||
),
|
||||
'--no-download',
|
||||
expect_error=True,
|
||||
)
|
||||
result.assert_installed('INITools', without_files=[curdir, '.svn'])
|
||||
|
||||
|
||||
def test_no_install_followed_by_no_download(script):
|
||||
"""
|
||||
Test installing in two steps (first with --no-install, then with
|
||||
--no-download).
|
||||
"""
|
||||
egg_info_folder = (
|
||||
script.site_packages / 'INITools-0.2-py%s.egg-info' % pyversion
|
||||
)
|
||||
initools_folder = script.site_packages / 'initools'
|
||||
build_dir = script.venv / 'build' / 'INITools'
|
||||
|
||||
result1 = script.pip_install_local(
|
||||
'INITools==0.2', '--no-install', expect_error=True,
|
||||
)
|
||||
assert egg_info_folder not in result1.files_created, str(result1)
|
||||
assert initools_folder not in result1.files_created, (
|
||||
sorted(result1.files_created)
|
||||
)
|
||||
assert build_dir in result1.files_created, result1.files_created
|
||||
assert build_dir / 'INITools.egg-info' in result1.files_created
|
||||
|
||||
result2 = script.pip_install_local(
|
||||
'INITools==0.2', '--no-download', expect_error=True,
|
||||
)
|
||||
assert egg_info_folder in result2.files_created, str(result2)
|
||||
assert initools_folder in result2.files_created, (
|
||||
sorted(result2.files_created)
|
||||
)
|
||||
assert build_dir not in result2.files_created
|
||||
assert build_dir / 'INITools.egg-info' not in result2.files_created
|
||||
|
||||
|
||||
def test_bad_install_with_no_download(script):
|
||||
"""
|
||||
Test that --no-download behaves sensibly if the package source can't be
|
||||
found.
|
||||
"""
|
||||
result = script.pip(
|
||||
'install', 'INITools==0.2', '--no-download', expect_error=True,
|
||||
)
|
||||
assert (
|
||||
"perhaps --no-download was used without first running "
|
||||
"an equivalent install with --no-install?" in result.stderr
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.network
|
||||
def test_install_dev_version_from_pypi(script):
|
||||
"""
|
||||
|
|
|
@ -4,7 +4,6 @@ import pytest
|
|||
from os.path import exists
|
||||
|
||||
from tests.lib.local_repos import local_checkout
|
||||
from tests.lib.path import Path
|
||||
from pip.locations import write_delete_marker_file
|
||||
from pip.status_codes import PREVIOUS_BUILD_DIR_ERROR
|
||||
|
||||
|
@ -72,27 +71,6 @@ def test_cleanup_after_install_from_local_directory(script, data):
|
|||
script.assert_no_temp()
|
||||
|
||||
|
||||
@pytest.mark.network
|
||||
def test_no_install_and_download_should_not_leave_build_dir(script):
|
||||
"""
|
||||
It should remove build/ dir if it was pip that created
|
||||
"""
|
||||
script.scratch_path.join("downloaded_packages").mkdir()
|
||||
assert not os.path.exists(script.venv_path / 'build')
|
||||
result = script.pip(
|
||||
'install', '--no-install', 'INITools==0.2', '-d',
|
||||
'downloaded_packages',
|
||||
expect_stderr=True,
|
||||
)
|
||||
assert (
|
||||
Path('scratch') / 'downloaded_packages/build'
|
||||
not in result.files_created
|
||||
), 'pip should not leave build/ dir'
|
||||
assert not os.path.exists(script.venv_path / 'build'), (
|
||||
"build/ dir should be deleted"
|
||||
)
|
||||
|
||||
|
||||
def test_cleanup_req_satisifed_no_name(script, data):
|
||||
"""
|
||||
Test cleanup when req is already satisfied, and req has no 'name'
|
||||
|
@ -113,28 +91,6 @@ def test_cleanup_req_satisifed_no_name(script, data):
|
|||
script.assert_no_temp()
|
||||
|
||||
|
||||
@pytest.mark.network
|
||||
def test_download_should_not_delete_existing_build_dir(script):
|
||||
"""
|
||||
It should not delete build/ if existing before run the command
|
||||
"""
|
||||
script.venv_path.join("build").mkdir()
|
||||
script.venv_path.join("build", "somefile.txt").write("I am not empty!")
|
||||
script.pip(
|
||||
'install', '--no-install', 'INITools==0.2', '-d', '.',
|
||||
expect_stderr=True,
|
||||
)
|
||||
with open(script.venv_path / 'build' / 'somefile.txt') as fp:
|
||||
content = fp.read()
|
||||
assert os.path.exists(script.venv_path / 'build'), (
|
||||
"build/ should be left if it exists before pip run"
|
||||
)
|
||||
assert content == 'I am not empty!', (
|
||||
"it should not affect build/ and its content"
|
||||
)
|
||||
assert ['somefile.txt'] == os.listdir(script.venv_path / 'build')
|
||||
|
||||
|
||||
def test_cleanup_after_install_exception(script, data):
|
||||
"""
|
||||
Test clean up after a 'setup.py install' exception.
|
||||
|
|
|
@ -85,7 +85,11 @@ def test_command_line_append_flags(script, virtualenv, data):
|
|||
|
||||
"""
|
||||
script.environ['PIP_FIND_LINKS'] = 'http://pypi.pinaxproject.com'
|
||||
result = script.pip('install', '-vvv', 'INITools', expect_error=True)
|
||||
result = script.pip(
|
||||
'install', '-vvv', 'INITools', '--trusted-host',
|
||||
'pypi.pinaxproject.com',
|
||||
expect_error=True,
|
||||
)
|
||||
assert (
|
||||
"Analyzing links from page http://pypi.pinaxproject.com"
|
||||
in result.stdout
|
||||
|
@ -93,6 +97,7 @@ def test_command_line_append_flags(script, virtualenv, data):
|
|||
virtualenv.clear()
|
||||
result = script.pip(
|
||||
'install', '-vvv', '--find-links', data.find_links, 'INITools',
|
||||
'--trusted-host', 'pypi.pinaxproject.com',
|
||||
expect_error=True,
|
||||
)
|
||||
assert (
|
||||
|
@ -111,7 +116,11 @@ def test_command_line_appends_correctly(script, data):
|
|||
script.environ['PIP_FIND_LINKS'] = (
|
||||
'http://pypi.pinaxproject.com %s' % data.find_links
|
||||
)
|
||||
result = script.pip('install', '-vvv', 'INITools', expect_error=True)
|
||||
result = script.pip(
|
||||
'install', '-vvv', 'INITools', '--trusted-host',
|
||||
'pypi.pinaxproject.com',
|
||||
expect_error=True,
|
||||
)
|
||||
|
||||
assert (
|
||||
"Analyzing links from page http://pypi.pinaxproject.com"
|
||||
|
|
|
@ -5,27 +5,6 @@ from pip.index import HTMLPage
|
|||
from pip.index import PackageFinder, Link, INSTALLED_VERSION
|
||||
|
||||
|
||||
def test_html_page_should_be_able_to_scrap_rel_links():
|
||||
"""
|
||||
Test scraping page looking for url in href
|
||||
"""
|
||||
page = HTMLPage(
|
||||
b"""
|
||||
<!-- The <th> elements below are a terrible terrible hack for setuptools -->
|
||||
<li>
|
||||
<strong>Home Page:</strong>
|
||||
<!-- <th>Home Page -->
|
||||
<a href="http://supervisord.org/">http://supervisord.org/</a>
|
||||
</li>
|
||||
""",
|
||||
"supervisor",
|
||||
)
|
||||
|
||||
links = list(page.scraped_rel_links())
|
||||
assert len(links) == 1
|
||||
assert links[0].url == 'http://supervisord.org/'
|
||||
|
||||
|
||||
def test_sort_locations_file_find_link(data):
|
||||
"""
|
||||
Test that a file:// find-link dir gets listdir run
|
||||
|
|
Loading…
Reference in New Issue