Fixed #9589 -- Made development web server more robust in the presence of a wider variety of code errors.

Thanks goes to contributor with Trac user 'berto' for the patch.
This commit is contained in:
Ramiro Morales 2012-12-12 00:33:03 -03:00
parent b052e6cc95
commit c2a6b2a43f
2 changed files with 33 additions and 3 deletions

View File

@ -91,6 +91,7 @@ answer newbie questions, and generally made Django that much better:
James Bennett James Bennett
Danilo Bargen Danilo Bargen
Shai Berger <shai@platonix.com> Shai Berger <shai@platonix.com>
berto
Julian Bez Julian Bez
Arvis Bickovskis <viestards.lists@gmail.com> Arvis Bickovskis <viestards.lists@gmail.com>
Natalia Bidart <nataliabidart@gmail.com> Natalia Bidart <nataliabidart@gmail.com>

View File

@ -28,7 +28,7 @@
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import os, sys, time, signal import os, sys, time, signal, traceback
try: try:
from django.utils.six.moves import _thread as thread from django.utils.six.moves import _thread as thread
@ -52,10 +52,12 @@ RUN_RELOADER = True
_mtimes = {} _mtimes = {}
_win = (sys.platform == "win32") _win = (sys.platform == "win32")
_error_files = []
def code_changed(): def code_changed():
global _mtimes, _win global _mtimes, _win
filenames = [getattr(m, "__file__", None) for m in sys.modules.values()] filenames = [getattr(m, "__file__", None) for m in sys.modules.values()]
for filename in filter(None, filenames): for filename in filter(None, filenames) + _error_files:
if filename.endswith(".pyc") or filename.endswith(".pyo"): if filename.endswith(".pyc") or filename.endswith(".pyo"):
filename = filename[:-1] filename = filename[:-1]
if filename.endswith("$py.class"): if filename.endswith("$py.class"):
@ -71,9 +73,34 @@ def code_changed():
continue continue
if mtime != _mtimes[filename]: if mtime != _mtimes[filename]:
_mtimes = {} _mtimes = {}
try:
del _error_files[_error_files.index(filename)]
except ValueError:
pass
return True return True
return False return False
def check_errors(fn):
def wrapper(*args, **kwargs):
try:
fn(*args, **kwargs)
except (ImportError, IndentationError, NameError, SyntaxError,
TypeError, AttributeError):
et, ev, tb = sys.exc_info()
if getattr(ev, 'filename', None) is None:
# get the filename from the last item in the stack
filename = traceback.extract_tb(tb)[-1][0]
else:
filename = ev.filename
if filename not in _error_files:
_error_files.append(filename)
raise
return wrapper
def ensure_echo_on(): def ensure_echo_on():
if termios: if termios:
fd = sys.stdin fd = sys.stdin
@ -142,5 +169,7 @@ def main(main_func, args=None, kwargs=None):
reloader = jython_reloader reloader = jython_reloader
else: else:
reloader = python_reloader reloader = python_reloader
reloader(main_func, args, kwargs)
wrapped_main_func = check_errors(main_func)
reloader(wrapped_main_func, args, kwargs)