Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

We’re showing branches in this repository, but you can also compare across forks.

base fork: spookylukey/django
...
head fork: spookylukey/django
  • 7 commits
  • 9 files changed
  • 0 commit comments
  • 6 contributors
Commits on May 11, 2012
Claude Paroz claudep [1.4.x] Fixed #18301 -- Fixed url name in password reset example.
Thanks nicknnn for the report.
589af49
Commits on May 15, 2012
Claude Paroz claudep [1.4.x] Fixed #18019 -- Use threaded runserver only when database sup…
…ports it.
6bb85d9
Commits on May 16, 2012
Adrian Holovaty adrianholovaty [1.4.x] Updated docs/intro/whatsnext.txt to reference Git instead of SVN d3fa8d9
Commits on May 27, 2012
Michael Newman newmaniese [1.4.x] Fixed #18135 -- Close connection used for db version checking
On MySQL when checking the server version, a new connection could be
created but never closed. This could result in open connections on
server startup.

Backport of 4423757.
0f69a16
Commits on Jun 04, 2012
Julien Phalip jphalip [1.4.X] Fixed #18379 -- Made the sensitive_variables decorator work w…
…ith object methods.
4d2fdd4
Florian Apolloner apollo13 [1.4.x] readd imports deleted in 4d2fdd 1c13cc0
Karen Tracey kmtracey Merge pull request #109 from apollo13/fix4d2fdd
Fix test error.
03f1d69
9 django/core/management/commands/testserver.py
View
@@ -35,4 +35,11 @@ def handle(self, *fixture_labels, **options):
# a strange error -- it causes this handle() method to be called
# multiple times.
shutdown_message = '\nServer stopped.\nNote that the test database, %r, has not been deleted. You can explore it on your own.' % db_name
- call_command('runserver', addrport=addrport, shutdown_message=shutdown_message, use_reloader=False, use_ipv6=options['use_ipv6'])
+ use_threading = connection.features.test_db_allows_multiple_connections
+ call_command('runserver',
+ addrport=addrport,
+ shutdown_message=shutdown_message,
+ use_reloader=False,
+ use_ipv6=options['use_ipv6'],
+ use_threading=use_threading
+ )
15 django/db/backends/mysql/base.py
View
@@ -407,11 +407,20 @@ def _rollback(self):
def get_server_version(self):
if not self.server_version:
+ new_connection = False
if not self._valid_connection():
- self.cursor()
- m = server_version_re.match(self.connection.get_server_info())
+ # Ensure we have a connection with the DB by using a temporary
+ # cursor
+ new_connection = True
+ self.cursor().close()
+ server_info = self.connection.get_server_info()
+ if new_connection:
+ # Make sure we close the connection
+ self.connection.close()
+ self.connection = None
+ m = server_version_re.match(server_info)
if not m:
- raise Exception('Unable to determine MySQL version from version string %r' % self.connection.get_server_info())
+ raise Exception('Unable to determine MySQL version from version string %r' % server_info)
self.server_version = tuple([int(x) for x in m.groups()])
return self.server_version
17 django/views/debug.py
View
@@ -155,9 +155,20 @@ def get_traceback_frame_variables(self, request, tb_frame):
Replaces the values of variables marked as sensitive with
stars (*********).
"""
- func_name = tb_frame.f_code.co_name
- func = tb_frame.f_globals.get(func_name)
- sensitive_variables = getattr(func, 'sensitive_variables', [])
+ # Loop through the frame's callers to see if the sensitive_variables
+ # decorator was used.
+ current_frame = tb_frame.f_back
+ sensitive_variables = None
+ while current_frame is not None:
+ if (current_frame.f_code.co_name == 'sensitive_variables_wrapper'
+ and 'sensitive_variables_wrapper' in current_frame.f_locals):
+ # The sensitive_variables decorator was used, so we take note
+ # of the sensitive variables' names.
+ wrapper = current_frame.f_locals['sensitive_variables_wrapper']
+ sensitive_variables = getattr(wrapper, 'sensitive_variables', None)
+ break
+ current_frame = current_frame.f_back
+
cleansed = []
if self.is_active(request) and sensitive_variables:
if sensitive_variables == '__ALL__':
12 django/views/decorators/debug.py
View
@@ -26,13 +26,13 @@ def my_function()
"""
def decorator(func):
@functools.wraps(func)
- def wrapper(*args, **kwargs):
+ def sensitive_variables_wrapper(*args, **kwargs):
if variables:
- wrapper.sensitive_variables = variables
+ sensitive_variables_wrapper.sensitive_variables = variables
else:
- wrapper.sensitive_variables = '__ALL__'
+ sensitive_variables_wrapper.sensitive_variables = '__ALL__'
return func(*args, **kwargs)
- return wrapper
+ return sensitive_variables_wrapper
return decorator
@@ -61,11 +61,11 @@ def my_view(request)
"""
def decorator(view):
@functools.wraps(view)
- def wrapper(request, *args, **kwargs):
+ def sensitive_post_parameters_wrapper(request, *args, **kwargs):
if parameters:
request.sensitive_post_parameters = parameters
else:
request.sensitive_post_parameters = '__ALL__'
return view(request, *args, **kwargs)
- return wrapper
+ return sensitive_post_parameters_wrapper
return decorator
28 docs/intro/whatsnext.txt
View
@@ -93,10 +93,10 @@ reasons:
Django APIs or behaviors change.
Django's documentation is kept in the same source control system as its code. It
-lives in the `django/trunk/docs`_ directory of our Subversion repository. Each
-document online is a separate text file in the repository.
+lives in the `docs`_ directory of our Git repository. Each document online is a
+separate text file in the repository.
-.. _django/trunk/docs: https://code.djangoproject.com/browser/django/trunk/docs
+.. _docs: https://github.com/django/django/tree/master/docs
Where to get it
===============
@@ -138,17 +138,9 @@ If you're using an official release of Django, note that the zipped package
(tarball) of the code includes a ``docs/`` directory, which contains all the
documentation for that release.
-If you're using the development version of Django (aka the Subversion "trunk"),
-note that the ``docs/`` directory contains all of the documentation. You can
-``svn update`` it, just as you ``svn update`` the Python code, in order to get
-the latest changes.
-
-You can check out the latest Django documentation from Subversion using this
-shell command:
-
-.. code-block:: bash
-
- $ svn co https://code.djangoproject.com/svn/django/trunk/docs/ django_docs
+If you're using the development version of Django (aka "trunk"), note that the
+``docs/`` directory contains all of the documentation. You can update your
+Git checkout to get the latest changes.
One low-tech way of taking advantage of the text documentation is by using the
Unix ``grep`` utility to search for a phrase in all of the documentation. For
@@ -202,22 +194,22 @@ __ http://www.gnu.org/software/make/
Differences between versions
============================
-As previously mentioned, the text documentation in our Subversion repository
+As previously mentioned, the text documentation in our Git repository
contains the "latest and greatest" changes and additions. These changes often
include documentation of new features added in the Django development version
--- the Subversion ("trunk") version of Django. For that reason, it's worth
+-- the Git ("trunk") version of Django. For that reason, it's worth
pointing out our policy on keeping straight the documentation for various
versions of the framework.
We follow this policy:
* The primary documentation on djangoproject.com is an HTML version of the
- latest docs in Subversion. These docs always correspond to the latest
+ latest docs in Git. These docs always correspond to the latest
official Django release, plus whatever features we've added/changed in
the framework *since* the latest release.
* As we add features to Django's development version, we try to update the
- documentation in the same Subversion commit transaction.
+ documentation in the same Git commit transaction.
* To distinguish feature changes/additions in the docs, we use the phrase:
"New in version X.Y", being X.Y the next release version (hence, the one
2  docs/topics/auth.txt
View
@@ -1244,7 +1244,7 @@ includes a few other useful built-in views located in
{% load url from future %}
Someone asked for password reset for email {{ email }}. Follow the link below:
- {{ protocol}}://{{ domain }}{% url 'auth_password_reset_confirm' uidb36=uid token=token %}
+ {{ protocol}}://{{ domain }}{% url 'password_reset_confirm' uidb36=uid token=token %}
The same template context is used for subject template. Subject must be
single line plain text string.
8 tests/regressiontests/backends/tests.py
View
@@ -65,6 +65,14 @@ def test_client_encoding(self):
self.assertEqual(connection.connection.encoding, "UTF-8")
self.assertEqual(connection.connection.nencoding, "UTF-8")
+class MySQLTests(TestCase):
+ @unittest.skipUnless(connection.vendor == 'mysql',
+ "Test valid only for MySQL")
+ def test_server_version_connections(self):
+ connection.close()
+ connection.get_server_version()
+ self.assertTrue(connection.connection is None)
+
class DateQuotingTest(TestCase):
def test_django_date_trunc(self):
104 tests/regressiontests/views/tests/debug.py
View
@@ -10,13 +10,12 @@
from django.test.utils import (setup_test_template_loader,
restore_template_loaders)
from django.core.urlresolvers import reverse
-from django.template import TemplateSyntaxError
from django.views.debug import ExceptionReporter
from django.core import mail
from .. import BrokenException, except_args
from ..views import (sensitive_view, non_sensitive_view, paranoid_view,
- custom_exception_reporter_filter_view)
+ custom_exception_reporter_filter_view, sensitive_method_view)
class DebugViewTests(TestCase):
@@ -238,7 +237,8 @@ class ExceptionReportTestMixin(object):
'hash-brown-key': 'hash-brown-value',
'bacon-key': 'bacon-value',}
- def verify_unsafe_response(self, view, check_for_vars=True):
+ def verify_unsafe_response(self, view, check_for_vars=True,
+ check_for_POST_params=True):
"""
Asserts that potentially sensitive info are displayed in the response.
"""
@@ -250,13 +250,14 @@ def verify_unsafe_response(self, view, check_for_vars=True):
self.assertContains(response, 'scrambled', status_code=500)
self.assertContains(response, 'sauce', status_code=500)
self.assertContains(response, 'worcestershire', status_code=500)
+ if check_for_POST_params:
+ for k, v in self.breakfast_data.items():
+ # All POST parameters are shown.
+ self.assertContains(response, k, status_code=500)
+ self.assertContains(response, v, status_code=500)
- for k, v in self.breakfast_data.items():
- # All POST parameters are shown.
- self.assertContains(response, k, status_code=500)
- self.assertContains(response, v, status_code=500)
-
- def verify_safe_response(self, view, check_for_vars=True):
+ def verify_safe_response(self, view, check_for_vars=True,
+ check_for_POST_params=True):
"""
Asserts that certain sensitive info are not displayed in the response.
"""
@@ -269,18 +270,19 @@ def verify_safe_response(self, view, check_for_vars=True):
# Sensitive variable's name is shown but not its value.
self.assertContains(response, 'sauce', status_code=500)
self.assertNotContains(response, 'worcestershire', status_code=500)
+ if check_for_POST_params:
+ for k, v in self.breakfast_data.items():
+ # All POST parameters' names are shown.
+ self.assertContains(response, k, status_code=500)
+ # Non-sensitive POST parameters' values are shown.
+ self.assertContains(response, 'baked-beans-value', status_code=500)
+ self.assertContains(response, 'hash-brown-value', status_code=500)
+ # Sensitive POST parameters' values are not shown.
+ self.assertNotContains(response, 'sausage-value', status_code=500)
+ self.assertNotContains(response, 'bacon-value', status_code=500)
- for k, v in self.breakfast_data.items():
- # All POST parameters' names are shown.
- self.assertContains(response, k, status_code=500)
- # Non-sensitive POST parameters' values are shown.
- self.assertContains(response, 'baked-beans-value', status_code=500)
- self.assertContains(response, 'hash-brown-value', status_code=500)
- # Sensitive POST parameters' values are not shown.
- self.assertNotContains(response, 'sausage-value', status_code=500)
- self.assertNotContains(response, 'bacon-value', status_code=500)
-
- def verify_paranoid_response(self, view, check_for_vars=True):
+ def verify_paranoid_response(self, view, check_for_vars=True,
+ check_for_POST_params=True):
"""
Asserts that no variables or POST parameters are displayed in the response.
"""
@@ -292,14 +294,14 @@ def verify_paranoid_response(self, view, check_for_vars=True):
self.assertNotContains(response, 'scrambled', status_code=500)
self.assertContains(response, 'sauce', status_code=500)
self.assertNotContains(response, 'worcestershire', status_code=500)
+ if check_for_POST_params:
+ for k, v in self.breakfast_data.items():
+ # All POST parameters' names are shown.
+ self.assertContains(response, k, status_code=500)
+ # No POST parameters' values are shown.
+ self.assertNotContains(response, v, status_code=500)
- for k, v in self.breakfast_data.items():
- # All POST parameters' names are shown.
- self.assertContains(response, k, status_code=500)
- # No POST parameters' values are shown.
- self.assertNotContains(response, v, status_code=500)
-
- def verify_unsafe_email(self, view):
+ def verify_unsafe_email(self, view, check_for_POST_params=True):
"""
Asserts that potentially sensitive info are displayed in the email report.
"""
@@ -314,12 +316,13 @@ def verify_unsafe_email(self, view):
self.assertNotIn('scrambled', email.body)
self.assertNotIn('sauce', email.body)
self.assertNotIn('worcestershire', email.body)
- for k, v in self.breakfast_data.items():
- # All POST parameters are shown.
- self.assertIn(k, email.body)
- self.assertIn(v, email.body)
+ if check_for_POST_params:
+ for k, v in self.breakfast_data.items():
+ # All POST parameters are shown.
+ self.assertIn(k, email.body)
+ self.assertIn(v, email.body)
- def verify_safe_email(self, view):
+ def verify_safe_email(self, view, check_for_POST_params=True):
"""
Asserts that certain sensitive info are not displayed in the email report.
"""
@@ -334,15 +337,16 @@ def verify_safe_email(self, view):
self.assertNotIn('scrambled', email.body)
self.assertNotIn('sauce', email.body)
self.assertNotIn('worcestershire', email.body)
- for k, v in self.breakfast_data.items():
- # All POST parameters' names are shown.
- self.assertIn(k, email.body)
- # Non-sensitive POST parameters' values are shown.
- self.assertIn('baked-beans-value', email.body)
- self.assertIn('hash-brown-value', email.body)
- # Sensitive POST parameters' values are not shown.
- self.assertNotIn('sausage-value', email.body)
- self.assertNotIn('bacon-value', email.body)
+ if check_for_POST_params:
+ for k, v in self.breakfast_data.items():
+ # All POST parameters' names are shown.
+ self.assertIn(k, email.body)
+ # Non-sensitive POST parameters' values are shown.
+ self.assertIn('baked-beans-value', email.body)
+ self.assertIn('hash-brown-value', email.body)
+ # Sensitive POST parameters' values are not shown.
+ self.assertNotIn('sausage-value', email.body)
+ self.assertNotIn('bacon-value', email.body)
def verify_paranoid_email(self, view):
"""
@@ -425,6 +429,24 @@ def test_custom_exception_reporter_filter(self):
self.verify_unsafe_response(custom_exception_reporter_filter_view)
self.verify_unsafe_email(custom_exception_reporter_filter_view)
+ def test_sensitive_method(self):
+ """
+ Ensure that the sensitive_variables decorator works with object
+ methods.
+ Refs #18379.
+ """
+ with self.settings(DEBUG=True):
+ self.verify_unsafe_response(sensitive_method_view,
+ check_for_POST_params=False)
+ self.verify_unsafe_email(sensitive_method_view,
+ check_for_POST_params=False)
+
+ with self.settings(DEBUG=False):
+ self.verify_safe_response(sensitive_method_view,
+ check_for_POST_params=False)
+ self.verify_safe_email(sensitive_method_view,
+ check_for_POST_params=False)
+
class AjaxResponseExceptionReporterFilter(TestCase, ExceptionReportTestMixin):
"""
21 tests/regressiontests/views/views.py
View
@@ -17,6 +17,7 @@
from .models import Article
+
def index_page(request):
"""Dummy index page"""
return HttpResponse('<html><body>Dummy page</body></html>')
@@ -228,3 +229,23 @@ def custom_exception_reporter_filter_view(request):
exc_info = sys.exc_info()
send_log(request, exc_info)
return technical_500_response(request, *exc_info)
+
+
+class Klass(object):
+
+ @sensitive_variables('sauce')
+ def method(self, request):
+ # Do not just use plain strings for the variables' values in the code
+ # so that the tests don't return false positives when the function's
+ # source is displayed in the exception report.
+ cooked_eggs = ''.join(['s', 'c', 'r', 'a', 'm', 'b', 'l', 'e', 'd'])
+ sauce = ''.join(['w', 'o', 'r', 'c', 'e', 's', 't', 'e', 'r', 's', 'h', 'i', 'r', 'e'])
+ try:
+ raise Exception
+ except Exception:
+ exc_info = sys.exc_info()
+ send_log(request, exc_info)
+ return technical_500_response(request, *exc_info)
+
+def sensitive_method_view(request):
+ return Klass().method(request)

No commit comments for this range

Something went wrong with that request. Please try again.