"""apipkg: control the exported namespace of a python package.see http://pypi.python.org/pypi/apipkg(c) holger krekel, 2009 - MIT license"""importosimportsysfromtypesimportModuleType__version__='1.2.dev6'definitpkg(pkgname,exportdefs,attr=dict()):""" initialize given package from the export definitions. """oldmod=sys.modules.get(pkgname)d={}f=getattr(oldmod,'__file__',None)iff:f=os.path.abspath(f)d['__file__']=fifhasattr(oldmod,'__version__'):d['__version__']=oldmod.__version__ifhasattr(oldmod,'__loader__'):d['__loader__']=oldmod.__loader__ifhasattr(oldmod,'__path__'):d['__path__']=[os.path.abspath(p)forpinoldmod.__path__]if'__doc__'notinexportdefsandgetattr(oldmod,'__doc__',None):d['__doc__']=oldmod.__doc__d.update(attr)ifhasattr(oldmod,"__dict__"):oldmod.__dict__.update(d)mod=ApiModule(pkgname,exportdefs,implprefix=pkgname,attr=d)sys.modules[pkgname]=moddefimportobj(modpath,attrname):module=__import__(modpath,None,None,['__doc__'])ifnotattrname:returnmoduleretval=modulenames=attrname.split(".")forxinnames:retval=getattr(retval,x)returnretvalclassApiModule(ModuleType):def__docget(self):try:returnself.__docexceptAttributeError:if'__doc__'inself.__map__:returnself.__makeattr('__doc__')def__docset(self,value):self.__doc=value__doc__=property(__docget,__docset)def__init__(self,name,importspec,implprefix=None,attr=None):self.__name__=nameself.__all__=[xforxinimportspecifx!='__onfirstaccess__']self.__map__={}self.__implprefix__=implprefixornameifattr:forname,valinattr.items():#print "setting", self.__name__, name, valsetattr(self,name,val)forname,importspecinimportspec.items():ifisinstance(importspec,dict):subname='%s.%s'%(self.__name__,name)apimod=ApiModule(subname,importspec,implprefix)sys.modules[subname]=apimodsetattr(self,name,apimod)else:parts=importspec.split(':')modpath=parts.pop(0)attrname=partsandparts[0]or""ifmodpath[0]=='.':modpath=implprefix+modpathifnotattrname:subname='%s.%s'%(self.__name__,name)apimod=AliasModule(subname,modpath)sys.modules[subname]=apimodif'.'notinname:setattr(self,name,apimod)else:self.__map__[name]=(modpath,attrname)def__repr__(self):l=[]ifhasattr(self,'__version__'):l.append("version="+repr(self.__version__))ifhasattr(self,'__file__'):l.append('from '+repr(self.__file__))ifl:return'<ApiModule %r%s>'%(self.__name__," ".join(l))return'<ApiModule %r>'%(self.__name__,)def__makeattr(self,name):"""lazily compute value for name or raise AttributeError if unknown."""#print "makeattr", self.__name__, nametarget=Noneif'__onfirstaccess__'inself.__map__:target=self.__map__.pop('__onfirstaccess__')importobj(*target)()try:modpath,attrname=self.__map__[name]exceptKeyError:iftargetisnotNoneandname!='__onfirstaccess__':# retry, onfirstaccess might have set attrsreturngetattr(self,name)raiseAttributeError(name)else:result=importobj(modpath,attrname)setattr(self,name,result)try:delself.__map__[name]exceptKeyError:pass# in a recursive-import situation a double-del can happenreturnresult__getattr__=__makeattrdef__dict__(self):# force all the content of the module to be loaded when __dict__ is readdictdescr=ModuleType.__dict__['__dict__']dict=dictdescr.__get__(self)ifdictisnotNone:hasattr(self,'some')fornameinself.__all__:try:self.__makeattr(name)exceptAttributeError:passreturndict__dict__=property(__dict__)defAliasModule(modname,modpath,attrname=None):mod=[]defgetmod():ifnotmod:x=importobj(modpath,None)ifattrnameisnotNone:x=getattr(x,attrname)mod.append(x)returnmod[0]classAliasModule(ModuleType):def__repr__(self):x=modpathifattrname:x+="."+attrnamereturn'<AliasModule %r for %r>'%(modname,x)def__getattribute__(self,name):returngetattr(getmod(),name)def__setattr__(self,name,value):setattr(getmod(),name,value)def__delattr__(self,name):delattr(getmod(),name)returnAliasModule(modname)