def upgrade(self, package_name, json, version): ''' Upgrade a package to the most recent version. ''' logger.info('Removing {0} old version', package_name) self.remove_files(package_name) args_manager['install']['upgrade'] = True logger.info('Upgrading {0} to {1}', package_name, version) logger.indent += 8 for release in json['urls']: logger.info('Installing {0}...', release['filename']) logger.indent += 4 try: Installer.from_url(release['url']) break except Exception as e: try: msg = e.args[0] except IndexError: msg = repr(e) logger.error('Error: An error occurred while installing {0}: {1}', package_name, msg) logger.info('Trying another file...') logger.indent -= 4 else: logger.warn('Error: Did not find any installable release on PyPI for {0}', package_name) try: Requirement('{0}=={1}'.format(package_name, version))._install_from_links(args_manager['install']['packages_url']) except Exception as e: logger.fatal('Error: {0}', e, exc=InstallationError) logger.info('Restoring uninstalled files') self.restore_files(package_name) logger.indent = 0
def install(self): with TempDir() as tempdir: acc = set() self.gist.download(tempdir, acc) if 'setup.py' not in self.gist.files: logger.fatal('Error: gist must contain at least the `setup.py` file') Installer.from_dir(tempdir, 'gist {0}'.format(self.gist.gist_id))
def _find_develop(self, dir, req): try: logger.info('Looking for a local package...') try: dist = Develop(req.name) except (ValueError, AttributeError): logger.error('Cannot find a local distribution for {0}', req.name, exc=PygError) else: # XXX: Add a `location` attribute in pkgtools' next release location = os.path.abspath(dist._arg_name) path = os.path.dirname(location) if not req.match(Version(dist.version)): logger.error('Found {0}, but it does not match the requirement', path, exc=PygError) setup_py = os.path.join(path, 'setup.py') if not os.path.exists(setup_py): logger.error('Cannot find setup.py for {0}', req.name, exc=PygError) logger.info('Found a matching package in {0}', path) with TempDir() as tempdir: code, output = call_setup(path, ['sdist', '-d', tempdir]) if code != 0: logger.fatal('setup.py failed to create the source distribution') print_output(output, 'setup.py sdist') raise PygError arch = glob.glob(os.path.join(tempdir, '*{0}*'.format(req.name)))[0] shutil.move(arch, dir) arch_name = os.path.join(dir, os.path.basename(arch)) unpack(arch_name) return arch_name except (PygError, IndexError, ValueError): return False
def develop(self): logger.info('Running setup.py develop for {0}', self.package_name) code, output = call_setup(self.dest, ['develop']) if code != 0: logger.fatal('Error: setup.py develop did not install {0}', self.package_name) print_output(output, 'setup.py develop') raise InstallationError('setup.py did not install {0}'.format(self.package_name)) logger.info('{0} installed succesfully', self.package_name)
def __init__(self, dest): self.dest = os.path.abspath(dest) ## Check command line programs existence (git, hg, bzr, etc.) to avoid ## strange errors. try: subprocess.check_call([self.cmd], stdout=subprocess.PIPE, stderr=subprocess.PIPE) except OSError: logger.fatal('Error: {0} command not found. Please make sure you ' \ 'have installed required vcs', self.cmd, exc=PygError)
def develop(self): self.retrieve_data() if not os.path.exists(os.path.join(self.dir, 'setup.py')): logger.fatal('Error: The repository must have a top-level setup.py file', exc=InstallationError) logger.info('Running setup.py develop for {0}', self.package_name) code, output = call_setup(self.dir, ['develop']) if code != 0: logger.fatal('Error: setup.py develop did not install {0}', self.package_name) print_output(output, 'setup.py develop') raise InstallationError('setup.py did not install {0}'.format(self.package_name)) logger.info('{0} installed succesfully', self.package_name)
def check_permissions(dir): if not os.path.exists(dir): logger.fatal('Error: installation directory {0} does not exist', dir, exc=PygError) try: path = os.path.join(dir, 'pyg-permissions-test.pth') with open(path, 'w'): pass os.remove(path) ## FIXME: Do we need OSError too? except (IOError, OSError): return False else: return True
def download_func(args): pref = None if args.prefer: pref = ['.' + args.prefer.strip('.')] name = args.packname dest = args_manager['download']['download_dir'] unpk = args_manager['download']['unpack'] downloader = ReqManager(Requirement(name), pref) downloader.download(dest) if downloader.downloaded_name is None: logger.fatal('Error: Did not find any files for {0}', name, exc=PygError) if unpk: path = os.path.abspath(downloader.downloaded_name) logger.info('Unpacking {0} to {1}', os.path.basename(path), os.getcwd()) unpack(path)
def _gen_eggs(self, source_dir, egg_dir): r = re.compile(r'-py\d\.\d') def unzip_egg(arch_path): arch = os.path.basename(arch_path) eggname = arch[:r.search(arch).start()] with ZipFile(arch_path) as z: z.extractall(os.path.join(egg_dir, eggname)) with TempDir() as tempdir: for dist in os.listdir(source_dir): code, output = call_setup(os.path.join(source_dir, dist), ['bdist_egg', '-d', tempdir]) if code != 0: logger.fatal('Error: cannot generate egg for {0}', dist) print_output(output, 'setup.py bdist_egg') raise PygError('cannot generate egg for {0}'.format(dist)) arch = glob.glob(os.path.join(tempdir, dist) + '*.egg')[0] unzip_egg(arch)
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 bundle_func(args): def get_reqs(path): path = os.path.abspath(path) reqs = set() with open(path) as f: for line in f: line = line.strip() if not line or line.startswith('#'): continue reqs.add(line) return reqs if not args.packages: logger.fatal('Error: You must specify at least one package', exc=PygError) reqs = [] if args.req_file: reqs = [Requirement(r) for f in args.req_file for r in get_reqs(f)] b = Bundler(map(Requirement, args.packages) + reqs, args.bundlename) b.bundle()
def _download_and_install(self, url, filename, packname, e, hash=None): fobj = download(url, 'Downloading {0}'.format(self.name)) if hash is not None: logger.info('Checking md5 sum') if md5(fobj.getvalue()).hexdigest() != hash: logger.fatal('Error: {0} appears to be corrupted', self.name) return if e in ('.tar.gz', '.tar.bz2', '.zip'): installer = Archive(fobj, e, packname, self.reqset) elif e == '.egg': installer = Egg(fobj, filename, self.reqset, packname) elif is_windows() and e in WINDOWS_EXT: installer = Binary(fobj, e, packname) else: logger.error('Error: unknown filetype: {0}', e, exc=InstallationError) ## There is no need to catch exceptions now, this will be done by `pyg.inst.Installer.install` installer.install() self.success = True
def vcs(url, dest=None): schemes = ('git+', 'hg+', 'bzr+', 'svn+', 'dir+') for scheme in schemes: if url.startswith(scheme): break else: logger.fatal('Error: URL should start with one of these schemes:\n{0}', schemes, exc=ValueError) if not '#egg=' in url: logger.fatal('Error: URL should contain `#egg=PACKAGE`', exc=ValueError) MAP = { 'git': Git, 'hg': Hg, 'bzr': Bzr, 'svn': Svn, 'dir': Local, } return MAP[scheme[:-1]](url, dest)
def run_setup(path, name, global_args=[], args=[], exc=TypeError): ''' Run `setup.py install` for the given setup file. `name` is the package name; `global_args` are the arguments to pass before the `install` command; `args` are the options for the `install` command and `exc` is the exception to throw in case of a failed installation. The warning for `path` is the same as `call_setup`. ''' logger.info('Running setup.py install for {0}', name) if name == 'dreampie': ar = global_args + ['install'] + args else: ar = global_args + ['install', '--single-version-externally-managed', '--record', os.path.join(tempfile.mkdtemp(), '.pyg-install-record')] + args code, output = call_setup(path, ar) if code != 0: logger.fatal('Error: setup.py did not install {0}', name) print_output(output, 'setup.py install') raise exc('setup.py did not install {0}'.format(name))
def bundle_func(packages, bundlename, exclude, req_file, develop): def get_reqs(path): path = os.path.abspath(path) reqs = set() with open(path) as f: for line in f: line = line.strip() if not line or line.startswith('#'): continue reqs.add(line) return reqs if not packages and not req_file: logger.fatal('Error: You must specify at least one package', exc=PygError) reqs = [] if req_file: reqs = [Requirement(r) for f in req_file for r in get_reqs(f)] exclude = [Requirement(r) for r in (exclude or [])] bundlename = os.path.abspath(bundlename) dest, bundlename = os.path.dirname(bundlename), os.path.basename(bundlename) b = Bundler(map(Requirement, packages) + reqs, bundlename, exclude, use_develop=develop) b.bundle(dest=dest)
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 retrieve_data(self): code, output = self.call_cmd([self.url]) if code != 0: logger.fatal('Error: Cannot retrieve data') print_output(output, '{0} {1}'.format(self.cmd, self.method)) logger.raise_last(InstallationError)