def _copy_dist_from_dir(link_path, location): """Copy distribution files in `link_path` to `location`. Invoked when user requests to install a local directory. E.g.: pip install . pip install ~/dev/git-repos/python-prompt-toolkit """ # Note: This is currently VERY SLOW if you have a lot of data in the # directory, because it copies everything with `shutil.copytree`. # What it should really do is build an sdist and install that. # See https://github.com/pypa/pip/issues/2195 if os.path.isdir(location): rmtree(location) # build an sdist setup_py = 'setup.py' sdist_args = [sys.executable] sdist_args.append('-c') sdist_args.append( "import setuptools, tokenize;__file__=%r;" "exec(compile(getattr(tokenize, 'open', open)(__file__).read()" ".replace('\\r\\n', '\\n'), __file__, 'exec'))" % setup_py)
def _copy_dist_from_dir(link_path, location): """Copy distribution files in `link_path` to `location`. Invoked when user requests to install a local directory. E.g.: pip install . pip install ~/dev/git-repos/python-prompt-toolkit """ # Note: This is currently VERY SLOW if you have a lot of data in the # directory, because it copies everything with `shutil.copytree`. # What it should really do is build an sdist and install that. # See https://github.com/pypa/pip/issues/2195 if os.path.isdir(location): rmtree(location) # build an sdist setup_py = 'setup.py' sdist_args = [sys.executable] sdist_args.append('-c') sdist_args.append(SETUPTOOLS_SHIM % setup_py) sdist_args.append('sdist') sdist_args += ['--dist-dir', location] logger.info('Running setup.py sdist for %s', link_path) with indent_log(): call_subprocess(sdist_args, cwd=link_path, show_stdout=False) # unpack sdist into `location` sdist = os.path.join(location, os.listdir(location)[0]) logger.info('Unpacking sdist %s into %s', sdist, location) unpack_file(sdist, location, content_type=None, link=None)
def unpack_http_url(link, location, download_dir=None, session=None): if session is None: raise TypeError( "unpack_http_url() missing 1 required keyword argument: 'session'" ) temp_dir = tempfile.mkdtemp('-unpack', 'pip-') # If a download dir is specified, is the file already downloaded there? already_downloaded_path = None if download_dir: already_downloaded_path = _check_download_dir(link, download_dir) if already_downloaded_path: from_path = already_downloaded_path content_type = mimetypes.guess_type(from_path)[0] else: # let's download to a tmp dir from_path, content_type = _download_http_url(link, session, temp_dir) # unpack the archive to the build dir location. even when only downloading # archives, they have to be unpacked to parse dependencies unpack_file(from_path, location, content_type, link) # a download dir is specified; let's copy the archive there if download_dir and not already_downloaded_path: _copy_file(from_path, download_dir, content_type, link) if not already_downloaded_path: os.unlink(from_path) rmtree(temp_dir)
def _test_packages(output, pending_fn): package = get_last_item(pending_fn) print("Testing package %s" % package) dest_dir = os.path.join(output, package) print("Creating virtualenv in %s" % dest_dir) create_venv(dest_dir) print("Uninstalling actual pip") code = subprocess.check_call([os.path.join(dest_dir, bin_dir, "pip"), "uninstall", "-y", "pip"]) assert not code, "pip uninstallation failed" print("Installing development pip") code = subprocess.check_call([os.path.join(dest_dir, bin_dir, "python"), "setup.py", "install"], cwd=src_folder) assert not code, "pip installation failed" print("Trying installation of %s" % dest_dir) code = subprocess.check_call([os.path.join(dest_dir, bin_dir, "pip"), "install", package]) if code: print("Installation of %s failed" % package) print("Now checking easy_install...") create_venv(dest_dir) code = subprocess.check_call([os.path.join(dest_dir, bin_dir, "easy_install"), package]) if code: print("easy_install also failed") add_package(os.path.join(output, "easy-failure.txt"), package) else: print("easy_install succeeded") add_package(os.path.join(output, "failure.txt"), package) pop_last_item(pending_fn, package) else: print("Installation of %s succeeded" % package) add_package(os.path.join(output, "success.txt"), package) pop_last_item(pending_fn, package) rmtree(dest_dir)
def test_rmtree_retries_for_3sec(tmpdir, monkeypatch): """ Test pip.utils.rmtree will retry failures for no more than 3 sec """ monkeypatch.setattr(shutil, 'rmtree', Failer(duration=5).call) with pytest.raises(OSError): rmtree('foo')
def unpack(self, location): """ Clean up current location and download the url repository (and vcs infos) into location """ if os.path.exists(location): rmtree(location) self.obtain(location)
def remove_temporary_source(self): """Remove the source files from this requirement, if they are marked for deletion""" if self.source_dir and os.path.exists( os.path.join(self.source_dir, PIP_DELETE_MARKER_FILENAME)): logger.debug('Removing source in %s', self.source_dir) rmtree(self.source_dir) self.source_dir = None self._temp_build_dir.cleanup()
def export(self, location): """Export the Hg repository at the url to the destination location""" temp_dir = tempfile.mkdtemp('-export', 'pip-') self.unpack(temp_dir) try: self.run_command( ['archive', location], show_stdout=False, cwd=temp_dir) finally: rmtree(temp_dir)
def export(self, location): """ Export the Bazaar repository at the url to the destination location """ temp_dir = tempfile.mkdtemp('-export', 'pip-') self.unpack(temp_dir) if os.path.exists(location): # Remove the location to make sure Bazaar can export it correctly rmtree(location) try:
def export(self, location): """Export the Hg repository at the url to the destination location""" temp_dir = tempfile.mkdtemp('-export', 'pip-') self.unpack(temp_dir) try: call_subprocess( [self.cmd, 'archive', location], filter_stdout=self._filter, show_stdout=False, cwd=temp_dir) finally: rmtree(temp_dir)
def cleanup_files(self): """Clean up files, remove builds.""" logger.debug('Cleaning up...') with indent_log(): 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 create_venv(dest_dir): if os.path.exists(dest_dir): rmtree(dest_dir) print('Creating virtualenv in %s' % dest_dir) code = subprocess.check_call([ 'virtualenv', '--no-site-packages', dest_dir, ]) assert not code, "virtualenv failed"
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 export(self, location): """Export the svn repository at the url to the destination location""" url, rev = self.get_url_rev() rev_options = get_rev_options(url, rev) logger.info("Exporting svn repository %s to %s", url, location) with indent_log(): if os.path.exists(location): # Subversion doesn't like to check out over an existing # directory --force fixes this, but was only added in svn 1.5 rmtree(location) self.run_command(["export"] + rev_options + [url, location], show_stdout=False)
def export(self, location): """Export the Git repository at the url to the destination location""" temp_dir = tempfile.mkdtemp('-export', 'pip-') self.unpack(temp_dir) try: if not location.endswith('/'): location = location + '/' self.run_command( ['checkout-index', '-a', '-f', '--prefix', location], show_stdout=False, cwd=temp_dir) finally: rmtree(temp_dir)
def export(self, location): """Export the Git repository at the url to the destination location""" temp_dir = tempfile.mkdtemp('-export', 'pip-') self.unpack(temp_dir) try: if not location.endswith('/'): location = location + '/' call_subprocess( [self.cmd, 'checkout-index', '-a', '-f', '--prefix', location], filter_stdout=self._filter, show_stdout=False, cwd=temp_dir) finally: rmtree(temp_dir)
def export(self, location): """Export the svn repository at the url to the destination location""" url, rev = self.get_url_rev() rev_options = get_rev_options(url, rev) logger.info('Exporting svn repository %s to %s', url, location) with indent_log(): if os.path.exists(location): # Subversion doesn't like to check out over an existing # directory --force fixes this, but was only added in svn 1.5 rmtree(location) call_subprocess( [self.cmd, 'export'] + rev_options + [url, location], filter_stdout=self._filter, show_stdout=False)
def export(self, location): """ Export the Bazaar repository at the url to the destination location """ temp_dir = tempfile.mkdtemp("-export", "pip-") self.unpack(temp_dir) if os.path.exists(location): # Remove the location to make sure Bazaar can export it correctly rmtree(location) try: self.run_command(["export", location], cwd=temp_dir, show_stdout=False) finally: rmtree(temp_dir)
def export(self, location): """ Export the Bazaar repository at the url to the destination location """ temp_dir = tempfile.mkdtemp('-export', 'pip-') self.unpack(temp_dir) if os.path.exists(location): # Remove the location to make sure Bazaar can export it correctly rmtree(location) try: call_subprocess([self.cmd, 'export', location], cwd=temp_dir, filter_stdout=self._filter, show_stdout=False) finally: rmtree(temp_dir)
def _test_packages(output, pending_fn): package = get_last_item(pending_fn) print('Testing package %s' % package) dest_dir = os.path.join(output, package) print('Creating virtualenv in %s' % dest_dir) create_venv(dest_dir) print('Uninstalling actual pip') code = subprocess.check_call([ os.path.join(dest_dir, bin_dir, 'pip'), 'uninstall', '-y', 'pip', ]) assert not code, 'pip uninstallation failed' print('Installing development pip') code = subprocess.check_call( [ os.path.join(dest_dir, bin_dir, 'python'), 'setup.py', 'install' ], cwd=src_folder, ) assert not code, 'pip installation failed' print('Trying installation of %s' % dest_dir) code = subprocess.check_call([ os.path.join(dest_dir, bin_dir, 'pip'), 'install', package, ]) if code: print('Installation of %s failed' % package) print('Now checking easy_install...') create_venv(dest_dir) code = subprocess.check_call([ os.path.join(dest_dir, bin_dir, 'easy_install'), package, ]) if code: print('easy_install also failed') add_package(os.path.join(output, 'easy-failure.txt'), package) else: print('easy_install succeeded') add_package(os.path.join(output, 'failure.txt'), package) pop_last_item(pending_fn, package) else: print('Installation of %s succeeded' % package) add_package(os.path.join(output, 'success.txt'), package) pop_last_item(pending_fn, package) rmtree(dest_dir)
def export(self, location): """ Export the Bazaar repository at the url to the destination location """ # Remove the location to make sure Bazaar can export it correctly if os.path.exists(location): rmtree(location) with TempDirectory(kind="export") as temp_dir: self.unpack(temp_dir.path) self.run_command( ['export', location], cwd=temp_dir.path, show_stdout=False, )
def test_install_curdir(script, data): """ Test installing current directory ('.'). """ run_from = data.packages.join("FSPkg") # Python 2.4 Windows balks if this exists already egg_info = join(run_from, "FSPkg.egg-info") if os.path.isdir(egg_info): rmtree(egg_info) result = script.pip('install', curdir, cwd=run_from, expect_error=False) fspkg_folder = script.site_packages / 'fspkg' egg_info_folder = ( script.site_packages / 'FSPkg-0.1.dev0-py%s.egg-info' % pyversion ) assert fspkg_folder in result.files_created, str(result.stdout) assert egg_info_folder in result.files_created, str(result)
def check_destination(self, dest, url, rev_options, rev_display): """ Prepare a location to receive a checkout/clone. Return True if the location is ready for (and requires) a checkout/clone, False otherwise. """ checkout = True prompt = False if os.path.exists(dest): checkout = False if os.path.exists(os.path.join(dest, self.dirname)): existing_url = self.get_url(dest) if self.compare_urls(existing_url, url): logger.debug( "%s in %s exists, and has correct URL (%s)", self.repo_name.title(), display_path(dest), url ) logger.info("Updating %s %s%s", display_path(dest), self.repo_name, rev_display) self.update(dest, rev_options) else: logger.warning( "%s %s in %s exists with URL %s", self.name, self.repo_name, display_path(dest), existing_url ) prompt = ("(s)witch, (i)gnore, (w)ipe, (b)ackup ", ("s", "i", "w", "b")) else: logger.warning("Directory %s already exists, and is not a %s %s.", dest, self.name, self.repo_name) prompt = ("(i)gnore, (w)ipe, (b)ackup ", ("i", "w", "b")) if prompt: logger.warning("The plan is to install the %s repository %s", self.name, url) response = ask_path_exists("What to do? %s" % prompt[0], prompt[1]) if response == "s": logger.info("Switching %s %s to %s%s", self.repo_name, display_path(dest), url, rev_display) self.switch(dest, url, rev_options) elif response == "i": # do nothing pass elif response == "w": logger.warning("Deleting %s", display_path(dest)) rmtree(dest) checkout = True elif response == "b": dest_dir = backup_dir(dest) logger.warning("Backing up %s to %s", display_path(dest), dest_dir) shutil.move(dest, dest_dir) checkout = True return checkout
def unpack_file_url(link, location, download_dir=None, hashes=None): """Unpack link into location. If download_dir is provided and link points to a file, make a copy of the link file inside download_dir. """ link_path = url_to_path(link.url_without_fragment) # If it's a url to a local directory if is_dir_url(link): if os.path.isdir(location): rmtree(location) shutil.copytree(link_path, location, symlinks=True) if download_dir: logger.info('Link is a directory, ignoring download_dir') return # If --require-hashes is off, `hashes` is either empty, the # link's embedded hash, or MissingHashes; it is required to # match. If --require-hashes is on, we are satisfied by any # hash in `hashes` matching: a URL-based or an option-based # one; no internet-sourced hash will be in `hashes`. if hashes: hashes.check_against_path(link_path) # If a download dir is specified, is the file already there and valid? already_downloaded_path = None if download_dir: already_downloaded_path = _check_download_dir(link, download_dir, hashes) if already_downloaded_path: from_path = already_downloaded_path else: from_path = link_path content_type = mimetypes.guess_type(from_path)[0] # unpack the archive to the build dir location. even when only downloading # archives, they have to be unpacked to parse dependencies unpack_file(from_path, location, content_type, link) # a download dir is specified and not already downloaded if download_dir and not already_downloaded_path: _copy_file(from_path, download_dir, link)
def test_uninstall_editable_with_source_outside_venv(script, tmpdir): """ Test uninstalling editable install from existing source outside the venv. """ cache_dir = tmpdir.join("cache") try: temp = mkdtemp() tmpdir = join(temp, 'pip-test-package') _test_uninstall_editable_with_source_outside_venv( script, tmpdir, cache_dir, ) finally: rmtree(temp)
def unpack_file_url(link, location, download_dir=None): """Unpack link into location. If download_dir is provided and link points to a file, make a copy of the link file inside download_dir.""" link_path = url_to_path(link.url_without_fragment) # If it's a url to a local directory if os.path.isdir(link_path): if os.path.isdir(location): rmtree(location) shutil.copytree( link_path, location, symlinks=True, ignore=shutil.ignore_patterns( '.tox', '.git', '.hg', '.bzr', '.svn')) if download_dir: logger.info('Link is a directory, ignoring download_dir') return # if link has a hash, let's confirm it matches if link.hash: link_path_hash = _get_hash_from_file(link_path, link) _check_hash(link_path_hash, link) # If a download dir is specified, is the file already there and valid? already_downloaded_path = None if download_dir: already_downloaded_path = _check_download_dir(link, download_dir) if already_downloaded_path: from_path = already_downloaded_path else: from_path = link_path content_type = mimetypes.guess_type(from_path)[0] # unpack the archive to the build dir location. even when only downloading # archives, they have to be unpacked to parse dependencies unpack_file(from_path, location, content_type, link) # a download dir is specified and not already downloaded if download_dir and not already_downloaded_path: _copy_file(from_path, download_dir, content_type, link)
def _build_one(self, req, output_dir): """Build one wheel. :return: The filename of the built wheel, or None if the build failed. """ tempd = tempfile.mkdtemp('pip-wheel-') try: if self.__build_one(req, tempd): try: wheel_name = os.listdir(tempd)[0] wheel_path = os.path.join(output_dir, wheel_name) shutil.move(os.path.join(tempd, wheel_name), wheel_path) logger.info('Stored in directory: %s', output_dir) return wheel_path except: return None return None finally: rmtree(tempd)
def _build_one(self, req, output_dir, python_tag=None): """Build one wheel. :return: The filename of the built wheel, or None if the build failed. """ tempd = tempfile.mkdtemp('pip-wheel-') try: if self.__build_one(req, tempd, python_tag=python_tag): try: wheel_name = os.listdir(tempd)[0] wheel_path = os.path.join(output_dir, wheel_name) shutil.move(os.path.join(tempd, wheel_name), wheel_path) logger.info('Stored in directory: %s', output_dir) return wheel_path except: pass # Ignore return, we can't do anything else useful. self._clean_one(req) return None finally: rmtree(tempd)
def unpack_file_url(link, location, download_dir=None): """Unpack link into location. If download_dir is provided and link points to a file, make a copy of the link file inside download_dir.""" link_path = url_to_path(link.url_without_fragment) # If it's a url to a local directory if os.path.isdir(link_path): if os.path.isdir(location): rmtree(location) shutil.copytree(link_path, location, symlinks=True) if download_dir: logger.info('Link is a directory, ignoring download_dir') return # if link has a hash, let's confirm it matches if link.hash: link_path_hash = _get_hash_from_file(link_path, link) _check_hash(link_path_hash, link) # If a download dir is specified, is the file already there and valid? already_downloaded_path = None if download_dir: already_downloaded_path = _check_download_dir(link, download_dir) if already_downloaded_path: from_path = already_downloaded_path else: from_path = link_path content_type = mimetypes.guess_type(from_path)[0] # unpack the archive to the build dir location. even when only downloading # archives, they have to be unpacked to parse dependencies unpack_file(from_path, location, content_type, link) # a download dir is specified and not already downloaded if download_dir and not already_downloaded_path: _copy_file(from_path, download_dir, content_type, link)
def _copy_dist_from_dir(link_path, location): """Copy distribution files in `link_path` to `location`. Invoked when user requests to install a local directory. E.g.: pip install . pip install ~/dev/git-repos/python-prompt-toolkit """ # Note: This is currently VERY SLOW if you have a lot of data in the # directory, because it copies everything with `shutil.copytree`. # What it should really do is build an sdist and install that. # See https://github.com/pypa/pip/issues/2195 if os.path.isdir(location): rmtree(location) # build an sdist setup_py = 'setup.py' sdist_args = [sys.executable] sdist_args.append('-c') sdist_args.append( "import setuptools, tokenize;__file__=%r;" "exec(compile(getattr(tokenize, 'open', open)(__file__).read()" ".replace('\\r\\n', '\\n'), __file__, 'exec'))" % setup_py) sdist_args.append('sdist') sdist_args += ['--dist-dir', location] logger.info('Running setup.py sdist for %s', link_path) with indent_log(): call_subprocess(sdist_args, cwd=link_path, show_stdout=False) # unpack sdist into `location` sdist = os.path.join(location, os.listdir(location)[0]) logger.info('Unpacking sdist %s into %s', sdist, location) unpack_file(sdist, location, content_type=None, link=None)
def unpack_http_url(link, location, download_dir=None, session=None, hashes=None, progress_bar="on"): if session is None: raise TypeError( "unpack_http_url() missing 1 required keyword argument: 'session'") temp_dir = tempfile.mkdtemp('-unpack', 'pip-') # If a download dir is specified, is the file already downloaded there? already_downloaded_path = None if download_dir: already_downloaded_path = _check_download_dir(link, download_dir, hashes) if already_downloaded_path: from_path = already_downloaded_path content_type = mimetypes.guess_type(from_path)[0] else: # let's download to a tmp dir from_path, content_type = _download_http_url(link, session, temp_dir, hashes, progress_bar) # unpack the archive to the build dir location. even when only downloading # archives, they have to be unpacked to parse dependencies unpack_file(from_path, location, content_type, link) # a download dir is specified; let's copy the archive there if download_dir and not already_downloaded_path: _copy_file(from_path, download_dir, link) if not already_downloaded_path: os.unlink(from_path) rmtree(temp_dir)
def install(self, install_options, global_options=[], root=None, prefix=None): if self.editable: self.install_editable(install_options, global_options, prefix=prefix) return if self.is_wheel: version = pip.wheel.wheel_version(self.source_dir) pip.wheel.check_compatibility(version, self.name) self.move_wheel_files(self.source_dir, root=root, prefix=prefix) self.install_succeeded = True return # Extend the list of global and install options passed on to # the setup.py call with the ones from the requirements file. # Options specified in requirements file override those # specified on the command line, since the last option given # to setup.py is the one that is used. global_options += self.options.get('global_options', []) install_options += self.options.get('install_options', []) if self.isolated: global_options = list(global_options) + ["--no-user-cfg"] temp_location = tempfile.mkdtemp('-record', 'pip-') record_filename = os.path.join(temp_location, 'install-record.txt') try: install_args = self.get_install_args(global_options, record_filename, root, prefix) msg = 'Running setup.py install for %s' % (self.name, ) with open_spinner(msg) as spinner: with indent_log(): call_subprocess( install_args + install_options, cwd=self.setup_py_dir, show_stdout=False, spinner=spinner, ) if not os.path.exists(record_filename): logger.debug('Record file %s not found', record_filename) return self.install_succeeded = True def prepend_root(path): if root is None or not os.path.isabs(path): return path else: return change_root(root, path) with open(record_filename) as f: for line in f: directory = os.path.dirname(line) if directory.endswith('.egg-info'): egg_info_dir = prepend_root(directory) break else: logger.warning( 'Could not find .egg-info directory in install record' ' for %s', self, ) # FIXME: put the record somewhere # FIXME: should this be an error? return new_lines = [] with open(record_filename) as f: for line in f: filename = line.strip() if os.path.isdir(filename): filename += os.path.sep new_lines.append( os.path.relpath(prepend_root(filename), egg_info_dir)) inst_files_path = os.path.join(egg_info_dir, 'installed-files.txt') with open(inst_files_path, 'w') as f: f.write('\n'.join(new_lines) + '\n') finally: if os.path.exists(record_filename): os.remove(record_filename) rmtree(temp_location)
"""Export the Git repository at the url to the destination location""" temp_dir = tempfile.mkdtemp('-export', 'pip-') self.unpack(temp_dir) try: if not location.endswith('/'): location = location + '/' <<<<<<< HEAD self.run_command( ['checkout-index', '-a', '-f', '--prefix', location], ======= call_subprocess( [self.cmd, 'checkout-index', '-a', '-f', '--prefix', location], >>>>>>> bde4533e29dfedadf6bcf9d451baa615bc828a59 filter_stdout=self._filter, show_stdout=False, cwd=temp_dir) finally: rmtree(temp_dir) def check_rev_options(self, rev, dest, rev_options): """Check the revision options before checkout to compensate that tags and branches may need origin/ as a prefix. Returns the SHA1 of the branch or tag if found. """ revisions = self.get_refs(dest) origin_rev = 'origin/%s' % rev if origin_rev in revisions: # remote branch return [revisions[origin_rev]] elif rev in revisions: # a local tag or branch name return [revisions[rev]]
def commit(self): """Remove temporary save dir: rollback will no longer be possible.""" if self.save_dir is not None: rmtree(self.save_dir) self.save_dir = None self._moved_paths = []
def run_egg_info(self): assert self.source_dir if self.name: logger.debug( 'Running setup.py (path:%s) egg_info for package %s', self.setup_py, self.name, ) else: logger.debug( 'Running setup.py (path:%s) egg_info for package from %s', self.setup_py, self.link, ) with indent_log(): # if it's distribute>=0.7, it won't contain an importable # setuptools, and having an egg-info dir blocks the ability of # setup.py to find setuptools plugins, so delete the egg-info dir # if no setuptools. it will get recreated by the run of egg_info # NOTE: this self.name check only works when installing from a # specifier (not archive path/urls) # TODO: take this out later if (self.name == 'distribute' and not os.path.isdir( os.path.join(self.source_dir, 'setuptools'))): rmtree(os.path.join(self.source_dir, 'distribute.egg-info')) script = self._run_setup_py script = script.replace('__SETUP_PY__', repr(self.setup_py)) script = script.replace('__PKG_NAME__', repr(self.name)) base_cmd = [sys.executable, '-c', script] if self.isolated: base_cmd += ["--no-user-cfg"] egg_info_cmd = base_cmd + ['egg_info'] # We can't put the .egg-info files at the root, because then the # source code will be mistaken for an installed egg, causing # problems if self.editable: egg_base_option = [] else: egg_info_dir = os.path.join(self.source_dir, 'pip-egg-info') if not os.path.exists(egg_info_dir): os.makedirs(egg_info_dir) egg_base_option = ['--egg-base', 'pip-egg-info'] cwd = self.source_dir if self.editable_options and \ 'subdirectory' in self.editable_options: cwd = os.path.join(cwd, self.editable_options['subdirectory']) call_subprocess( egg_info_cmd + egg_base_option, cwd=cwd, filter_stdout=_filter_install, show_stdout=False, command_level=logging.DEBUG, command_desc='python setup.py egg_info') if not self.req: if isinstance( pkg_resources.parse_version(self.pkg_info()["Version"]), Version): op = "==" else: op = "===" self.req = pkg_resources.Requirement.parse( "".join([ self.pkg_info()["Name"], op, self.pkg_info()["Version"], ])) self._correct_build_location()
def install(self, install_options, global_options=[], root=None, prefix=None): if self.editable: self.install_editable(install_options, global_options, prefix=prefix) return if self.is_wheel: version = pip.wheel.wheel_version(self.source_dir) pip.wheel.check_compatibility(version, self.name) self.move_wheel_files(self.source_dir, root=root, prefix=prefix) self.install_succeeded = True return # Extend the list of global and install options passed on to # the setup.py call with the ones from the requirements file. # Options specified in requirements file override those # specified on the command line, since the last option given # to setup.py is the one that is used. global_options += self.options.get('global_options', []) install_options += self.options.get('install_options', []) if self.isolated: global_options = list(global_options) + ["--no-user-cfg"] temp_location = tempfile.mkdtemp('-record', 'pip-') record_filename = os.path.join(temp_location, 'install-record.txt') try: install_args = [sys.executable, "-u"] install_args.append('-c') install_args.append(SETUPTOOLS_SHIM % self.setup_py) install_args += list(global_options) + \ ['install', '--record', record_filename] if not self.as_egg: install_args += ['--single-version-externally-managed'] if root is not None: install_args += ['--root', root] if prefix is not None: install_args += ['--prefix', prefix] if self.pycompile: install_args += ["--compile"] else: install_args += ["--no-compile"] if running_under_virtualenv(): py_ver_str = 'python' + sysconfig.get_python_version() install_args += [ '--install-headers', os.path.join(sys.prefix, 'include', 'site', py_ver_str, self.name) ] msg = 'Running setup.py install for %s' % (self.name, ) with open_spinner(msg) as spinner: with indent_log(): call_subprocess( install_args + install_options, cwd=self.source_dir, show_stdout=False, spinner=spinner, ) if not os.path.exists(record_filename): logger.debug('Record file %s not found', record_filename) return self.install_succeeded = True if self.as_egg: # there's no --always-unzip option we can pass to install # command so we unable to save the installed-files.txt return def prepend_root(path): if root is None or not os.path.isabs(path): return path else: return change_root(root, path) with open(record_filename) as f: for line in f: directory = os.path.dirname(line) if directory.endswith('.egg-info'): egg_info_dir = prepend_root(directory) break else: logger.warning( 'Could not find .egg-info directory in install record' ' for %s', self, ) # FIXME: put the record somewhere # FIXME: should this be an error? return new_lines = [] with open(record_filename) as f: for line in f: filename = line.strip() if os.path.isdir(filename): filename += os.path.sep new_lines.append( os.path.relpath(prepend_root(filename), egg_info_dir)) inst_files_path = os.path.join(egg_info_dir, 'installed-files.txt') with open(inst_files_path, 'w') as f: f.write('\n'.join(new_lines) + '\n') finally: if os.path.exists(record_filename): os.remove(record_filename) rmtree(temp_location)
def cleanup(self): """Remove the temporary directory created and reset state """ if self.path is not None and os.path.exists(self.path): rmtree(self.path) self.path = None
def install(self, install_options, global_options=(), root=None): if self.editable: self.install_editable(install_options, global_options) return if self.is_wheel: version = pip.wheel.wheel_version(self.source_dir) pip.wheel.check_compatibility(version, self.name) self.move_wheel_files(self.source_dir, root=root) self.install_succeeded = True return if self.isolated: global_options = list(global_options) + ["--no-user-cfg"] temp_location = tempfile.mkdtemp('-record', 'pip-') record_filename = os.path.join(temp_location, 'install-record.txt') try: install_args = [sys.executable] install_args.append('-c') install_args.append( "import setuptools, tokenize;__file__=%r;" "exec(compile(getattr(tokenize, 'open', open)(__file__).read()" ".replace('\\r\\n', '\\n'), __file__, 'exec'))" % self.setup_py ) install_args += list(global_options) + \ ['install', '--record', record_filename] if not self.as_egg: install_args += ['--single-version-externally-managed'] if root is not None: install_args += ['--root', root] if self.pycompile: install_args += ["--compile"] else: install_args += ["--no-compile"] if running_under_virtualenv(): py_ver_str = 'python' + sysconfig.get_python_version() install_args += ['--install-headers', os.path.join(sys.prefix, 'include', 'site', py_ver_str, self.name)] logger.info('Running setup.py install for %s', self.name) with indent_log(): call_subprocess( install_args + install_options, cwd=self.source_dir, filter_stdout=_filter_install, show_stdout=False, ) if not os.path.exists(record_filename): logger.debug('Record file %s not found', record_filename) return self.install_succeeded = True if self.as_egg: # there's no --always-unzip option we can pass to install # command so we unable to save the installed-files.txt return def prepend_root(path): if root is None or not os.path.isabs(path): return path else: return change_root(root, path) with open(record_filename) as f: for line in f: directory = os.path.dirname(line) if directory.endswith('.egg-info'): egg_info_dir = prepend_root(directory) break else: logger.warning( 'Could not find .egg-info directory in install record' ' for %s', self, ) # FIXME: put the record somewhere # FIXME: should this be an error? return new_lines = [] with open(record_filename) as f: for line in f: filename = line.strip() if os.path.isdir(filename): filename += os.path.sep new_lines.append( make_path_relative( prepend_root(filename), egg_info_dir) ) inst_files_path = os.path.join(egg_info_dir, 'installed-files.txt') with open(inst_files_path, 'w') as f: f.write('\n'.join(new_lines) + '\n') finally: if os.path.exists(record_filename): os.remove(record_filename) rmtree(temp_location)
def install(self, install_options, global_options=(), root=None, strip_file_prefix=None): if self.editable: self.install_editable(install_options, global_options) return if self.is_wheel: version = pip.wheel.wheel_version(self.source_dir) pip.wheel.check_compatibility(version, self.name) self.move_wheel_files( self.source_dir, root=root, strip_file_prefix=strip_file_prefix ) self.install_succeeded = True return if self.isolated: global_options = list(global_options) + ["--no-user-cfg"] temp_location = tempfile.mkdtemp('-record', 'pip-') record_filename = os.path.join(temp_location, 'install-record.txt') try: install_args = [sys.executable] install_args.append('-c') install_args.append( "import setuptools, tokenize;__file__=%r;" "exec(compile(getattr(tokenize, 'open', open)(__file__).read()" ".replace('\\r\\n', '\\n'), __file__, 'exec'))" % self.setup_py ) install_args += list(global_options) + \ ['install', '--record', record_filename] if not self.as_egg: install_args += ['--single-version-externally-managed'] if root is not None: install_args += ['--root', root] if self.pycompile: install_args += ["--compile"] else: install_args += ["--no-compile"] if running_under_virtualenv(): # FIXME: I'm not sure if this is a reasonable location; # probably not but we can't put it in the default location, as # that is a virtualenv symlink that isn't writable py_ver_str = 'python' + sysconfig.get_python_version() install_args += ['--install-headers', os.path.join(sys.prefix, 'include', 'site', py_ver_str)] logger.info('Running setup.py install for %s', self.name) with indent_log(): call_subprocess( install_args + install_options, cwd=self.source_dir, filter_stdout=self._filter_install, show_stdout=False, ) if not os.path.exists(record_filename): logger.debug('Record file %s not found', record_filename) return self.install_succeeded = True if self.as_egg: # there's no --always-unzip option we can pass to install # command so we unable to save the installed-files.txt return def prepend_root(path): if root is None or not os.path.isabs(path): return path else: return change_root(root, path) with open(record_filename) as f: for line in f: directory = os.path.dirname(line) if directory.endswith('.egg-info'): egg_info_dir = prepend_root(directory) break else: logger.warning( 'Could not find .egg-info directory in install record' ' for %s', self, ) # FIXME: put the record somewhere # FIXME: should this be an error? return new_lines = [] with open(record_filename) as f: for line in f: filename = line.strip() if os.path.isdir(filename): filename += os.path.sep new_lines.append( make_path_relative( prepend_root(filename), egg_info_dir) ) inst_files_path = os.path.join(egg_info_dir, 'installed-files.txt') with open(inst_files_path, 'w') as f: f.write('\n'.join(new_lines) + '\n') finally: if os.path.exists(record_filename): os.remove(record_filename) rmtree(temp_location)
def cleanup(self): if self.delete: rmtree(self.name)
def run_egg_info(self): assert self.source_dir if self.name: logger.debug( 'Running setup.py (path:%s) egg_info for package %s', self.setup_py, self.name, ) else: logger.debug( 'Running setup.py (path:%s) egg_info for package from %s', self.setup_py, self.url, ) with indent_log(): # if it's distribute>=0.7, it won't contain an importable # setuptools, and having an egg-info dir blocks the ability of # setup.py to find setuptools plugins, so delete the egg-info dir # if no setuptools. it will get recreated by the run of egg_info # NOTE: this self.name check only works when installing from a # specifier (not archive path/urls) # TODO: take this out later if (self.name == 'distribute' and not os.path.isdir( os.path.join(self.source_dir, 'setuptools'))): rmtree(os.path.join(self.source_dir, 'distribute.egg-info')) script = self._run_setup_py script = script.replace('__SETUP_PY__', repr(self.setup_py)) script = script.replace('__PKG_NAME__', repr(self.name)) base_cmd = [sys.executable, '-c', script] if self.isolated: base_cmd += ["--no-user-cfg"] egg_info_cmd = base_cmd + ['egg_info'] # We can't put the .egg-info files at the root, because then the # source code will be mistaken for an installed egg, causing # problems if self.editable: egg_base_option = [] else: egg_info_dir = os.path.join(self.source_dir, 'pip-egg-info') if not os.path.exists(egg_info_dir): os.makedirs(egg_info_dir) egg_base_option = ['--egg-base', 'pip-egg-info'] cwd = self.source_dir if self.editable_options and \ 'subdirectory' in self.editable_options: cwd = os.path.join(cwd, self.editable_options['subdirectory']) call_subprocess( egg_info_cmd + egg_base_option, cwd=cwd, filter_stdout=self._filter_install, show_stdout=False, command_level=logging.DEBUG, command_desc='python setup.py egg_info') if not self.req: if isinstance( pkg_resources.parse_version(self.pkg_info()["Version"]), Version): op = "==" else: op = "===" self.req = pkg_resources.Requirement.parse( "".join([ self.pkg_info()["Name"], op, self.pkg_info()["Version"], ])) self.correct_build_location()
display_path(location), ) logger.debug('Output that cannot be parsed: \n%s', output) return url, None return url, match.group(1) def export(self, location): """Export the svn repository at the url to the destination location""" url, rev = self.get_url_rev() rev_options = get_rev_options(url, rev) logger.info('Exporting svn repository %s to %s', url, location) with indent_log(): if os.path.exists(location): # Subversion doesn't like to check out over an existing # directory --force fixes this, but was only added in svn 1.5 rmtree(location) <<<<<<< HEAD self.run_command( ['export'] + rev_options + [url, location], filter_stdout=self._filter, show_stdout=False) def switch(self, dest, url, rev_options): self.run_command(['switch'] + rev_options + [url, dest]) def update(self, dest, rev_options): self.run_command(['update'] + rev_options + [dest]) ======= call_subprocess( [self.cmd, 'export'] + rev_options + [url, location], filter_stdout=self._filter, show_stdout=False)
def check_destination(self, dest, url, rev_options, rev_display): """ Prepare a location to receive a checkout/clone. Return True if the location is ready for (and requires) a checkout/clone, False otherwise. """ checkout = True prompt = False if os.path.exists(dest): checkout = False if os.path.exists(os.path.join(dest, self.dirname)): existing_url = self.get_url(dest) if self.compare_urls(existing_url, url): logger.debug( '%s in %s exists, and has correct URL (%s)', self.repo_name.title(), display_path(dest), url, ) if not self.check_version(dest, rev_options): logger.info( 'Updating %s %s%s', display_path(dest), self.repo_name, rev_display, ) self.update(dest, rev_options) else: logger.info('Skipping because already up-to-date.') else: logger.warning( '%s %s in %s exists with URL %s', self.name, self.repo_name, display_path(dest), existing_url, ) prompt = ('(s)witch, (i)gnore, (w)ipe, (b)ackup ', ('s', 'i', 'w', 'b')) else: logger.warning( 'Directory %s already exists, and is not a %s %s.', dest, self.name, self.repo_name, ) prompt = ('(i)gnore, (w)ipe, (b)ackup ', ('i', 'w', 'b')) if prompt: logger.warning( 'The plan is to install the %s repository %s', self.name, url, ) response = ask_path_exists('What to do? %s' % prompt[0], prompt[1]) if response == 's': logger.info( 'Switching %s %s to %s%s', self.repo_name, display_path(dest), url, rev_display, ) self.switch(dest, url, rev_options) elif response == 'i': # do nothing pass elif response == 'w': logger.warning('Deleting %s', display_path(dest)) rmtree(dest) checkout = True elif response == 'b': dest_dir = backup_dir(dest) logger.warning( 'Backing up %s to %s', display_path(dest), dest_dir, ) shutil.move(dest, dest_dir) checkout = True elif response == 'a': sys.exit(-1) return checkout
def test_rmtree_retries(tmpdir, monkeypatch): """ Test pip.utils.rmtree will retry failures """ monkeypatch.setattr(shutil, 'rmtree', Failer(duration=1).call) rmtree('foo')