Coverage for /home/martinb/.local/share/virtualenvs/camcops/lib/python3.6/site-packages/py/_vendored_packages/apipkg/__init__.py : 15%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""
2apipkg: control the exported namespace of a Python package.
4see https://pypi.python.org/pypi/apipkg
6(c) holger krekel, 2009 - MIT license
7"""
8import os
9import sys
10from types import ModuleType
12from .version import version as __version__
15def _py_abspath(path):
16 """
17 special version of abspath
18 that will leave paths from jython jars alone
19 """
20 if path.startswith('__pyclasspath__'):
22 return path
23 else:
24 return os.path.abspath(path)
27def distribution_version(name):
28 """try to get the version of the named distribution,
29 returs None on failure"""
30 from pkg_resources import get_distribution, DistributionNotFound
31 try:
32 dist = get_distribution(name)
33 except DistributionNotFound:
34 pass
35 else:
36 return dist.version
39def initpkg(pkgname, exportdefs, attr=None, eager=False):
40 """ initialize given package from the export definitions. """
41 attr = attr or {}
42 oldmod = sys.modules.get(pkgname)
43 d = {}
44 f = getattr(oldmod, '__file__', None)
45 if f:
46 f = _py_abspath(f)
47 d['__file__'] = f
48 if hasattr(oldmod, '__version__'):
49 d['__version__'] = oldmod.__version__
50 if hasattr(oldmod, '__loader__'):
51 d['__loader__'] = oldmod.__loader__
52 if hasattr(oldmod, '__path__'):
53 d['__path__'] = [_py_abspath(p) for p in oldmod.__path__]
54 if hasattr(oldmod, '__package__'):
55 d['__package__'] = oldmod.__package__
56 if '__doc__' not in exportdefs and getattr(oldmod, '__doc__', None):
57 d['__doc__'] = oldmod.__doc__
58 d.update(attr)
59 if hasattr(oldmod, "__dict__"):
60 oldmod.__dict__.update(d)
61 mod = ApiModule(pkgname, exportdefs, implprefix=pkgname, attr=d)
62 sys.modules[pkgname] = mod
63 # eagerload in bypthon to avoid their monkeypatching breaking packages
64 if 'bpython' in sys.modules or eager:
65 for module in list(sys.modules.values()):
66 if isinstance(module, ApiModule):
67 module.__dict__
70def importobj(modpath, attrname):
71 """imports a module, then resolves the attrname on it"""
72 module = __import__(modpath, None, None, ['__doc__'])
73 if not attrname:
74 return module
76 retval = module
77 names = attrname.split(".")
78 for x in names:
79 retval = getattr(retval, x)
80 return retval
83class ApiModule(ModuleType):
84 """the magical lazy-loading module standing"""
85 def __docget(self):
86 try:
87 return self.__doc
88 except AttributeError:
89 if '__doc__' in self.__map__:
90 return self.__makeattr('__doc__')
92 def __docset(self, value):
93 self.__doc = value
94 __doc__ = property(__docget, __docset)
96 def __init__(self, name, importspec, implprefix=None, attr=None):
97 self.__name__ = name
98 self.__all__ = [x for x in importspec if x != '__onfirstaccess__']
99 self.__map__ = {}
100 self.__implprefix__ = implprefix or name
101 if attr:
102 for name, val in attr.items():
103 # print "setting", self.__name__, name, val
104 setattr(self, name, val)
105 for name, importspec in importspec.items():
106 if isinstance(importspec, dict):
107 subname = '%s.%s' % (self.__name__, name)
108 apimod = ApiModule(subname, importspec, implprefix)
109 sys.modules[subname] = apimod
110 setattr(self, name, apimod)
111 else:
112 parts = importspec.split(':')
113 modpath = parts.pop(0)
114 attrname = parts and parts[0] or ""
115 if modpath[0] == '.':
116 modpath = implprefix + modpath
118 if not attrname:
119 subname = '%s.%s' % (self.__name__, name)
120 apimod = AliasModule(subname, modpath)
121 sys.modules[subname] = apimod
122 if '.' not in name:
123 setattr(self, name, apimod)
124 else:
125 self.__map__[name] = (modpath, attrname)
127 def __repr__(self):
128 repr_list = []
129 if hasattr(self, '__version__'):
130 repr_list.append("version=" + repr(self.__version__))
131 if hasattr(self, '__file__'):
132 repr_list.append('from ' + repr(self.__file__))
133 if repr_list:
134 return '<ApiModule %r %s>' % (self.__name__, " ".join(repr_list))
135 return '<ApiModule %r>' % (self.__name__,)
137 def __makeattr(self, name):
138 """lazily compute value for name or raise AttributeError if unknown."""
139 # print "makeattr", self.__name__, name
140 target = None
141 if '__onfirstaccess__' in self.__map__:
142 target = self.__map__.pop('__onfirstaccess__')
143 importobj(*target)()
144 try:
145 modpath, attrname = self.__map__[name]
146 except KeyError:
147 if target is not None and name != '__onfirstaccess__':
148 # retry, onfirstaccess might have set attrs
149 return getattr(self, name)
150 raise AttributeError(name)
151 else:
152 result = importobj(modpath, attrname)
153 setattr(self, name, result)
154 try:
155 del self.__map__[name]
156 except KeyError:
157 pass # in a recursive-import situation a double-del can happen
158 return result
160 __getattr__ = __makeattr
162 @property
163 def __dict__(self):
164 # force all the content of the module
165 # to be loaded when __dict__ is read
166 dictdescr = ModuleType.__dict__['__dict__']
167 dict = dictdescr.__get__(self)
168 if dict is not None:
169 hasattr(self, 'some')
170 for name in self.__all__:
171 try:
172 self.__makeattr(name)
173 except AttributeError:
174 pass
175 return dict
178def AliasModule(modname, modpath, attrname=None):
179 mod = []
181 def getmod():
182 if not mod:
183 x = importobj(modpath, None)
184 if attrname is not None:
185 x = getattr(x, attrname)
186 mod.append(x)
187 return mod[0]
189 class AliasModule(ModuleType):
191 def __repr__(self):
192 x = modpath
193 if attrname:
194 x += "." + attrname
195 return '<AliasModule %r for %r>' % (modname, x)
197 def __getattribute__(self, name):
198 try:
199 return getattr(getmod(), name)
200 except ImportError:
201 return None
203 def __setattr__(self, name, value):
204 setattr(getmod(), name, value)
206 def __delattr__(self, name):
207 delattr(getmod(), name)
209 return AliasModule(str(modname))