[docs]classTranslatorBase(AbstractClass):""" Translate a link into a distribution. """@abstractmethoddeftranslate(self,link,into=None):pass

[docs]classChainedTranslator(TranslatorBase):""" Glue a sequence of Translators together in priority order. The first Translator to resolve a requirement wins. """def__init__(self,*translators):self._translators=list(filter(None,translators))fortxinself._translators:ifnotisinstance(tx,TranslatorBase):raiseValueError('Expected a sequence of translators, got %s instead.'%type(tx))deftranslate(self,package,into=None):fortxinself._translators:dist=tx.translate(package,into=into)ifdist:returndistdef__str__(self):return'ChainedTranslator(%s)'%(', '.join((tx.__class__.__name__fortxinself._translators)))

classSourceTranslator(TranslatorBase):@classmethoddefrun_2to3(cls,path):fromlib2to3.refactorimportget_fixers_from_package,RefactoringToolrt=RefactoringTool(get_fixers_from_package('lib2to3.fixes'))withTRACER.timed('Translating %s'%path):forroot,dirs,filesinos.walk(path):forfninfiles:full_fn=os.path.join(root,fn)iffull_fn.endswith('.py'):withTRACER.timed('%s'%fn,V=3):try:chmod_plus_w(full_fn)rt.refactor_file(full_fn,write=True)exceptIOError:TRACER.log('Failed to translate %s'%fn)TRACER.log(traceback.format_exc())def__init__(self,interpreter=PythonInterpreter.get(),platform=Platform.current(),use_2to3=False,installer_impl=WheelInstaller):self._interpreter=interpreterself._installer_impl=installer_implself._use_2to3=use_2to3self._platform=platformdeftranslate(self,package,into=None):"""From a SourcePackage, translate to a binary distribution."""ifnotisinstance(package,SourcePackage):returnNoneifnotpackage.local:raiseValueError('SourceTranslator cannot translate remote packages.')installer=Noneversion=self._interpreter.versionunpack_path=Archiver.unpack(package.path)into=intoorsafe_mkdtemp()try:ifself._use_2to3andversion>=(3,):withTRACER.timed('Translating 2->3 %s'%package.name):self.run_2to3(unpack_path)installer=self._installer_impl(unpack_path,interpreter=self._interpreter,strict=(package.namenotin('distribute','setuptools')))withTRACER.timed('Packaging %s'%package.name):try:dist_path=installer.bdist()exceptself._installer_impl.InstallFailurease:TRACER.log('Failed to install package at %s: %s'%(unpack_path,e))returnNonetarget_path=os.path.join(into,os.path.basename(dist_path))safe_copy(dist_path,target_path)target_package=Package.from_href(target_path)ifnottarget_package:TRACER.log('Target path %s does not look like a Package.'%target_path)returnNoneifnottarget_package.compatible(self._interpreter.identity,platform=self._platform):TRACER.log('Target package %s is not compatible with %s / %s'%(target_package,self._interpreter.identity,self._platform))returnNonereturnDistributionHelper.distribution_from_path(target_path)exceptExceptionase:TRACER.log('Failed to translate %s'%package)TRACER.log(traceback.format_exc())finally:ifinstaller:installer.cleanup()ifunpack_path:safe_rmtree(unpack_path)classBinaryTranslator(TranslatorBase):def__init__(self,package_type,interpreter=PythonInterpreter.get(),platform=Platform.current()):self._package_type=package_typeself._platform=platformself._identity=interpreter.identitydeftranslate(self,package,into=None):"""From a binary package, translate to a local binary distribution."""ifnotpackage.local:raiseValueError('BinaryTranslator cannot translate remote packages.')ifnotisinstance(package,self._package_type):returnNoneifnotpackage.compatible(identity=self._identity,platform=self._platform):TRACER.log('Target package %s is not compatible with %s / %s'%(package,self._identity,self._platform))returnNoneinto=intoorsafe_mkdtemp()target_path=os.path.join(into,package.filename)safe_copy(package.path,target_path)returnDistributionHelper.distribution_from_path(target_path)classEggTranslator(BinaryTranslator):def__init__(self,**kw):super(EggTranslator,self).__init__(EggPackage,**kw)classWheelTranslator(BinaryTranslator):def__init__(self,**kw):super(WheelTranslator,self).__init__(WheelPackage,**kw)classTranslator(object):@staticmethoddefdefault(platform=Platform.current(),interpreter=None):# TODO(wickman) Consider interpreter=None to indicate "universal" packages# since the .whl format can support this.# Also consider platform=None to require platform-inspecific packages.# Issue #95.interpreter=interpreterorPythonInterpreter.get()whl_translator=WheelTranslator(platform=platform,interpreter=interpreter)egg_translator=EggTranslator(platform=platform,interpreter=interpreter)source_translator=SourceTranslator(platform=platform,interpreter=interpreter)returnChainedTranslator(whl_translator,egg_translator,source_translator)