Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Added debughelpers. Flask will now tell you if you forget enctype

  • Loading branch information...
commit 2e022cb2727cfa99355261f2c18d1e0fc56e82ee 1 parent a69b437
@mitsuhiko authored
Showing with 65 additions and 0 deletions.
  1. +2 −0  CHANGES
  2. +52 −0 flask/debughelpers.py
  3. +11 −0 flask/wrappers.py
View
2  CHANGES
@@ -16,6 +16,8 @@ Relase date to be decided, codename to be chosen.
OPTIONS implementation.
- HTTP exceptions and Bad Request Key Errors can now be trapped so that they
show up normally in the traceback.
+- Flask in debug mode is now detecting some common problems and tries to
+ warn you about them.
Version 0.7.3
-------------
View
52 flask/debughelpers.py
@@ -0,0 +1,52 @@
+# -*- coding: utf-8 -*-
+"""
+ flask.debughelpers
+ ~~~~~~~~~~~~~~~~~~
+
+ Various helpers to make the development experience better.
+
+ :copyright: (c) 2011 by Armin Ronacher.
+ :license: BSD, see LICENSE for more details.
+"""
+
+
+class DebugFilesKeyError(KeyError, AssertionError):
+ """Raised from request.files during debugging. The idea is that it can
+ provide a better error message than just a generic KeyError/BadRequest.
+ """
+
+ def __init__(self, request, key):
+ form_matches = request.form.getlist(key)
+ buf = ['You tried to access the file "%s" in the request.files '
+ 'dictionary but it does not exist. The mimetype for the request '
+ 'is "%s" instead of "multipart/form-data" which means that no '
+ 'files were transmitted. To fix this error you most likely have '
+ 'to provide enctype="multipart/form-data" in your form.' %
+ (key, request.mimetype)]
+ if form_matches:
+ buf.append('\n\nThe browser instead most likely submitted the '
+ 'filenames in the form. This was submitted: %s' %
+ ', '.join('"%s"' % x for x in form_matches))
+ self.msg = ''.join(buf)
+
+ def __str__(self):
+ return self.msg
+
+
+def make_enctype_error_multidict(request):
+ """Since Flask 0.8 we're monkeypatching the files object in case a
+ request is detected that does not use multipart form data but the files
+ object is accessed.
+ """
+ oldcls = request.files.__class__
+ class newcls(oldcls):
+ def __getitem__(self, key):
+ try:
+ return oldcls.__getitem__(self, key)
+ except KeyError, e:
+ if key not in request.form:
+ raise
+ raise DebugFilesKeyError(request, key)
+ newcls.__name__ = oldcls.__name__
+ newcls.__module__ = oldcls.__module__
+ request.files.__class__ = newcls
View
11 flask/wrappers.py
@@ -12,6 +12,7 @@
from werkzeug.wrappers import Request as RequestBase, Response as ResponseBase
from werkzeug.utils import cached_property
+from .debughelpers import make_enctype_error_multidict
from .helpers import json, _assert_have_json
from .globals import _request_ctx_stack
@@ -99,6 +100,16 @@ def json(self):
return json.loads(self.data, encoding=request_charset)
return json.loads(self.data)
+ def _load_form_data(self):
+ RequestBase._load_form_data(self)
+
+ # in debug mode we're replacing the files multidict with an ad-hoc
+ # subclass that raises a different error for key errors.
+ ctx = _request_ctx_stack.top
+ if ctx is not None and ctx.app.debug and \
+ self.mimetype != 'multipart/form-data':
+ make_enctype_error_multidict(self)
+
class Response(ResponseBase):
"""The response object that is used by default in Flask. Works like the
Please sign in to comment.
Something went wrong with that request. Please try again.