def _pyenv_scheme_path(self, path): pyenv = self.pypmenv.pyenv fullpath = pyenv.get_install_scheme_path(path) assert fullpath.startswith(pyenv.base_dir), \ "'%s' is not based on '%s' (%s)" % ( fullpath, pyenv.base_dir, pyenv.root_dir) p = os.path.relpath(fullpath, pyenv.base_dir) if PLATNAME.startswith('win'): p = p.replace('\\', '/') return p
def get_install_scheme_path(self, path, usersite=False): if self.pyversion_info[:2] not in ((2, 6), (3, 1)): # use the `sysconfig` module that was introduced in Python 2.7 # Find the desired scheme; alas, there is no standard function for # this in the stdlib. See http://bugs.python.org/issue8772 # The following should work on default ActivePython installation. scheme = os.name if usersite: if PLATNAME.startswith('mac'): scheme = 'osx_framework_user' else: scheme += '_user' elif scheme == 'posix': scheme = 'posix_prefix' return self.eval("sysconfig.get_paths('%s')['%s']" % (scheme, path), with_modules=['sysconfig']).strip() else: # backward compat: use the limited `distutils.sysconfig` module on # 2.6. Unlike 2.7's sysconfig, this does not have the convenient # `get_paths` function ... forcing us to do the template # substitution ourselves, which may be error prone. :-/ # HACK: 2.6 does not have a path named 'stdlib'; let's just use # purelib, which is usually site-packages/ and go one-level up to # get the intended stdlib. if path == 'stdlib': joinwith = '..' path = 'purelib' else: joinwith = None if PLATNAME.startswith('win'): scheme = 'nt' else: scheme = 'unix' scheme += ('_user' if usersite else ('_prefix' if scheme == 'unix' else '')) template = self.eval( "INSTALL_SCHEMES['%s']['%s']" % (scheme, path), preimport_stmts=[ "import os", "from distutils.command.install import INSTALL_SCHEMES", ]).strip() # hardcoded template substitution (distutils API does not provide # this) template = template.replace('$base', self.base_dir) template = template.replace('$py_version_short', self.pyver) if '$user' in template: assert isinstance(self, UserLocalPythonEnvironment) template = template.replace('$usersite', self.user_site_dir) template = template.replace('$userbase', self.user_base_dir) assert '$' not in template, \ 'Unsubstituded variables left in "%s"' % template if joinwith: template = os.path.join(template, joinwith) return template
def get_install_scheme_path(self, path, usersite=False): if self.pyversion_info[:2] not in ((2,6), (3,1)): # use the `sysconfig` module that was introduced in Python 2.7 # Find the desired scheme; alas, there is no standard function for # this in the stdlib. See http://bugs.python.org/issue8772 # The following should work on default ActivePython installation. scheme = os.name if usersite: if PLATNAME.startswith('mac'): scheme = 'osx_framework_user' else: scheme += '_user' elif scheme == 'posix': scheme = 'posix_prefix' return self.eval( "sysconfig.get_paths('%s')['%s']" % (scheme, path), with_modules=['sysconfig'] ).strip() else: # backward compat: use the limited `distutils.sysconfig` module on # 2.6. Unlike 2.7's sysconfig, this does not have the convenient # `get_paths` function ... forcing us to do the template # substitution ourselves, which may be error prone. :-/ # HACK: 2.6 does not have a path named 'stdlib'; let's just use # purelib, which is usually site-packages/ and go one-level up to # get the intended stdlib. if path == 'stdlib': joinwith = '..' path = 'purelib' else: joinwith = None if PLATNAME.startswith('win'): scheme = 'nt' else: scheme = 'unix' scheme += ('_user' if usersite else ( '_prefix' if scheme == 'unix' else '')) template = self.eval( "INSTALL_SCHEMES['%s']['%s']" % (scheme, path), preimport_stmts=[ "import os", "from distutils.command.install import INSTALL_SCHEMES", ]).strip() # hardcoded template substitution (distutils API does not provide # this) template = template.replace('$base', self.base_dir) template = template.replace('$py_version_short', self.pyver) if '$user' in template: assert isinstance(self, UserLocalPythonEnvironment) template = template.replace('$usersite', self.user_site_dir) template = template.replace('$userbase', self.user_base_dir) assert '$' not in template, \ 'Unsubstituded variables left in "%s"' % template if joinwith: template = os.path.join(template, joinwith) return template
def _extract_to_install_scheme(self, bpkgfile, name): pyenv = self.pypmenv.pyenv # Install scheme used by the build environment (i.e., pyenv used by # pypm-builder on our build machines). as_build_scheme = { 'win': { 'purelib': 'lib/site-packages', 'stdlib': 'lib', 'scripts': 'scripts', }, 'unix': { 'purelib': 'lib/python{0}/site-packages'.format(pyenv.pyver), 'stdlib': 'lib/python{0}'.format(pyenv.pyver), 'scripts': 'bin', }, } plat = PLATNAME.startswith('win') and 'win' or 'unix' # Scheme used by pyenv pyenv_scheme = { 'purelib': self._pyenv_scheme_path('purelib'), 'stdlib': self._pyenv_scheme_path('stdlib'), 'scripts': self._pyenv_scheme_path('scripts'), } files_to_overwrite = [] force_overwrite = self.pypmenv.options['force'] # Hack #1: Don't check for distribute and pip, as virtualenvs usually # already have a copy of them installed. if name in ('distribute', 'setuptools', 'pip'): force_overwrite = True with bpkgfile.extract_over2(pyenv.base_dir) as tf: for tinfo in tf.getmembers(): # Replace AS build virtualenv scheme with the user's scheme # Eg: lib/site-packages/XYZ -> %APPDATA%/Python/Python26/XYZ for name, prefix in as_build_scheme[plat].items(): if tinfo.name.lower().startswith(prefix): old = tinfo.name new = pyenv_scheme[name] + old[len(prefix):] if new != old: LOG.debug('fs:extract: transforming "%s" to "%s"', old, new) tinfo.name = new # Check for overwrites if os.path.lexists( tinfo.name) and not os.path.isdir(tinfo.name): # Hack #2: allow overwriting of *.pth files (setuptools # hackishness) eg: [...]/site-packages/setuptools.pth if not tinfo.name.endswith('.pth'): files_to_overwrite.append(tinfo.name) if files_to_overwrite: LOG.debug( 'install requires overwriting of %d files:\n%s', len(files_to_overwrite), '\n'.join([ os.path.join(pyenv.base_dir, f) for f in files_to_overwrite ])) if force_overwrite: LOG.warn('overwriting %d files' % len(files_to_overwrite)) else: errmsg = [ 'cannot overwrite "%s"' % concise_path( os.path.join(pyenv.base_dir, files_to_overwrite[0])) ] if len(files_to_overwrite) > 1: errmsg.append(' (and %d other files)' % (len(files_to_overwrite) - 1, )) errmsg.append( '; run pypm as "pypm --force ..." to overwrite anyway') if len(files_to_overwrite) > 1: errmsg.append( '; run "pypm log" to see the full list of files to be overwritten' ) raise IOError(wrapped(''.join(errmsg))) return tf.getnames()
def _extract_to_install_scheme(self, bpkgfile, name): pyenv = self.pypmenv.pyenv # Install scheme used by the build environment (i.e., pyenv used by # pypm-builder on our build machines). as_build_scheme = { 'win': { 'purelib': 'lib/site-packages', 'stdlib': 'lib', 'scripts': 'scripts', }, 'unix': { 'purelib': 'lib/python{0}/site-packages'.format(pyenv.pyver), 'stdlib': 'lib/python{0}'.format(pyenv.pyver), 'scripts': 'bin', }, } plat = PLATNAME.startswith('win') and 'win' or 'unix' # Scheme used by pyenv pyenv_scheme = { 'purelib': self._pyenv_scheme_path('purelib'), 'stdlib': self._pyenv_scheme_path('stdlib'), 'scripts': self._pyenv_scheme_path('scripts'), } files_to_overwrite = [] force_overwrite = self.pypmenv.options['force'] # Hack #1: Don't check for distribute and pip, as virtualenvs usually # already have a copy of them installed. if name in ('distribute', 'setuptools', 'pip'): force_overwrite = True with bpkgfile.extract_over2(pyenv.base_dir) as tf: for tinfo in tf.getmembers(): # Replace AS build virtualenv scheme with the user's scheme # Eg: lib/site-packages/XYZ -> %APPDATA%/Python/Python26/XYZ for name, prefix in as_build_scheme[plat].items(): if tinfo.name.lower().startswith(prefix): old = tinfo.name new = pyenv_scheme[name] + old[len(prefix):] if new != old: LOG.debug('fs:extract: transforming "%s" to "%s"', old, new) tinfo.name = new # Check for overwrites if os.path.exists(tinfo.name) and not os.path.isdir(tinfo.name): # Hack #2: allow overwriting of *.pth files (setuptools # hackishness) eg: [...]/site-packages/setuptools.pth if not tinfo.name.endswith('.pth'): files_to_overwrite.append(tinfo.name) if files_to_overwrite: LOG.debug( 'install requires overwriting of %d files:\n%s', len(files_to_overwrite), '\n'.join([os.path.join(pyenv.base_dir, f) for f in files_to_overwrite])) if force_overwrite: LOG.warn('overwriting %d files' % len(files_to_overwrite)) else: errmsg = ['cannot overwrite "%s"' % concise_path(os.path.join( pyenv.base_dir, files_to_overwrite[0]))] if len(files_to_overwrite) > 1: errmsg.append(' (and %d other files)' % (len(files_to_overwrite)-1,)) errmsg.append('; run pypm as "pypm --force ..." to overwrite anyway') if len(files_to_overwrite) > 1: errmsg.append('; run "pypm log" to see the full list of files to be overwritten') raise IOError(wrapped(''.join(errmsg))) return tf.getnames()