diff --git a/CHANGES.txt b/CHANGES.txt index cdeafb4f9ef..68eb7b9bc4c 100644 --- a/CHANGES.txt +++ b/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)** diff --git a/pip/cmdoptions.py b/pip/cmdoptions.py index 1611187420b..5e49f6795d5 100644 --- a/pip/cmdoptions.py +++ b/pip/cmdoptions.py @@ -213,23 +213,6 @@ def make(self): "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 @@ def make(self): extra_index_url, no_index, find_links, - use_mirrors, - mirrors, allow_external, allow_all_external, no_allow_external, diff --git a/pip/commands/__init__.py b/pip/commands/__init__.py index 93ab3807cd4..24bc27f8b11 100644 --- a/pip/commands/__init__.py +++ b/pip/commands/__init__.py @@ -11,8 +11,6 @@ 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 @@ 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 @@ ShowCommand, SearchCommand, WheelCommand, - ZipCommand, - UnzipCommand, HelpCommand, ] diff --git a/pip/commands/install.py b/pip/commands/install.py index ddaa4709ec9..8f69c0889c9 100644 --- a/pip/commands/install.py +++ b/pip/commands/install.py @@ -8,7 +8,7 @@ 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 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 @@ def __init__(self, *args, **kw): 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 @@ def _build_package_finder(self, options, index_urls, session): 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 @@ def run(self, options, args): 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 @@ def run(self, options, args): 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 @@ def run(self, options, args): 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: diff --git a/pip/commands/list.py b/pip/commands/list.py index e3443340196..dbc17b2f62d 100644 --- a/pip/commands/list.py +++ b/pip/commands/list.py @@ -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 @@ def find_packages_latest_versions(self, options): 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): diff --git a/pip/commands/unzip.py b/pip/commands/unzip.py deleted file mode 100644 index 83899888284..00000000000 --- a/pip/commands/unzip.py +++ /dev/null @@ -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.' diff --git a/pip/commands/wheel.py b/pip/commands/wheel.py index c3ef65eef22..2f848f81876 100644 --- a/pip/commands/wheel.py +++ b/pip/commands/wheel.py @@ -11,7 +11,7 @@ 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 @@ def run(self, options, args): 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 " diff --git a/pip/commands/zip.py b/pip/commands/zip.py deleted file mode 100644 index 078c5ffad6e..00000000000 --- a/pip/commands/zip.py +++ /dev/null @@ -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] ...""" - 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 diff --git a/pip/index.py b/pip/index.py index 6fcef25deab..d54edb335e1 100644 --- a/pip/index.py +++ b/pip/index.py @@ -16,7 +16,7 @@ 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 @@ def add_dependency_links(self, links): 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 @@ def _validate_secure_origin(self, logger, location): 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 + + # 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, + ) - 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, - ) + return False def _get_index_urls_locations(self, project_name): """Returns the locations found via self.index_urls @@ -362,11 +357,17 @@ def _find_all_versions(self, project_name): # 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 @@ def find_requirement(self, req, upgrade): "%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 @@ def _get_page(self, link): class HTMLPage(object): """Represents one page, along with its URL""" - # FIXME: these regexes are horrible hacks: - _homepage_re = re.compile(b'\\s*home\\s*page', re.I) - _download_re = re.compile(b'\\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 @@ def links(self): 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 @@ def explicit_rel_links(self, rels=('homepage', 'download')): ) 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 @@ def clean_link(self, url): 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 @@ def __init__(self, url, comes_from=None, internal=None, trusted=None, self.comes_from = comes_from self.internal = internal self.trusted = trusted - self._deprecated_regex = _deprecated_regex def __str__(self): if self.comes_from: diff --git a/pip/locations.py b/pip/locations.py index dfbc6da2791..c1722cbba50 100644 --- a/pip/locations.py +++ b/pip/locations.py @@ -6,18 +6,12 @@ import os.path import site import sys -import tempfile from distutils import sysconfig -from distutils.command.install import install, SCHEME_KEYS +from distutils.command.install import install, SCHEME_KEYS # noqa -from pip.compat import get_path_uid, WINDOWS +from pip.compat import WINDOWS from pip.utils import appdirs -from pip import exceptions - - -# Hack for flake8 -install # CA Bundle Locations @@ -108,48 +102,9 @@ def __get_username(): return pwd.getpwuid(os.geteuid()).pw_name -def _get_build_prefix(): - """ Returns a safe build_prefix """ - path = os.path.join( - tempfile.gettempdir(), - 'pip_build_%s' % __get_username().replace(' ', '_') - ) - if WINDOWS: - """ on windows(tested on 7) temp dirs are isolated """ - return path - try: - os.mkdir(path) - write_delete_marker_file(path) - except OSError: - file_uid = None - try: - # raises OSError for symlinks - # https://github.com/pypa/pip/pull/935#discussion_r5307003 - file_uid = get_path_uid(path) - except OSError: - file_uid = None - - if file_uid != os.geteuid(): - msg = ( - "The temporary folder for building (%s) is either not owned by" - " you, or is a symlink." % path - ) - print(msg) - print( - "pip will not work until the temporary folder is either " - "deleted or is a real directory owned by your user account." - ) - raise exceptions.InstallationError(msg) - return path - if running_under_virtualenv(): - build_prefix = os.path.join(sys.prefix, 'build') src_prefix = os.path.join(sys.prefix, 'src') else: - # Note: intentionally NOT using mkdtemp - # See https://github.com/pypa/pip/issues/906 for plan to move to mkdtemp - build_prefix = _get_build_prefix() - # FIXME: keep src in cwd for now (it is not a temporary folder) try: src_prefix = os.path.join(os.getcwd(), 'src') @@ -162,7 +117,6 @@ def _get_build_prefix(): # under Mac OS X + virtualenv sys.prefix is not properly resolved # it is something like /path/to/python/bin/.. # Note: using realpath due to tmp dirs on OSX being symlinks -build_prefix = os.path.abspath(os.path.realpath(build_prefix)) src_prefix = os.path.abspath(src_prefix) # FIXME doesn't account for venv linked to global site-packages diff --git a/pip/req/req_set.py b/pip/req/req_set.py index 1e395582011..ef788b3b796 100644 --- a/pip/req/req_set.py +++ b/pip/req/req_set.py @@ -13,9 +13,8 @@ from pip.download import (url_to_path, unpack_url) from pip.exceptions import (InstallationError, BestVersionAlreadyInstalled, DistributionNotFound, PreviousBuildDirError) -from pip.locations import (PIP_DELETE_MARKER_FILENAME, build_prefix) from pip.req.req_install import InstallRequirement -from pip.utils import (display_path, rmtree, dist_in_usersite, normalize_path) +from pip.utils import display_path, dist_in_usersite, normalize_path from pip.utils.logging import indent_log from pip.vcs import vcs @@ -309,52 +308,6 @@ def _walk_req_to_install(self, handler): 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. @@ -604,18 +557,6 @@ def cleanup_files(self): for req in self.reqs_to_cleanup: req.remove_temporary_source() - if self._pip_has_created_build_dir(): - logger.debug('Removing temporary dir %s...', self.build_dir) - rmtree(self.build_dir) - - def _pip_has_created_build_dir(self): - return ( - self.build_dir == build_prefix and - os.path.exists( - os.path.join(self.build_dir, PIP_DELETE_MARKER_FILENAME) - ) - ) - def _to_install(self): """Create the installation order. diff --git a/pip/utils/deprecation.py b/pip/utils/deprecation.py index 1852471a732..bac00ece73e 100644 --- a/pip/utils/deprecation.py +++ b/pip/utils/deprecation.py @@ -11,15 +11,15 @@ class PipDeprecationWarning(Warning): pass -class RemovedInPip7Warning(PipDeprecationWarning, DeprecationWarning): +class RemovedInPip8Warning(PipDeprecationWarning, PendingDeprecationWarning): pass -class RemovedInPip8Warning(PipDeprecationWarning, PendingDeprecationWarning): +class RemovedInPip9Warning(PipDeprecationWarning, PendingDeprecationWarning): pass -DEPRECATIONS = [RemovedInPip7Warning, RemovedInPip8Warning] +DEPRECATIONS = [RemovedInPip8Warning, RemovedInPip9Warning] # Warnings <-> Logging Integration diff --git a/tests/functional/test_completion.py b/tests/functional/test_completion.py index f224093602d..5680f9f02bc 100644 --- a/tests/functional/test_completion.py +++ b/tests/functional/test_completion.py @@ -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): diff --git a/tests/functional/test_install.py b/tests/functional/test_install.py index 2e9ecacc188..cc3c2090573 100644 --- a/tests/functional/test_install.py +++ b/tests/functional/test_install.py @@ -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): """ diff --git a/tests/functional/test_install_cleanup.py b/tests/functional/test_install_cleanup.py index 41d9e7956ac..49fc5a0abe5 100644 --- a/tests/functional/test_install_cleanup.py +++ b/tests/functional/test_install_cleanup.py @@ -4,7 +4,6 @@ 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. diff --git a/tests/functional/test_install_config.py b/tests/functional/test_install_config.py index 39bce1bcd0d..af8b81dbbce 100644 --- a/tests/functional/test_install_config.py +++ b/tests/functional/test_install_config.py @@ -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" diff --git a/tests/unit/test_index.py b/tests/unit/test_index.py index f170d2c08d1..0e00ed15595 100644 --- a/tests/unit/test_index.py +++ b/tests/unit/test_index.py @@ -5,27 +5,6 @@ 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""" - -
  • -Home Page: - -http://supervisord.org/ -
  • - """, - "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 diff --git a/tests/unit/test_locations.py b/tests/unit/test_locations.py index 7e84844a163..12a2a6f457f 100644 --- a/tests/unit/test_locations.py +++ b/tests/unit/test_locations.py @@ -8,10 +8,7 @@ import tempfile import getpass -import pytest - from mock import Mock -import pip from pip.locations import distutils_scheme @@ -77,86 +74,6 @@ def get_mock_getpwuid(self, uid): result.pw_name = self.username return result - def get_build_dir_location(self): - """ returns a string pointing to the - current build_prefix. - """ - return os.path.join(self.tempdir, 'pip_build_%s' % self.username) - - def test_dir_path(self): - """ test the path name for the build_prefix - """ - from pip import locations - assert locations._get_build_prefix() == self.get_build_dir_location() - - # skip on windows, build dir is not created - @pytest.mark.skipif("sys.platform == 'win32'") - @pytest.mark.skipif("not hasattr(os, 'O_NOFOLLOW')") - def test_dir_created(self): - """ test that the build_prefix directory is generated when - _get_build_prefix is called. - """ - assert not os.path.exists(self.get_build_dir_location()), \ - "the build_prefix directory should not exist yet!" - from pip import locations - locations._get_build_prefix() - assert os.path.exists(self.get_build_dir_location()), \ - "the build_prefix directory should now exist!" - - # skip on windows, build dir is not created - @pytest.mark.skipif("sys.platform == 'win32'") - def test_dir_created_without_NOFOLLOW(self, monkeypatch): - """ test that the build_prefix directory is generated when - os.O_NOFOLLOW doen't exist - """ - if hasattr(os, 'O_NOFOLLOW'): - monkeypatch.delattr("os.O_NOFOLLOW") - assert not os.path.exists(self.get_build_dir_location()), \ - "the build_prefix directory should not exist yet!" - from pip import locations - locations._get_build_prefix() - assert os.path.exists(self.get_build_dir_location()), \ - "the build_prefix directory should now exist!" - - # skip on windows; this exception logic only runs on linux - @pytest.mark.skipif("sys.platform == 'win32'") - @pytest.mark.skipif("not hasattr(os, 'O_NOFOLLOW')") - def test_error_raised_when_owned_by_another(self): - """ test calling _get_build_prefix when there is a temporary - directory owned by another user raises an InstallationError. - """ - from pip import locations - os.geteuid = lambda: 1111 - os.mkdir(self.get_build_dir_location()) - - with pytest.raises(pip.exceptions.InstallationError): - locations._get_build_prefix() - - # skip on windows; this exception logic only runs on linux - @pytest.mark.skipif("sys.platform == 'win32'") - def test_error_raised_when_owned_by_another_without_NOFOLLOW( - self, monkeypatch): - """ test calling _get_build_prefix when there is a temporary - directory owned by another user raises an InstallationError. - (when os.O_NOFOLLOW doesn't exist - """ - if hasattr(os, 'O_NOFOLLOW'): - monkeypatch.delattr("os.O_NOFOLLOW") - from pip import locations - os.geteuid = lambda: 1111 - os.mkdir(self.get_build_dir_location()) - - with pytest.raises(pip.exceptions.InstallationError): - locations._get_build_prefix() - - def test_no_error_raised_when_owned_by_you(self): - """ test calling _get_build_prefix when there is a temporary - directory owned by you raise no InstallationError. - """ - from pip import locations - os.mkdir(self.get_build_dir_location()) - locations._get_build_prefix() - class TestDisutilsScheme: