summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaude Paroz <claude@2xlibre.net>2014-12-28 18:10:12 +0100
committerClaude Paroz <claude@2xlibre.net>2014-12-29 19:02:45 +0100
commit1d24f073e65113c8c6d974db0504ef7d083809f7 (patch)
treedae0eb0284deedc859b63ffb4f64d14ae2df4da2
parentbae404dea30e8bb0843db94a45d011d637ff2869 (diff)
Fixed #21255 -- Closed connections after management command ran
Thanks kabakov.as@gmail.com for the report, and Aymeric Augustin, Simon Charette for the reviews.
-rw-r--r--django/core/management/base.py3
-rw-r--r--django/db/utils.py8
-rw-r--r--docs/releases/1.8.txt3
-rw-r--r--tests/admin_scripts/tests.py14
4 files changed, 27 insertions, 1 deletions
diff --git a/django/core/management/base.py b/django/core/management/base.py
index 68bcb188e5..869a11bce9 100644
--- a/django/core/management/base.py
+++ b/django/core/management/base.py
@@ -18,6 +18,7 @@ import django
from django.core import checks
from django.core.exceptions import ImproperlyConfigured
from django.core.management.color import color_style, no_style
+from django.db import connections
from django.utils.deprecation import RemovedInDjango19Warning, RemovedInDjango20Warning
from django.utils.encoding import force_str
@@ -398,6 +399,8 @@ class BaseCommand(object):
else:
self.stderr.write('%s: %s' % (e.__class__.__name__, e))
sys.exit(1)
+ finally:
+ connections.close_all()
def execute(self, *args, **options):
"""
diff --git a/django/db/utils.py b/django/db/utils.py
index acb90c0a1a..a355bbe466 100644
--- a/django/db/utils.py
+++ b/django/db/utils.py
@@ -252,6 +252,14 @@ class ConnectionHandler(object):
def all(self):
return [self[alias] for alias in self]
+ def close_all(self):
+ for alias in self:
+ try:
+ connection = getattr(self._connections, alias)
+ except AttributeError:
+ continue
+ connection.close()
+
class ConnectionRouter(object):
def __init__(self, routers=None):
diff --git a/docs/releases/1.8.txt b/docs/releases/1.8.txt
index 7379e1da8f..507aed6584 100644
--- a/docs/releases/1.8.txt
+++ b/docs/releases/1.8.txt
@@ -352,6 +352,9 @@ Logging
Management Commands
^^^^^^^^^^^^^^^^^^^
+* Database connections are now always closed after a management command called
+ from the command line has finished doing its job.
+
* :djadmin:`dumpdata` now has the option :djadminopt:`--output` which allows
specifying the file to which the serialized data is written.
diff --git a/tests/admin_scripts/tests.py b/tests/admin_scripts/tests.py
index 518c83b4be..086e5365a1 100644
--- a/tests/admin_scripts/tests.py
+++ b/tests/admin_scripts/tests.py
@@ -25,7 +25,7 @@ from django.core.management import BaseCommand, CommandError, call_command, colo
from django.utils.encoding import force_text
from django.utils._os import npath, upath
from django.utils.six import StringIO
-from django.test import LiveServerTestCase, TestCase, override_settings
+from django.test import LiveServerTestCase, TestCase, mock, override_settings
from django.test.runner import DiscoverRunner
@@ -1581,6 +1581,18 @@ class CommandTypes(AdminScriptTestCase):
with self.assertRaises(SystemExit):
command.run_from_argv(['', ''])
+ def test_run_from_argv_closes_connections(self):
+ """
+ A command called from the command line should close connections after
+ being executed (#21255).
+ """
+ command = BaseCommand(stderr=StringIO())
+ command.handle = lambda *args, **kwargs: args
+ with mock.patch('django.core.management.base.connections') as mock_connections:
+ command.run_from_argv(['', ''])
+ # Test connections have been closed
+ self.assertTrue(mock_connections.close_all.called)
+
def test_noargs(self):
"NoArg Commands can be executed"
args = ['noargs_command']