summaryrefslogtreecommitdiff
path: root/django
diff options
context:
space:
mode:
authorClaude Paroz <claude@2xlibre.net>2014-07-05 14:43:12 +0200
committerClaude Paroz <claude@2xlibre.net>2014-07-06 21:45:09 +0200
commit1bb8ccdb9e70bee35759f2ada4d661481852ab95 (patch)
tree44f781f9877da4065d982c47c9d2a1232844706b /django
parenta1ddfe440151c81898b94df4d5ea99696398c3f7 (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.py4
-rw-r--r--django/utils/autoreload.py43
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.