summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosep Cugat <jcugat@gmail.com>2015-11-06 12:36:38 +0100
committerTim Graham <timograham@gmail.com>2015-11-09 10:50:02 -0500
commita42c5376e764712d8ff4a1f9dd3c2d5537722288 (patch)
treebe40d0f39a84bbe6f67a66f945b6b2d32504f89d
parent94d13415d81f24743045bcaa43027c737e2bcf5f (diff)
[1.8.x] Fixed #25686 -- Fixed crash on routers without an allow_migrate() method.
Thanks Simon Charette for review.
-rw-r--r--django/db/utils.py35
-rw-r--r--docs/releases/1.8.7.txt3
-rw-r--r--tests/multiple_database/tests.py21
3 files changed, 43 insertions, 16 deletions
diff --git a/django/db/utils.py b/django/db/utils.py
index e442ac1fc1..ccfcfd4dd4 100644
--- a/django/db/utils.py
+++ b/django/db/utils.py
@@ -326,30 +326,35 @@ class ConnectionRouter(object):
method = router.allow_migrate
except AttributeError:
method = router.allow_syncdb
+ has_deprecated_signature = True
warnings.warn(
'Router.allow_syncdb has been deprecated and will stop working in Django 1.9. '
'Rename the method to allow_migrate.',
RemovedInDjango19Warning, stacklevel=2)
+ else:
+ if HAS_INSPECT_SIGNATURE:
+ sig = inspect.signature(method)
+ has_deprecated_signature = not any(
+ p.kind == inspect.Parameter.VAR_KEYWORD for p in sig.parameters.values()
+ )
+ else:
+ argspec = inspect.getargspec(method)
+ has_deprecated_signature = len(argspec.args) == 3 and not argspec.keywords
+ if has_deprecated_signature:
+ # Raised here because allow_syncdb has to be called with
+ # the deprecated signature but shouldn't show this
+ # warning (only the deprecated method one)
+ warnings.warn(
+ "The signature of allow_migrate has changed from "
+ "allow_migrate(self, db, model) to "
+ "allow_migrate(self, db, app_label, model_name=None, **hints). "
+ "Support for the old signature will be removed in Django 1.10.",
+ RemovedInDjango110Warning)
except AttributeError:
# If the router doesn't have a method, skip to the next one.
continue
- if HAS_INSPECT_SIGNATURE:
- sig = inspect.signature(router.allow_migrate)
- has_deprecated_signature = not any(
- p.kind == inspect.Parameter.VAR_KEYWORD for p in sig.parameters.values()
- )
- else:
- argspec = inspect.getargspec(router.allow_migrate)
- has_deprecated_signature = len(argspec.args) == 3 and not argspec.keywords
-
if has_deprecated_signature:
- warnings.warn(
- "The signature of allow_migrate has changed from "
- "allow_migrate(self, db, model) to "
- "allow_migrate(self, db, app_label, model_name=None, **hints). "
- "Support for the old signature will be removed in Django 1.10.",
- RemovedInDjango110Warning)
model = hints.get('model')
allow = None if model is None else method(db, model)
else:
diff --git a/docs/releases/1.8.7.txt b/docs/releases/1.8.7.txt
index 9aed739c01..f3cfc8e046 100644
--- a/docs/releases/1.8.7.txt
+++ b/docs/releases/1.8.7.txt
@@ -12,4 +12,5 @@ Bugfixes
* Fixed a crash of the debug view during the autumn DST change when
:setting:`USE_TZ` is ``False`` and ``pytz`` is installed.
-* ...
+* Fixed a regression in 1.8.6 that caused database routers without an
+ ``allow_migrate()`` method to crash (:ticket:`25686`).
diff --git a/tests/multiple_database/tests.py b/tests/multiple_database/tests.py
index cad410baff..d329340eec 100644
--- a/tests/multiple_database/tests.py
+++ b/tests/multiple_database/tests.py
@@ -956,6 +956,27 @@ class RouterTestCase(TestCase):
self.assertTrue(router.allow_migrate('default', 'app_label'))
self.assertEqual(force_text(recorded.pop().message), msg)
+ def test_allow_syncdb_deprecation(self):
+ class LegacyRouter(object):
+ def allow_syncdb(self, db, model):
+ assert db == 'default'
+ assert model is User
+ return True
+
+ with override_settings(DATABASE_ROUTERS=[LegacyRouter()]):
+ with warnings.catch_warnings(record=True) as recorded:
+ warnings.filterwarnings('always')
+ msg = (
+ "Router.allow_syncdb has been deprecated and will stop "
+ "working in Django 1.9. Rename the method to allow_migrate."
+ )
+ self.assertTrue(router.allow_migrate_model('default', User))
+ self.assertEqual(force_text(recorded.pop().message), msg)
+ self.assertEqual(recorded, [])
+
+ self.assertTrue(router.allow_migrate('default', 'app_label'))
+ self.assertEqual(force_text(recorded.pop().message), msg)
+
def test_partial_router(self):
"A router can choose to implement a subset of methods"
dive = Book.objects.using('other').create(title="Dive into Python",