def uninstall(self): path_re = re.compile(r'\./{0}-[\d\w\.]+-py\d\.\d.egg'.format(self.name), re.I) path_re2 = re.compile(r'\.{0}'.format(self.name), re.I) to_del = self.find_files() if not to_del: logger.warn('{0}: did not find any files to delete', self.name) raise PygError logger.info('Uninstalling {0}', self.name) logger.indent += 8 for d in to_del: logger.info(d) logger.indent -= 8 do_it = logger.ask('Proceed', bool=('remove files', 'cancel'), dont_ask=args_manager['install']['yes']) if do_it: for d in to_del: try: logger.verbose('Deleting: {0}', d) shutil.rmtree(d) except OSError: ## It is not a directory try: os.remove(d) except OSError: logger.error('Error: cannot delete {0}', d) logger.verbose('Removing egg path from easy_install.pth...') with open(EASY_INSTALL) as f: lines = f.readlines() with open(EASY_INSTALL, 'w') as f: for line in lines: if path_re.match(line) or path_re2.match(line): continue f.write(line) logger.success('{0} uninstalled succesfully', self.name) else: logger.info('{0} has not been uninstalled', self.name)
def install(self): try: r = Requirement(self.req) updater = Updater(skip=True) if self.upgrading: updater.remove_files(self.req) r.install() # Now let's install dependencies Installer._install_deps(r.reqset, r.name, updater) logger.success('{0} installed successfully', r.name) except (KeyboardInterrupt, Exception) as e: try: msg = e.args[0] except IndexError: msg = repr(e) if isinstance(e, KeyboardInterrupt): logger.warn('Process interrupted...') else: logger.warn('Error: An error occurred during the {0} of {1}: {2}', 'upgrading' if self.upgrading else 'installation', self.req, msg) if self.upgrading: logger.info('Restoring files...') updater.restore_files(self.req) else: logger.info('Removing broken files...') Uninstaller(self.req).uninstall() logger.error(msg, exc=InstallationError)
def update(self): ''' Searches for updates for every package in the WorkingSet. Then calls :meth:`~pyg.inst.Updater.upgrade`. ''' logger.info('Searching for updates') for dist in self.working_set: package = dist.project_name version = Version(dist.version) logger.verbose('Found: {0}=={1}', package, version) try: json = PyPIJson(package).retrieve() new_version = Version(json['info']['version']) except Exception as e: logger.error('Error: Failed to fetch data for {0} ({1})', package, e) continue if version >= new_version: continue txt = 'A new release is avaiable for {0}: {1!s} (old {2}), update'.format(package, new_version, dist.version) u = logger.ask(txt, bool=('upgrade version', 'keep working version'), dont_ask=self.yes) if u: self.upgrade(package, json, new_version) else: logger.info('{0} has not been upgraded', package) self._clean() logger.success('Updating finished successfully')
def install(self): ''' Install a bundle. For every package runs ``setup.py install``. ''' with TempDir() as tempdir: with ZipFile(self.path) as z: z.extractall(tempdir) location = os.path.join(tempdir, 'build') for f in os.listdir(location): logger.info('Installing {0}...', f) fullpath = os.path.join(location, f) Dir(fullpath, f, tempdir).install() logger.success('Bundle installed successfully')
def _download_all(self, dir): reqs = list(self.reqs) already_downloaded = set() while reqs: r = reqs.pop() # Hack for virtualenvs if r.name.lower == 'python': continue if any(r.name == rq.name for rq in already_downloaded): logger.debug('debug: Already downloaded: {0}', r) continue if any(r == rq for rq in self.exclude): logger.info('Excluding {0}', r) continue logger.indent = 0 logger.info('{0}:', r) logger.indent = 8 try: dist = SDist(self._download(dir, r)) self.callback(r, dist) except ConfigParser.MissingSectionHeaderError: continue try: logger.info('Looking for {0} dependencies', r) logger.indent += 8 found = False try: requirements = dist.file('requires.txt') except KeyError: requirements = [] for requirement in requirements: rq = Requirement(requirement) if rq not in already_downloaded: logger.info('Found: {0}', requirement) reqs.append(rq) found = True if not found: logger.info('None found') except KeyError: logger.debug('debug: requires.txt not found for {0}', dist) try: as_req = dist.as_req except KeyError: as_req = str(r) already_downloaded.add(Requirement(as_req)) logger.indent = 0 logger.success('Finished processing dependencies')
def from_dir(path, name=None): name = name or os.path.basename(path) reqset = ReqSet(name) try: with TempDir() as tempdir: logger.info('Installing {0}', name) Dir(path, name, tempdir, reqset).install() except Exception as e: try: msg = e.args[0] except IndexError: msg = repr(e) logger.fatal('Error: {0}: cannot install the package', msg, exc=InstallationError) else: if reqset: Installer._install_deps(reqset) logger.success('{0} installed successfully', name)
def download(self, dest): dest = os.path.abspath(dest) files = self.files() ## We need a placeholder because of the nested for loops success = False for p in self.pref: if success: break if not files[p]: logger.warn('{0} files not found. Continue searching...', p) continue for v, name, hash, url in files[p]: if success: break if p == '.egg' and not right_egg(name): logger.info('Found egg file for another Python version: {0}. Continue searching...', version_egg(name)) continue try: data = download(url, 'Retrieving data for {0}'.format(self.name)).getvalue() except (urllib2.URLError, urllib2.HTTPError) as e: logger.debug('urllib2 error: {0}', e.args) continue if not data: logger.debug('debug: Request failed') continue if not os.path.exists(dest): os.makedirs(dest) try: # Fix for packages with no version in the name if '-' not in name: name = '{0}-{1}{2}'.format(name, v, p) logger.info('Writing data into {0}', name) with open(os.path.join(dest, name), 'w') as f: f.write(data) except (IOError, OSError): logger.debug('debug: Error while writing data') continue logger.success('{0} downloaded successfully', self.name) success = True self.downloaded_name = name self.downloaded_version = v
def _install_deps(rs, name=None, updater=None): if not rs: return if args_manager['install']['no_deps']: logger.info('Skipping dependencies for {0}', name) logger.indent = 8 for req in rs: logger.info(req) logger.indent = 0 return logger.info('Installing dependencies...') dep_error = False newly_installed = [] for req in rs: if is_installed(req) and not args_manager['install']['upgrade_all']: logger.indent = 8 logger.info('{0} is already installed, use -A, --upgrade-all to upgrade dependencies', req) continue logger.indent = 0 logger.info('Installing {0} (from {1})', req, rs.comes_from) logger.indent = 8 try: Installer(req).install() newly_installed.append(req) except AlreadyInstalled: continue except InstallationError: dep_error = True logger.error('Error: {0} has not been installed correctly', req) continue logger.indent = 0 if dep_error: if updater: for req in newly_installed: updater.restore_files(req) updater.remove_files(rs.comes_from.name) updater.restore_files(rs.comes_from.name) logger.error("{0}'s dependencies installation failed", rs.comes_from.name, exc=InstallationError) else: logger.success('Finished installing dependencies for {0}', rs.comes_from.name)
def from_file(filepath, packname=None): packname = packname or os.path.basename(filepath).split('-')[0] reqset = ReqSet(packname) e = ext(filepath) path = os.path.abspath(filepath) if e in ('.tar.gz', '.tar.bz2', '.zip'): installer = Archive(open(path), e, packname, reqset) elif e in ('.pybundle', '.pyb'): installer = Bundle(filepath) elif e == '.egg': installer = Egg(open(path), path, reqset) elif e in ('.exe', '.msi') and is_windows(): installer = Binary(open(path), e, packname) else: if tarfile.is_tarfile(path): installer = Archive(open(path), None, packname, reqset) elif zipfile.is_zipfile(path): installer = Archive(open(path), '.zip', packname, reqset) else: logger.fatal('Error: Cannot install {0}: unknown filetype', packname, exc=InstallationError) installer.install() Installer._install_deps(reqset, packname) logger.success('{0} installed successfully', packname)
def bundle(self, include_manifest=True, build_dir=True, additional_files=[]): ''' Create a bundle of the specified package: 1. Download all required packages (included dependencies) 2. Clean the build directory 3. Collect the packages in a single zip file (bundle) 4. Add the manifest file 5. Move the bundle from the build dir to the destination ''' def _add_to_archive(zfile, dir): for file in os.listdir(dir): path = os.path.join(dir, file) if os.path.isfile(path): zfile.write(path, os.path.join(dir, file)[len(tempdir):]) elif os.path.isdir(path): _add_to_archive(zfile, path) with TempDir() as tempdir, TempDir() as bundle_dir: ## Step 1: we create the `build` directory ## If you choose to create a bundle without the build directory, ## be aware that your bundle will not be compatible with Pip. ##### if build_dir: build = os.path.join(tempdir, 'build') os.mkdir(build) else: build = tempdir tmp_bundle = os.path.join(bundle_dir, self.bundle_name) ## Step 2: we *recursively* download all required packages ##### reqs = list(self.reqs) already_downloaded = set() while reqs: r = reqs.pop() if any(rq.name == r.name and rq.match(r.version) for rq in self.exclude): logger.info('Excluding {0}', r) continue logger.indent = 0 logger.info('{0}:', r) logger.indent = 8 try: dist = SDist(self._download(build, r)) except ConfigParser.MissingSectionHeaderError: continue try: logger.info('Looking for {0} dependencies', r) logger.indent += 8 for requirement in dist.file('requires.txt'): if requirement not in already_downloaded: logger.info('Found: {0}', requirement) reqs.append(Requirement(requirement)) except KeyError: logger.debug('debug: requires.txt not found for {0}', dist) try: as_req = dist.as_req except KeyError: as_req = str(r) already_downloaded.add(as_req) logger.indent = 0 logger.success('Finished processing dependencies') ## Step 3: we remove all files in the build directory, so we make sure ## that when we collect packages we collect only dirs ##### self._clean(build) ## Step 4: we collect the downloaded packages and bundle all together ## in a single file (zipped) ##### logger.info('Adding packages to the bundle') bundle = zipfile.ZipFile(tmp_bundle, mode='w') _add_to_archive(bundle, build) ## Step 4: add the manifest file if include_manifest: logger.info('Adding the manifest file') bundle.writestr('pyg-manifest.txt', Bundler.MANIFEST.format('\n'.join(self.bundled))) # Additional files to add for path in additional_files: try: _add_to_archive(bundle, path) except (IOError, OSError): logger.debug('debug: Error while adding an additional file: {0}', path) bundle.close() ## Last step: move the bundle to the current working directory dest = os.path.join(os.getcwd(), self.bundle_name) if os.path.exists(dest): logger.debug('debug: dest already exists, removing it') os.remove(dest) shutil.move(tmp_bundle, os.getcwd())