[py-svn] apipkg commit e630694050b2: refine and better test onfirstaccess handling
commits-noreply at bitbucket.org
commits-noreply at bitbucket.org
Tue Dec 29 14:51:15 CET 2009
# HG changeset patch -- Bitbucket.org
# Project apipkg
# URL http://bitbucket.org/hpk42/apipkg/overview/
# User holger krekel <holger at merlinux.eu>
# Date 1262094649 -3600
# Node ID e630694050b26b2db57b46b2c68774af4c3b9e08
# Parent 47756aba150f1bd68aebc04364a9a44fe78ef524
refine and better test onfirstaccess handling
--- /dev/null
+++ b/conftest.py
@@ -0,0 +1,9 @@
+
+def pytest_generate_tests(metafunc):
+ multi = getattr(metafunc.function, 'multi', None)
+ if multi is None:
+ return
+ assert len(multi.kwargs) == 1
+ for name, l in multi.kwargs.items():
+ for val in l:
+ metafunc.addcall(funcargs={name: val})
--- a/apipkg.py
+++ b/apipkg.py
@@ -35,8 +35,6 @@ class ApiModule(ModuleType):
apimod = ApiModule(subname, importspec, implprefix)
sys.modules[subname] = apimod
setattr(self, name, apimod)
- elif name == '__onfirstaccess__':
- self.__map__[name] = importspec
else:
modpath, attrname = importspec.split(':')
if modpath[0] == '.':
@@ -57,16 +55,17 @@ class ApiModule(ModuleType):
return '<ApiModule %r>' % (self.__name__,)
def __getattr__(self, name):
- try:
- func = self.__map__.pop('__onfirstaccess__')
- except KeyError:
- pass
- else:
- if func:
- func()
+ target = None
+ if '__onfirstaccess__' in self.__map__:
+ target = self.__map__.pop('__onfirstaccess__')
+ importobj(*target)()
+ if name == "__onfirstaccess__":
+ return target
try:
modpath, attrname = self.__map__[name]
except KeyError:
+ if target is not None: # retry, onfirstaccess might have set attrs
+ return getattr(self, name)
raise AttributeError(name)
else:
result = importobj(modpath, attrname)
--- a/test_apipkg.py
+++ b/test_apipkg.py
@@ -209,30 +209,49 @@ def test_error_loading_one_element(monke
py.test.raises(ImportError, 'errorloading1.x')
py.test.raises(ImportError, 'errorloading1.x')
-def test_onfirstaccess(monkeypatch):
- mod = type(sys)('hello')
- monkeypatch.setitem(sys.modules, 'hello', mod)
- l = []
- apipkg.initpkg('hello', {
- '__onfirstaccess__': lambda: l.append(1),
- 'world': 'sys:executable',
- 'world2': 'sys:executable',
- })
- hello = sys.modules['hello']
- assert hello.world == sys.executable
- assert len(l) == 1
- assert hello.world == sys.executable
- assert len(l) == 1
+def test_onfirstaccess(tmpdir, monkeypatch):
+ pkgdir = tmpdir.mkdir("firstaccess")
+ pkgdir.join('__init__.py').write(py.code.Source("""
+ import apipkg
+ apipkg.initpkg(__name__, exportdefs={
+ '__onfirstaccess__': '.submod:init',
+ 'l': '.submod:l',
+ },
+ )
+ """))
+ pkgdir.join('submod.py').write(py.code.Source("""
+ l = []
+ def init():
+ l.append(1)
+ """))
+ monkeypatch.syspath_prepend(tmpdir)
+ import firstaccess
+ assert isinstance(firstaccess, apipkg.ApiModule)
+ assert len(firstaccess.l) == 1
+ assert len(firstaccess.l) == 1
-def test_onfirstaccess__dict__(monkeypatch):
- mod = type(sys)('hello')
- monkeypatch.setitem(sys.modules, 'hello', mod)
- l = []
- apipkg.initpkg('hello', {
- '__onfirstaccess__': lambda: l.append(1),
- })
- hello = sys.modules['hello']
- hello.__dict__
- assert len(l) == 1
- hello.__dict__
- assert len(l) == 1
+ at py.test.mark.multi(mode=['attr', 'dict'])
+def test_onfirstaccess_setsnewattr(tmpdir, monkeypatch, mode):
+ pkgname = tmpdir.basename.replace("-", "")
+ pkgdir = tmpdir.mkdir(pkgname)
+ pkgdir.join('__init__.py').write(py.code.Source("""
+ import apipkg
+ apipkg.initpkg(__name__, exportdefs={
+ '__onfirstaccess__': '.submod:init',
+ },
+ )
+ """))
+ pkgdir.join('submod.py').write(py.code.Source("""
+ def init():
+ import %s as pkg
+ pkg.newattr = 42
+ """ % pkgname))
+ monkeypatch.syspath_prepend(tmpdir)
+ mod = __import__(pkgname)
+ assert isinstance(mod, apipkg.ApiModule)
+ if mode == 'attr':
+ assert mod.newattr == 42
+ elif mode == "dict":
+ print mod.__dict__.keys()
+ assert 'newattr' in mod.__dict__
+ assert '__onfirstaccess__' not in vars(mod)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,5 @@
1.0.0b3 (compared to 1.0.0b2)
------------------------------------
-- added special attribute __onfirstaccess__ whose value will
- be called on the first attribute access to the apimodule
+- added special __onfirstaccess__ attribute whose value will
+ be called on the first attribute access of an apimodule.
More information about the pytest-commit
mailing list