############################################################################## # # Copyright (c) 2006 Zope Corporation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Install packages as eggs $Id: egg.py 115900 2010-08-23 20:26:07Z gary $ """ import UserDict, logging, os, re, zipfile import zc.buildout import zc.buildout.easy_install class Eggs(object): include_site_packages = allowed_eggs = None def __init__(self, buildout, name, options): self.buildout = buildout self.name = self.default_eggs = name if getattr(options, 'query_bool', None) is None: # Someone is not passing us a zc.buildout.buildout.Options # object. Maybe we should have a deprecation warning. # Whatever. options = _BackwardsSupportOption(options) self.options = options b_options = buildout['buildout'] links = options.get('find-links', b_options['find-links']) if links: links = links.split() options['find-links'] = '\n'.join(links) else: links = () self.links = links index = options.get('index', b_options.get('index')) if index is not None: options['index'] = index self.index = index allow_hosts = b_options['allow-hosts'] allow_hosts = tuple([host.strip() for host in allow_hosts.split('\n') if host.strip()!='']) self.allow_hosts = allow_hosts options['eggs-directory'] = b_options['eggs-directory'] options['_e'] = options['eggs-directory'] # backward compat. options['develop-eggs-directory'] = b_options['develop-eggs-directory'] options['_d'] = options['develop-eggs-directory'] # backward compat. python = options.setdefault('python', b_options['python']) options['executable'] = buildout[python]['executable'] def working_set(self, extra=()): """Separate method to just get the working set This is intended for reuse by similar recipes. """ options = self.options b_options = self.buildout['buildout'] distributions = [ r.strip() for r in options.get('eggs', self.default_eggs).split('\n') if r.strip()] orig_distributions = distributions[:] distributions.extend(extra) if b_options.get('offline') == 'true': ws = zc.buildout.easy_install.working_set( distributions, options['executable'], [options['develop-eggs-directory'], options['eggs-directory']], include_site_packages=self.include_site_packages, allowed_eggs_from_site_packages=self.allowed_eggs, ) else: kw = {} if 'unzip' in options: kw['always_unzip'] = options.query_bool('unzip', None) ws = zc.buildout.easy_install.install( distributions, options['eggs-directory'], links=self.links, index=self.index, executable=options['executable'], path=[options['develop-eggs-directory']], newest=b_options.get('newest') == 'true', include_site_packages=self.include_site_packages, allowed_eggs_from_site_packages=self.allowed_eggs, allow_hosts=self.allow_hosts, **kw) return orig_distributions, ws def install(self): reqs, ws = self.working_set() return () update = install class ScriptBase(Eggs): def __init__(self, buildout, name, options): super(ScriptBase, self).__init__(buildout, name, options) b_options = buildout['buildout'] options['bin-directory'] = b_options['bin-directory'] options['_b'] = options['bin-directory'] # backward compat. self.extra_paths = [ os.path.join(b_options['directory'], p.strip()) for p in options.get('extra-paths', '').split('\n') if p.strip() ] if self.extra_paths: options['extra-paths'] = '\n'.join(self.extra_paths) relative_paths = options.get( 'relative-paths', b_options.get('relative-paths', 'false')) if relative_paths == 'true': options['buildout-directory'] = b_options['directory'] self._relative_paths = options['buildout-directory'] else: self._relative_paths = '' assert relative_paths == 'false' parse_entry_point = re.compile( '([^=]+)=(\w+(?:[.]\w+)*):(\w+(?:[.]\w+)*)$' ).match def install(self): reqs, ws = self.working_set() options = self.options scripts = options.get('scripts') if scripts or scripts is None or options.get('interpreter'): if scripts is not None: scripts = scripts.split() scripts = dict([ ('=' in s) and s.split('=', 1) or (s, s) for s in scripts ]) for s in options.get('entry-points', '').split(): parsed = self.parse_entry_point(s) if not parsed: logging.getLogger(self.name).error( "Cannot parse the entry point %s.", s) raise zc.buildout.UserError("Invalid entry point") reqs.append(parsed.groups()) if options.query_bool('dependent-scripts', 'false'): # Generate scripts for all packages in the working set, # except setuptools. reqs = list(reqs) for dist in ws: name = dist.project_name if name != 'setuptools' and name not in reqs: reqs.append(name) return self._install(reqs, ws, scripts) return () update = install def _install(self, reqs, ws, scripts): # Subclasses implement this. raise NotImplementedError() class Scripts(ScriptBase): def _install(self, reqs, ws, scripts): options = self.options return zc.buildout.easy_install.scripts( reqs, ws, options['executable'], options['bin-directory'], scripts=scripts, extra_paths=self.extra_paths, interpreter=options.get('interpreter'), initialization=options.get('initialization', ''), arguments=options.get('arguments', ''), relative_paths=self._relative_paths ) Egg = Scripts class _BackwardsSupportOption(UserDict.UserDict): def __init__(self, data): self.data = data # We want to show mutations to the underlying dict. def query_bool(self, name, default=None): """Given a name, return a boolean value for that name. ``default``, if given, should be 'true', 'false', or None. """ if default is not None: value = self.setdefault(name, default) else: value = self.get(name) if value is None: return value return _convert_bool(name, value) def get_bool(self, name): """Given a name, return a boolean value for that name. """ return _convert_bool(name, self[name]) def _convert_bool(name, value): if value not in ('true', 'false'): raise zc.buildout.UserError( 'Invalid value for %s option: %s' % (name, value)) else: return value == 'true'