[1.8.x] Fixed #25686 -- Fixed crash on routers without an allow_migrate() method.
Thanks Simon Charette for review.
This commit is contained in:
parent
94d13415d8
commit
a42c5376e7
|
@ -326,30 +326,35 @@ class ConnectionRouter(object):
|
||||||
method = router.allow_migrate
|
method = router.allow_migrate
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
method = router.allow_syncdb
|
method = router.allow_syncdb
|
||||||
|
has_deprecated_signature = True
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
'Router.allow_syncdb has been deprecated and will stop working in Django 1.9. '
|
'Router.allow_syncdb has been deprecated and will stop working in Django 1.9. '
|
||||||
'Rename the method to allow_migrate.',
|
'Rename the method to allow_migrate.',
|
||||||
RemovedInDjango19Warning, stacklevel=2)
|
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:
|
except AttributeError:
|
||||||
# If the router doesn't have a method, skip to the next one.
|
# If the router doesn't have a method, skip to the next one.
|
||||||
continue
|
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:
|
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')
|
model = hints.get('model')
|
||||||
allow = None if model is None else method(db, model)
|
allow = None if model is None else method(db, model)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -12,4 +12,5 @@ Bugfixes
|
||||||
* Fixed a crash of the debug view during the autumn DST change when
|
* Fixed a crash of the debug view during the autumn DST change when
|
||||||
:setting:`USE_TZ` is ``False`` and ``pytz`` is installed.
|
: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`).
|
||||||
|
|
|
@ -956,6 +956,27 @@ class RouterTestCase(TestCase):
|
||||||
self.assertTrue(router.allow_migrate('default', 'app_label'))
|
self.assertTrue(router.allow_migrate('default', 'app_label'))
|
||||||
self.assertEqual(force_text(recorded.pop().message), msg)
|
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):
|
def test_partial_router(self):
|
||||||
"A router can choose to implement a subset of methods"
|
"A router can choose to implement a subset of methods"
|
||||||
dive = Book.objects.using('other').create(title="Dive into Python",
|
dive = Book.objects.using('other').create(title="Dive into Python",
|
||||||
|
|
Loading…
Reference in New Issue