Skip to content

Commit c9b9977

Browse files
committed
alias modules pointing to unimportable modules will return None for
all their attributes instead of raising ImportError. This addresses python3.4 where any call to getframeinfo() can choke on sys.modules contents if pytest is not installed (because py.test.* imports it).
1 parent 2f921b8 commit c9b9977

File tree

3 files changed

+22
-7
lines changed

3 files changed

+22
-7
lines changed

CHANGELOG

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33

44
- fix issue2 - adapt tests on Jython
55
- handle jython __pkgpath__ missabstraction when running python from jar files
6+
- alias modules pointing to unimportable modules will return None for
7+
all their attributes instead of raising ImportError. This addresses
8+
python3.4 where any call to getframeinfo() can choke on sys.modules
9+
contents if pytest is not installed (because py.test.* imports it).
610

711
1.2
812
----------------------------------------

apipkg.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ def _py_abspath(path):
1717
that will leave paths from jython jars alone
1818
"""
1919
if path.startswith('__pyclasspath__'):
20+
2021
return path
2122
else:
2223
return os.path.abspath(path)
@@ -41,7 +42,7 @@ def initpkg(pkgname, exportdefs, attr=dict()):
4142
if hasattr(oldmod, "__dict__"):
4243
oldmod.__dict__.update(d)
4344
mod = ApiModule(pkgname, exportdefs, implprefix=pkgname, attr=d)
44-
sys.modules[pkgname] = mod
45+
sys.modules[pkgname] = mod
4546

4647
def importobj(modpath, attrname):
4748
module = __import__(modpath, None, None, ['__doc__'])
@@ -72,11 +73,11 @@ def __init__(self, name, importspec, implprefix=None, attr=None):
7273
self.__implprefix__ = implprefix or name
7374
if attr:
7475
for name, val in attr.items():
75-
#print "setting", self.__name__, name, val
76+
# print "setting", self.__name__, name, val
7677
setattr(self, name, val)
7778
for name, importspec in importspec.items():
7879
if isinstance(importspec, dict):
79-
subname = '%s.%s'%(self.__name__, name)
80+
subname = '%s.%s' % (self.__name__, name)
8081
apimod = ApiModule(subname, importspec, implprefix)
8182
sys.modules[subname] = apimod
8283
setattr(self, name, apimod)
@@ -88,7 +89,7 @@ def __init__(self, name, importspec, implprefix=None, attr=None):
8889
modpath = implprefix + modpath
8990

9091
if not attrname:
91-
subname = '%s.%s'%(self.__name__, name)
92+
subname = '%s.%s' % (self.__name__, name)
9293
apimod = AliasModule(subname, modpath)
9394
sys.modules[subname] = apimod
9495
if '.' not in name:
@@ -108,7 +109,7 @@ def __repr__(self):
108109

109110
def __makeattr(self, name):
110111
"""lazily compute value for name or raise AttributeError if unknown."""
111-
#print "makeattr", self.__name__, name
112+
# print "makeattr", self.__name__, name
112113
target = None
113114
if '__onfirstaccess__' in self.__map__:
114115
target = self.__map__.pop('__onfirstaccess__')
@@ -126,7 +127,7 @@ def __makeattr(self, name):
126127
try:
127128
del self.__map__[name]
128129
except KeyError:
129-
pass # in a recursive-import situation a double-del can happen
130+
pass # in a recursive-import situation a double-del can happen
130131
return result
131132

132133
__getattr__ = __makeattr
@@ -166,7 +167,10 @@ def __repr__(self):
166167
return '<AliasModule %r for %r>' % (modname, x)
167168

168169
def __getattribute__(self, name):
169-
return getattr(getmod(), name)
170+
try:
171+
return getattr(getmod(), name)
172+
except ImportError:
173+
return None
170174

171175
def __setattr__(self, name, value):
172176
setattr(getmod(), name, value)

test_apipkg.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,13 @@ def test_aliasmodule_aliases_an_attribute():
423423
r = repr(am)
424424
assert "<AliasModule 'mymod' for 'pprint.PrettyPrinter'>" == r
425425
assert am.format
426+
assert not hasattr(am, "lqkje")
427+
428+
def test_aliasmodule_aliases_unimportable():
429+
am = apipkg.AliasModule("mymod", "qlwkejqlwe", 'main')
430+
r = repr(am)
431+
assert "<AliasModule 'mymod' for 'qlwkejqlwe.main'>" == r
432+
assert am.qwe is None
426433

427434
def test_aliasmodule_unicode():
428435
am = apipkg.AliasModule(py.builtin._totext("mymod"), "pprint")

0 commit comments

Comments
 (0)