Permalink
Browse files

Switch auto reload implementation to use reload()

Auto reloading python code is notoriously tricky.  With this change
the logic switches from direct manipulation of sys.modules (with regex
filters for protection) to calling python's reload() function.  A
stale check is added, to avoid reloading things that haven't changed.
This is still a very basic implementation that will undoubtedly fail
to reload code in some cases, and easily could load code
problematically in other cases.  Just a little reading on mod_python,
mod_wsgi, and django will provide some insight into how challenging
this task can be.
  • Loading branch information...
1 parent e733b27 commit 67dd584ff050e059a71d104a7dbdb1a5dadfb207 @jmcfarlane committed Jun 5, 2011
Showing with 31 additions and 6 deletions.
  1. +31 −6 chula/www/adapters/base.py
View
@@ -2,20 +2,25 @@
Chula base adapter for all supported web adapters
"""
+# Python imports
from copy import deepcopy
import os
import re
import sys
import time
-import chula
+# Project imports
from chula import collection, error, guid, logger
from chula.www import cookie
from chula.www.mapper import ClassPathMapper
from chula.www.mapper import RegexMapper
+# Constants
+EXTRA = {'clientip':''}
RE_HTML = re.compile(r'</body>\s*</html>\s*$', re.IGNORECASE)
-RE_REQ = re.compile(r'(chula|fastcgi|mod_python|wsgi)')
+
+# Cache namespace lookups
+getmtime = os.path.getmtime
class BaseAdapter(object):
def __init__(self, config):
@@ -39,11 +44,31 @@ def _reload_all_modules(self):
return
for k, v in sys.modules.items():
- pyc = getattr(v, '__file__', None)
+ mod = getattr(v, '__file__', None)
+
+ if not mod:
+ continue
+
+ # After reloading mod will end with 'py', not 'pyc'.
+ # Would like to understand this behavior, coding by
+ # observation seems bad.
+ if mod.endswith('.py'):
+ mod += 'c'
- if pyc and os.access(pyc, os.W_OK) and not RE_REQ.search(repr(v)):
- del sys.modules[k]
- self.log.debug('Unloaded module: %s' % k)
+ if not mod.endswith('.pyc'):
+ self.log.debug('Skipping: %s' % mod, extra=EXTRA)
+ continue
+
+ try:
+ stale = getmtime(mod[:-1]) > getmtime(mod)
+ except:
+ msg = 'Auto reload error while analyzing: %s' % k
+ self.log.debug(msg, exc_info=True, extra=EXTRA)
+ stale = False
+
+ if stale:
+ reload(v)
+ self.log.debug('Auto reload successful: %s' % k)
def exception(self, controller, ex):
# Prepare a collection to hold exception context

0 comments on commit 67dd584

Please sign in to comment.