diff options
| author | Claude Paroz <claude@2xlibre.net> | 2014-07-05 14:43:12 +0200 |
|---|---|---|
| committer | Claude Paroz <claude@2xlibre.net> | 2014-07-06 21:45:09 +0200 |
| commit | 1bb8ccdb9e70bee35759f2ada4d661481852ab95 (patch) | |
| tree | 44f781f9877da4065d982c47c9d2a1232844706b /django | |
| parent | a1ddfe440151c81898b94df4d5ea99696398c3f7 (diff) | |
[1.7.x] Fixed pyinotify performance regression in 15f82c7011
Refs #9722. Thanks Tim Graham for the review.
Backport of 6d302f639 from master.
Diffstat (limited to 'django')
| -rw-r--r-- | django/contrib/staticfiles/handlers.py | 4 | ||||
| -rw-r--r-- | django/utils/autoreload.py | 43 |
2 files changed, 37 insertions, 10 deletions
diff --git a/django/contrib/staticfiles/handlers.py b/django/contrib/staticfiles/handlers.py index bb54db6b7d..e711f9a476 100644 --- a/django/contrib/staticfiles/handlers.py +++ b/django/contrib/staticfiles/handlers.py @@ -12,6 +12,10 @@ class StaticFilesHandler(WSGIHandler): WSGI middleware that intercepts calls to the static files directory, as defined by the STATIC_URL setting, and serves those files. """ + # May be used to differentiate between handler types (e.g. in a + # request_finished signal) + handles_files = True + def __init__(self, application): self.application = application self.base_url = urlparse(self.get_base_url()) diff --git a/django/utils/autoreload.py b/django/utils/autoreload.py index 482ae060a5..e75ee5a15c 100644 --- a/django/utils/autoreload.py +++ b/django/utils/autoreload.py @@ -77,17 +77,28 @@ _mtimes = {} _win = (sys.platform == "win32") _error_files = [] +_cached_modules = set() +_cached_filenames = [] - -def gen_filenames(): +def gen_filenames(only_new=False): """ - Yields a generator over filenames referenced in sys.modules and translation + Returns a list of filenames referenced in sys.modules and translation files. """ - filenames = [filename.__file__ for filename in list(sys.modules.values()) - if hasattr(filename, '__file__')] + global _cached_modules, _cached_filenames + module_values = set(sys.modules.values()) + if _cached_modules == module_values: + # No changes in module list, short-circuit the function + if only_new: + return [] + else: + return _cached_filenames + + new_modules = module_values - _cached_modules + new_filenames = [filename.__file__ for filename in new_modules + if hasattr(filename, '__file__')] - if settings.USE_I18N: + if not _cached_filenames and settings.USE_I18N: # Add the names of the .mo files that can be generated # by compilemessages management command to the list of files watched. basedirs = [os.path.join(os.path.dirname(os.path.dirname(__file__)), @@ -102,9 +113,14 @@ def gen_filenames(): for dirpath, dirnames, locale_filenames in os.walk(basedir): for filename in locale_filenames: if filename.endswith('.mo'): - filenames.append(os.path.join(dirpath, filename)) + new_filenames.append(os.path.join(dirpath, filename)) - for filename in filenames + _error_files: + if only_new: + filelist = new_filenames + else: + filelist = _cached_filenames + new_filenames + _error_files + filenames = [] + for filename in filelist: if not filename: continue if filename.endswith(".pyc") or filename.endswith(".pyo"): @@ -112,7 +128,10 @@ def gen_filenames(): if filename.endswith("$py.class"): filename = filename[:-9] + ".py" if os.path.exists(filename): - yield filename + filenames.append(filename) + _cached_modules = _cached_modules.union(new_modules) + _cached_filenames += new_filenames + return filenames def reset_translations(): @@ -142,6 +161,10 @@ def inotify_code_changed(): notifier = pyinotify.Notifier(wm, EventHandler()) def update_watch(sender=None, **kwargs): + if sender and getattr(sender, 'handles_files', False): + # No need to update watches when request serves files. + # (sender is supposed to be a django.core.handlers.BaseHandler subclass) + return mask = ( pyinotify.IN_MODIFY | pyinotify.IN_DELETE | @@ -150,7 +173,7 @@ def inotify_code_changed(): pyinotify.IN_MOVED_TO | pyinotify.IN_CREATE ) - for path in gen_filenames(): + for path in gen_filenames(only_new=True): wm.add_watch(path, mask) # New modules may get imported when a request is processed. |
