eggs/py-1.4.0-py2.6.egg/py/_apipkg.py
changeset 69 c6bca38c1cbf
equal deleted inserted replaced
68:5ff1fc726848 69:c6bca38c1cbf
       
     1 """
       
     2 apipkg: control the exported namespace of a python package.
       
     3 
       
     4 see http://pypi.python.org/pypi/apipkg
       
     5 
       
     6 (c) holger krekel, 2009 - MIT license
       
     7 """
       
     8 import os
       
     9 import sys
       
    10 from types import ModuleType
       
    11 
       
    12 __version__ = '1.2.dev5'
       
    13 
       
    14 def initpkg(pkgname, exportdefs, attr=dict()):
       
    15     """ initialize given package from the export definitions. """
       
    16     oldmod = sys.modules.get(pkgname)
       
    17     d = {}
       
    18     f = getattr(oldmod, '__file__', None)
       
    19     if f:
       
    20         f = os.path.abspath(f)
       
    21     d['__file__'] = f
       
    22     if hasattr(oldmod, '__version__'):
       
    23         d['__version__'] = oldmod.__version__
       
    24     if hasattr(oldmod, '__loader__'):
       
    25         d['__loader__'] = oldmod.__loader__
       
    26     if hasattr(oldmod, '__path__'):
       
    27         d['__path__'] = [os.path.abspath(p) for p in oldmod.__path__]
       
    28     if '__doc__' not in exportdefs and getattr(oldmod, '__doc__', None):
       
    29         d['__doc__'] = oldmod.__doc__
       
    30     d.update(attr)
       
    31     if hasattr(oldmod, "__dict__"):
       
    32         oldmod.__dict__.update(d)
       
    33     mod = ApiModule(pkgname, exportdefs, implprefix=pkgname, attr=d)
       
    34     sys.modules[pkgname]  = mod
       
    35 
       
    36 def importobj(modpath, attrname):
       
    37     module = __import__(modpath, None, None, ['__doc__'])
       
    38     if not attrname:
       
    39         return module
       
    40 
       
    41     retval = module
       
    42     names = attrname.split(".")
       
    43     for x in names:
       
    44         retval = getattr(retval, x)
       
    45     return retval
       
    46 
       
    47 class ApiModule(ModuleType):
       
    48     def __docget(self):
       
    49         try:
       
    50             return self.__doc
       
    51         except AttributeError:
       
    52             if '__doc__' in self.__map__:
       
    53                 return self.__makeattr('__doc__')
       
    54     def __docset(self, value):
       
    55         self.__doc = value
       
    56     __doc__ = property(__docget, __docset)
       
    57 
       
    58     def __init__(self, name, importspec, implprefix=None, attr=None):
       
    59         self.__name__ = name
       
    60         self.__all__ = [x for x in importspec if x != '__onfirstaccess__']
       
    61         self.__map__ = {}
       
    62         self.__implprefix__ = implprefix or name
       
    63         if attr:
       
    64             for name, val in attr.items():
       
    65                 #print "setting", self.__name__, name, val
       
    66                 setattr(self, name, val)
       
    67         for name, importspec in importspec.items():
       
    68             if isinstance(importspec, dict):
       
    69                 subname = '%s.%s'%(self.__name__, name)
       
    70                 apimod = ApiModule(subname, importspec, implprefix)
       
    71                 sys.modules[subname] = apimod
       
    72                 setattr(self, name, apimod)
       
    73             else:
       
    74                 parts = importspec.split(':')
       
    75                 modpath = parts.pop(0)
       
    76                 attrname = parts and parts[0] or ""
       
    77                 if modpath[0] == '.':
       
    78                     modpath = implprefix + modpath
       
    79 
       
    80                 if not attrname:
       
    81                     subname = '%s.%s'%(self.__name__, name)
       
    82                     apimod = AliasModule(subname, modpath)
       
    83                     sys.modules[subname] = apimod
       
    84                     if '.' not in name:
       
    85                         setattr(self, name, apimod)
       
    86                 else:
       
    87                     self.__map__[name] = (modpath, attrname)
       
    88 
       
    89     def __repr__(self):
       
    90         l = []
       
    91         if hasattr(self, '__version__'):
       
    92             l.append("version=" + repr(self.__version__))
       
    93         if hasattr(self, '__file__'):
       
    94             l.append('from ' + repr(self.__file__))
       
    95         if l:
       
    96             return '<ApiModule %r %s>' % (self.__name__, " ".join(l))
       
    97         return '<ApiModule %r>' % (self.__name__,)
       
    98 
       
    99     def __makeattr(self, name):
       
   100         """lazily compute value for name or raise AttributeError if unknown."""
       
   101         #print "makeattr", self.__name__, name
       
   102         target = None
       
   103         if '__onfirstaccess__' in self.__map__:
       
   104             target = self.__map__.pop('__onfirstaccess__')
       
   105             importobj(*target)()
       
   106         try:
       
   107             modpath, attrname = self.__map__[name]
       
   108         except KeyError:
       
   109             if target is not None and name != '__onfirstaccess__':
       
   110                 # retry, onfirstaccess might have set attrs
       
   111                 return getattr(self, name)
       
   112             raise AttributeError(name)
       
   113         else:
       
   114             result = importobj(modpath, attrname)
       
   115             setattr(self, name, result)
       
   116             try:
       
   117                 del self.__map__[name]
       
   118             except KeyError:
       
   119                 pass # in a recursive-import situation a double-del can happen
       
   120             return result
       
   121 
       
   122     __getattr__ = __makeattr
       
   123 
       
   124     def __dict__(self):
       
   125         # force all the content of the module to be loaded when __dict__ is read
       
   126         dictdescr = ModuleType.__dict__['__dict__']
       
   127         dict = dictdescr.__get__(self)
       
   128         if dict is not None:
       
   129             hasattr(self, 'some')
       
   130             for name in self.__all__:
       
   131                 try:
       
   132                     self.__makeattr(name)
       
   133                 except AttributeError:
       
   134                     pass
       
   135         return dict
       
   136     __dict__ = property(__dict__)
       
   137 
       
   138 
       
   139 def AliasModule(modname, modpath):
       
   140     mod = []
       
   141 
       
   142     def getmod():
       
   143         if not mod:
       
   144             mod.append(importobj(modpath, None))
       
   145         return mod[0]
       
   146 
       
   147     class AliasModule(ModuleType):
       
   148 
       
   149         def __repr__(self):
       
   150             return '<AliasModule %r for %r>' % (modname, modpath)
       
   151 
       
   152         def __getattribute__(self, name):
       
   153             return getattr(getmod(), name)
       
   154 
       
   155         def __setattr__(self, name, value):
       
   156             setattr(getmod(), name, value)
       
   157 
       
   158         def __delattr__(self, name):
       
   159             delattr(getmod(), name)
       
   160 
       
   161     return AliasModule(modname)