##// END OF EJS Templates
Make autoreload extension work on Python 3....
Thomas Kluyver -
Show More
@@ -108,6 +108,9 try:
108 108 except NameError:
109 109 from imp import reload
110 110
111 from IPython.utils import pyfile
112 from IPython.utils.py3compat import PY3
113
111 114 def _get_compiled_ext():
112 115 """Official way to get the extension of compiled files (.pyc or .pyo)"""
113 116 for ext, mode, typ in imp.get_suffixes():
@@ -198,11 +201,14 class ModuleReloader(object):
198 201
199 202 if ext.lower() == '.py':
200 203 ext = PY_COMPILED_EXT
201 pyc_filename = path + PY_COMPILED_EXT
204 pyc_filename = pyfile.cache_from_source(filename)
202 205 py_filename = filename
203 206 else:
204 207 pyc_filename = filename
205 py_filename = filename[:-1]
208 try:
209 py_filename = pyfile.source_from_cache(filename)
210 except ValueError:
211 continue
206 212
207 213 if ext != PY_COMPILED_EXT:
208 214 continue
@@ -229,10 +235,16 class ModuleReloader(object):
229 235 # superreload
230 236 #------------------------------------------------------------------------------
231 237
238 if PY3:
239 func_attrs = ['__code__', '__defaults__', '__doc__',
240 '__closure__', '__globals__', '__dict__']
241 else:
242 func_attrs = ['func_code', 'func_defaults', 'func_doc',
243 'func_closure', 'func_globals', 'func_dict']
244
232 245 def update_function(old, new):
233 246 """Upgrade the code object of a function"""
234 for name in ['func_code', 'func_defaults', 'func_doc',
235 'func_closure', 'func_globals', 'func_dict']:
247 for name in func_attrs:
236 248 try:
237 249 setattr(old, name, getattr(new, name))
238 250 except (AttributeError, TypeError):
@@ -271,17 +283,25 def isinstance2(a, b, typ):
271 283 return isinstance(a, typ) and isinstance(b, typ)
272 284
273 285 UPDATE_RULES = [
274 (lambda a, b: isinstance2(a, b, types.ClassType),
275 update_class),
276 (lambda a, b: isinstance2(a, b, types.TypeType),
286 (lambda a, b: isinstance2(a, b, type),
277 287 update_class),
278 288 (lambda a, b: isinstance2(a, b, types.FunctionType),
279 289 update_function),
280 290 (lambda a, b: isinstance2(a, b, property),
281 291 update_property),
292 ]
293
294 if PY3:
295 UPDATE_RULES.extend([(lambda a, b: isinstance2(a, b, types.MethodType),
296 lambda a, b: update_function(a.__func__, b.__func__)),
297 ])
298 else:
299 UPDATE_RULES.extend([(lambda a, b: isinstance2(a, b, types.ClassType),
300 update_class),
282 301 (lambda a, b: isinstance2(a, b, types.MethodType),
283 302 lambda a, b: update_function(a.im_func, b.im_func)),
284 ]
303 ])
304
285 305
286 306 def update_generic(a, b):
287 307 for type_check, update in UPDATE_RULES:
@@ -317,7 +337,7 def superreload(module, reload=reload, old_objects={}):
317 337 except TypeError:
318 338 # weakref doesn't work for all types;
319 339 # create strong references for 'important' cases
320 if isinstance(obj, types.ClassType):
340 if not PY3 and isinstance(obj, types.ClassType):
321 341 old_objects.setdefault(key, []).append(StrongRef(obj))
322 342
323 343 # reload module
@@ -294,12 +294,8 x = -99
294 294 self.shell.run_code("pass") # trigger reload
295 295 nt.assert_equal(mod.x, -99)
296 296
297 # The autoreload extension needs to be updated for Python 3.2, as .pyc files
298 # are stored in a different location. See gh-846.
299 @knownfailureif(sys.version_info >= (3,2))
300 297 def test_smoketest_aimport(self):
301 298 self._check_smoketest(use_aimport=True)
302 299
303 @knownfailureif(sys.version_info >= (3,2))
304 300 def test_smoketest_autoreload(self):
305 301 self._check_smoketest(use_aimport=False)
General Comments 0
You need to be logged in to leave comments. Login now