Skip to content

Commit 2d0a1b8

Browse files
committed
dont load __doc__ early, making ApiModules now fully lazy
also bump and normalize __version__ setting
1 parent ab7285f commit 2d0a1b8

File tree

4 files changed

+34
-20
lines changed

4 files changed

+34
-20
lines changed

CHANGELOG

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
1.2
1+
1.2.dev
22
----------------------------------------
33

44
- Allow to import from Aliasmodules (thanks Ralf Schmitt)
5+
- avoid loading __doc__ early, so ApiModule is now fully lazy
56

67
1.1
78
----------------------------------------

apipkg.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def initpkg(pkgname, exportdefs, attr=dict()):
2525
d['__loader__'] = oldmod.__loader__
2626
if hasattr(oldmod, '__path__'):
2727
d['__path__'] = [os.path.abspath(p) for p in oldmod.__path__]
28-
if hasattr(oldmod, '__doc__'):
28+
if '__doc__' not in exportdefs and getattr(oldmod, '__doc__', None):
2929
d['__doc__'] = oldmod.__doc__
3030
d.update(attr)
3131
if hasattr(oldmod, "__dict__"):
@@ -45,6 +45,16 @@ def importobj(modpath, attrname):
4545
return retval
4646

4747
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+
4858
def __init__(self, name, importspec, implprefix=None, attr=None):
4959
self.__name__ = name
5060
self.__all__ = [x for x in importspec if x != '__onfirstaccess__']
@@ -73,10 +83,7 @@ def __init__(self, name, importspec, implprefix=None, attr=None):
7383
sys.modules[subname] = apimod
7484
setattr(self, name, apimod)
7585
else:
76-
if name == '__doc__':
77-
self.__doc__ = importobj(modpath, attrname)
78-
else:
79-
self.__map__[name] = (modpath, attrname)
86+
self.__map__[name] = (modpath, attrname)
8087

8188
def __repr__(self):
8289
l = []

setup.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,13 @@
1313
except ImportError:
1414
from distutils.core import setup
1515

16-
from apipkg import __version__
17-
1816
def main():
1917
setup(
2018
name='apipkg',
2119
description=
2220
'apipkg: namespace control and lazy-import mechanism',
2321
long_description = open('README.txt').read(),
24-
version= __version__,
22+
version='1.2.dev4',
2523
url='http://bitbucket.org/hpk42/apipkg',
2624
license='MIT License',
2725
platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'],
@@ -40,4 +38,4 @@ def main():
4038
)
4139

4240
if __name__ == '__main__':
43-
main()
41+
main()

test_apipkg.py

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -115,12 +115,12 @@ def test_recursive_import(self, monkeypatch, tmpdir):
115115
})
116116
"""))
117117
pkgdir.join('submod.py').write(py.code.Source("""
118-
import recmodule
118+
import recmodule
119119
class someclass: pass
120120
print (recmodule.__dict__)
121121
"""))
122122
monkeypatch.syspath_prepend(tmpdir)
123-
import recmodule
123+
import recmodule
124124
assert isinstance(recmodule, apipkg.ApiModule)
125125
assert recmodule.some.__name__ == "someclass"
126126

@@ -224,14 +224,22 @@ def test_initpkg_transfers_attrs(monkeypatch):
224224
assert newmod.__loader__ == mod.__loader__
225225
assert newmod.__doc__ == mod.__doc__
226226

227-
def test_initpkg_not_overwrite_exportdefs(monkeypatch):
227+
def test_initpkg_nodoc(monkeypatch):
228228
mod = type(sys)('hello')
229-
mod.__doc__ = "this is the documentation"
229+
mod.__file__ = "hello.py"
230230
monkeypatch.setitem(sys.modules, 'hello', mod)
231-
apipkg.initpkg('hello', {"__doc__": "sys:__doc__"})
231+
apipkg.initpkg('hello', {})
232232
newmod = sys.modules['hello']
233-
assert newmod != mod
234-
assert newmod.__doc__ == sys.__doc__
233+
assert not newmod.__doc__
234+
235+
def test_initpkg_overwrite_doc(monkeypatch):
236+
hello = type(sys)('hello')
237+
hello.__doc__ = "this is the documentation"
238+
monkeypatch.setitem(sys.modules, 'hello', hello)
239+
apipkg.initpkg('hello', {"__doc__": "sys:__doc__"})
240+
newhello = sys.modules['hello']
241+
assert newhello != hello
242+
assert newhello.__doc__ == sys.__doc__
235243

236244
def test_initpkg_not_transfers_not_existing_attrs(monkeypatch):
237245
mod = type(sys)('hello')
@@ -289,7 +297,7 @@ def test_onfirstaccess(tmpdir, monkeypatch):
289297
"""))
290298
pkgdir.join('submod.py').write(py.code.Source("""
291299
l = []
292-
def init():
300+
def init():
293301
l.append(1)
294302
"""))
295303
monkeypatch.syspath_prepend(tmpdir)
@@ -311,9 +319,9 @@ def test_onfirstaccess_setsnewattr(tmpdir, monkeypatch, mode):
311319
)
312320
"""))
313321
pkgdir.join('submod.py').write(py.code.Source("""
314-
def init():
322+
def init():
315323
import %s as pkg
316-
pkg.newattr = 42
324+
pkg.newattr = 42
317325
""" % pkgname))
318326
monkeypatch.syspath_prepend(tmpdir)
319327
mod = __import__(pkgname)

0 commit comments

Comments
 (0)