Merge pull request #1307 from campagnola/acq4-merge

Fix reload to use mod.__cache__ to get name of pyc files
This commit is contained in:
Luke Campagnola 2020-07-13 15:47:15 -07:00 committed by GitHub
commit 51bb8b9bb8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 44 additions and 15 deletions

View File

@ -34,42 +34,72 @@ py3 = sys.version_info >= (3,)
def reloadAll(prefix=None, debug=False):
"""Automatically reload everything whose __file__ begins with prefix.
- Skips reload if the file has not been updated (if .pyc is newer than .py)
- if prefix is None, checks all loaded modules
"""Automatically reload all modules whose __file__ begins with *prefix*.
Skips reload if the file has not been updated (if .pyc is newer than .py)
If *prefix* is None, then all loaded modules are checked.
Returns a dictionary {moduleName: (reloaded, reason)} describing actions taken
for each module.
"""
failed = []
changed = []
ret = {}
for modName, mod in list(sys.modules.items()): ## don't use iteritems; size may change during reload
if not inspect.ismodule(mod):
ret[modName] = (False, 'not a module')
continue
if modName == '__main__':
ret[modName] = (False, 'ignored __main__')
continue
## Ignore if the file name does not start with prefix
if not hasattr(mod, '__file__') or mod.__file__ is None or os.path.splitext(mod.__file__)[1] not in ['.py', '.pyc']:
# Ignore modules without a __file__ that is .py or .pyc
if getattr(mod, '__file__', None) is None:
ret[modName] = (False, 'module has no __file__')
continue
if os.path.splitext(mod.__file__)[1] not in ['.py', '.pyc']:
ret[modName] = (False, '%s not a .py/pyc file' % str(mod.__file__))
continue
# Ignore if the file name does not start with prefix
if prefix is not None and mod.__file__[:len(prefix)] != prefix:
ret[modName] = (False, 'file %s not in prefix %s' % (mod.__file__, prefix))
continue
## ignore if the .pyc is newer than the .py (or if there is no pyc or py)
py = os.path.splitext(mod.__file__)[0] + '.py'
pyc = py + 'c'
if py not in changed and os.path.isfile(pyc) and os.path.isfile(py) and os.stat(pyc).st_mtime >= os.stat(py).st_mtime:
#if debug:
#print "Ignoring module %s; unchanged" % str(mod)
if py in changed:
# already processed this module
continue
changed.append(py) ## keep track of which modules have changed to insure that duplicate-import modules get reloaded.
if not os.path.isfile(py):
# skip modules that lie about their __file__
ret[modName] = (False, '.py does not exist: %s' % py)
continue
# if source file is newer than cache file, then it needs to be reloaded.
pyc = getattr(mod, '__cached__', py + 'c')
if os.path.isfile(pyc) and os.stat(pyc).st_mtime < os.stat(py).st_mtime:
ret[modName] = (False, 'code has not changed since compile')
continue
# keep track of which modules have changed to ensure that duplicate-import modules get reloaded.
changed.append(py)
try:
reload(mod, debug=debug)
except:
ret[modName] = (True, None)
except Exception as exc:
printExc("Error while reloading module %s, skipping\n" % mod)
failed.append(mod.__name__)
ret[modName] = (False, 'reload failed: %s' % traceback.format_exception_only(type(exc), exc))
if len(failed) > 0:
raise Exception("Some modules failed to reload: %s" % ', '.join(failed))
return ret
def reload(module, debug=False, lists=False, dicts=False):
"""Replacement for the builtin reload function:
- Reloads the module as usual

View File

@ -62,11 +62,10 @@ def test_reload():
v1 = (reload_test_mod.C, reload_test_mod.C.sig, reload_test_mod.C.fn, reload_test_mod.C.fn.__func__, c.sig, c.fn, c.fn.__func__)
# write again and reload
open(mod, 'w').write(code.format(path_repr=pgpath_repr, msg="C.fn() Version2"))
remove_cache(mod)
pg.reload.reloadAll(path, debug=True)
result1 = pg.reload.reloadAll(path, debug=True)
if py3:
v2 = (reload_test_mod.C, reload_test_mod.C.sig, reload_test_mod.C.fn, c.sig, c.fn, c.fn.__func__)
else:
@ -90,7 +89,7 @@ def test_reload():
# write again and reload
open(mod, 'w').write(code.format(path_repr=pgpath_repr, msg="C.fn() Version2"))
remove_cache(mod)
pg.reload.reloadAll(path, debug=True)
result2 = pg.reload.reloadAll(path, debug=True)
if py3:
v3 = (reload_test_mod.C, reload_test_mod.C.sig, reload_test_mod.C.fn, c.sig, c.fn, c.fn.__func__)
else: