[1.8.x] Fixed #25686 -- Fixed crash on routers without an allow_migrate() method.

Thanks Simon Charette for review.
This commit is contained in:
Josep Cugat 2015-11-06 12:36:38 +01:00 committed by Tim Graham
parent 94d13415d8
commit a42c5376e7
3 changed files with 43 additions and 16 deletions

View File

@ -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:

View File

@ -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`).

View File

@ -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",