diff --git a/AUTHORS b/AUTHORS index 6a527fa229a..ab62be513c4 100644 --- a/AUTHORS +++ b/AUTHORS @@ -561,6 +561,7 @@ answer newbie questions, and generally made Django that much better: Raúl Cumplido Remco Wendt Renaud Parent + Renbi Yu Reza Mohammadi rhettg@gmail.com Ricardo Javier Cárdenes Medina diff --git a/django/contrib/admin/apps.py b/django/contrib/admin/apps.py index 3b4f1a30287..b052746ff4e 100644 --- a/django/contrib/admin/apps.py +++ b/django/contrib/admin/apps.py @@ -11,7 +11,7 @@ class SimpleAdminConfig(AppConfig): verbose_name = _("Administration") def ready(self): - checks.register(checks.Tags.admin)(check_admin_app) + checks.register(check_admin_app, checks.Tags.admin) class AdminConfig(SimpleAdminConfig): diff --git a/django/contrib/auth/apps.py b/django/contrib/auth/apps.py index 254a73d3db9..3a0cb1aea1f 100644 --- a/django/contrib/auth/apps.py +++ b/django/contrib/auth/apps.py @@ -10,4 +10,4 @@ class AuthConfig(AppConfig): verbose_name = _("Authentication and Authorization") def ready(self): - checks.register(checks.Tags.models)(check_user_model) + checks.register(check_user_model, checks.Tags.models) diff --git a/django/contrib/contenttypes/apps.py b/django/contrib/contenttypes/apps.py index 0462e3163c9..6fc86337623 100644 --- a/django/contrib/contenttypes/apps.py +++ b/django/contrib/contenttypes/apps.py @@ -9,4 +9,4 @@ class ContentTypesConfig(AppConfig): verbose_name = _("Content Types") def ready(self): - checks.register(checks.Tags.models)(check_generic_foreign_keys) + checks.register(check_generic_foreign_keys, checks.Tags.models) diff --git a/django/core/checks/registry.py b/django/core/checks/registry.py index e8626f03c7f..88cc519a506 100644 --- a/django/core/checks/registry.py +++ b/django/core/checks/registry.py @@ -23,11 +23,11 @@ class CheckRegistry(object): self.registered_checks = [] self.deployment_checks = [] - def register(self, *tags, **kwargs): + def register(self, check=None, *tags, **kwargs): """ - Decorator. Register given function `f` labeled with given `tags`. The - function should receive **kwargs and return list of Errors and - Warnings. + Can be used as a function or a decorator. Register given function + `f` labeled with given `tags`. The function should receive **kwargs + and return list of Errors and Warnings. Example:: @@ -36,6 +36,8 @@ class CheckRegistry(object): def my_check(apps, **kwargs): # ... perform checks and collect `errors` ... return errors + # or + registry.register(my_check, 'mytag', 'anothertag') """ kwargs.setdefault('deploy', False) @@ -49,7 +51,12 @@ class CheckRegistry(object): self.registered_checks.append(check) return check - return inner + if callable(check): + return inner(check) + else: + if check: + tags += (check, ) + return inner def run_checks(self, app_configs=None, tags=None, include_deployment_checks=False): """ Run all registered checks and return list of Errors and Warnings. diff --git a/docs/releases/1.8.txt b/docs/releases/1.8.txt index dda798f0a28..d5281243be4 100644 --- a/docs/releases/1.8.txt +++ b/docs/releases/1.8.txt @@ -364,6 +364,11 @@ Signals the request, was added to the :data:`~django.core.signals.request_started` signal. +System Check Framework +^^^^^^^^^^^^^^^^^^^^^^ + +* :attr:`~django.core.checks.register` can now be used as a function. + Templates ^^^^^^^^^ diff --git a/docs/topics/checks.txt b/docs/topics/checks.txt index 55181688b30..b40b06f1370 100644 --- a/docs/topics/checks.txt +++ b/docs/topics/checks.txt @@ -151,6 +151,20 @@ settings file like this:: These checks will only be run if the :djadminopt:`--deploy` option is passed to the :djadmin:`check` command. +You can also use ``register`` as a function rather than a decorator by +passing a callable object (usually a function) as the first argument +to ``register``. + +The code below is equivalent to the code above:: + + def my_check(app_configs, **kwargs): + ... + register(my_check, Tags.security, deploy=True) + +.. versionchanged:: 1.8 + + The ability to use register as a function was added. + .. _field-checking: Field, Model, and Manager checks diff --git a/tests/check_framework/tests.py b/tests/check_framework/tests.py index 4d29429313e..43b579d383e 100644 --- a/tests/check_framework/tests.py +++ b/tests/check_framework/tests.py @@ -31,17 +31,47 @@ class DummyObj(object): class SystemCheckFrameworkTests(TestCase): def test_register_and_run_checks(self): - calls = [0] - registry = CheckRegistry() - - @registry.register() def f(**kwargs): calls[0] += 1 return [1, 2, 3] + + def f2(**kwargs): + return [4, ] + + def f3(**kwargs): + return [5, ] + + calls = [0] + + # test register as decorator + registry = CheckRegistry() + registry.register()(f) + registry.register("tag1", "tag2")(f2) + registry.register("tag2", deploy=True)(f3) + + # test register as function + registry2 = CheckRegistry() + registry2.register(f) + registry2.register(f2, "tag1", "tag2") + registry2.register(f3, "tag2", deploy=True) + + # check results errors = registry.run_checks() - self.assertEqual(errors, [1, 2, 3]) - self.assertEqual(calls[0], 1) + errors2 = registry2.run_checks() + self.assertEqual(errors, errors2) + self.assertEqual(sorted(errors), [1, 2, 3, 4]) + self.assertEqual(calls[0], 2) + + errors = registry.run_checks(tags=["tag1"]) + errors2 = registry2.run_checks(tags=["tag1"]) + self.assertEqual(errors, errors2) + self.assertEqual(sorted(errors), [4]) + + errors = registry.run_checks(tags=["tag1", "tag2"], include_deployment_checks=True) + errors2 = registry2.run_checks(tags=["tag1", "tag2"], include_deployment_checks=True) + self.assertEqual(errors, errors2) + self.assertEqual(sorted(errors), [4, 5]) class MessageTests(TestCase):