1
0
mirror of https://github.com/django/django.git synced 2025-04-05 22:16:41 +00:00

Update module level function methods

"global" can be confusing
This commit is contained in:
Jake Howard 2024-10-17 17:22:16 +01:00
parent c92a97267a
commit 646e0746f1
No known key found for this signature in database
GPG Key ID: 57AFB45680EDD477
6 changed files with 51 additions and 49 deletions

View File

@ -8,7 +8,7 @@ from django.db import connections
from django.tasks import DEFAULT_QUEUE_NAME
from django.tasks.exceptions import InvalidTaskError
from django.tasks.task import MAX_PRIORITY, MIN_PRIORITY, Task
from django.tasks.utils import is_global_function
from django.tasks.utils import is_module_level_function
from django.utils import timezone
@ -48,10 +48,8 @@ class BaseTaskBackend(metaclass=ABCMeta):
"""
Determine whether the provided task is one which can be executed by the backend.
"""
if not is_global_function(task.func):
raise InvalidTaskError(
"Task function must be a globally importable function"
)
if not is_module_level_function(task.func):
raise InvalidTaskError("Task function must be defined at a module level")
if not self.supports_async_task and iscoroutinefunction(task.func):
raise InvalidTaskError("Backend does not support async tasks")

View File

@ -7,7 +7,7 @@ from traceback import format_exception
from django.utils.module_loading import import_string
def is_global_function(func):
def is_module_level_function(func):
if not inspect.isfunction(func) or inspect.isbuiltin(func):
return False

View File

@ -1,27 +0,0 @@
"""
This file is used to test function is considered global even if it's not defined yet
because it's covered by a decorator.
"""
from django.tasks.utils import is_global_function
@is_global_function
def really_global_function() -> None:
pass
inner_func_is_global_function = None
def main() -> None:
global inner_func_is_global_function
@is_global_function
def inner_func() -> None:
pass
inner_func_is_global_function = inner_func
main()

View File

@ -0,0 +1,27 @@
"""
This file is used to test function is considered module level even if it's not defined
yet because it's covered by a decorator.
"""
from django.tasks.utils import is_module_level_function
@is_module_level_function
def really_module_level_function() -> None:
pass
inner_func_is_module_level_function = None
def main() -> None:
global inner_func_is_module_level_function
@is_module_level_function
def inner_func() -> None:
pass
inner_func_is_module_level_function = inner_func
main()

View File

@ -219,7 +219,7 @@ class TaskTestCase(SimpleTestCase):
with self.subTest(invalid_function):
with self.assertRaisesMessage(
InvalidTaskError,
"Task function must be a globally importable function",
"Task function must be defined at a module level",
):
task()(invalid_function)

View File

@ -13,39 +13,43 @@ from django.test import SimpleTestCase
from . import tasks as test_tasks
class IsGlobalFunctionTestCase(SimpleTestCase):
class IsModuleLevelFunctionTestCase(SimpleTestCase):
def test_builtin(self):
self.assertFalse(utils.is_global_function(any))
self.assertFalse(utils.is_global_function(isinstance))
self.assertFalse(utils.is_module_level_function(any))
self.assertFalse(utils.is_module_level_function(isinstance))
def test_from_module(self):
self.assertTrue(utils.is_global_function(subprocess.run))
self.assertTrue(utils.is_global_function(subprocess.check_output))
self.assertTrue(utils.is_global_function(test_tasks.noop_task.func))
self.assertTrue(utils.is_module_level_function(subprocess.run))
self.assertTrue(utils.is_module_level_function(subprocess.check_output))
self.assertTrue(utils.is_module_level_function(test_tasks.noop_task.func))
def test_private_function(self):
def private_function():
pass
self.assertFalse(utils.is_global_function(private_function))
self.assertFalse(utils.is_module_level_function(private_function))
def test_coroutine(self):
self.assertTrue(utils.is_global_function(test_tasks.noop_task_async.func))
self.assertTrue(utils.is_module_level_function(test_tasks.noop_task_async.func))
def test_method(self):
self.assertFalse(utils.is_global_function(self.test_method))
self.assertFalse(utils.is_global_function(self.setUp))
self.assertFalse(utils.is_module_level_function(self.test_method))
self.assertFalse(utils.is_module_level_function(self.setUp))
def test_lambda(self):
self.assertFalse(utils.is_global_function(lambda: True))
self.assertFalse(utils.is_module_level_function(lambda: True))
def test_uninitialised_method(self):
# This import has to be here, so the module is loaded during the test
from . import is_global_function_fixture
from . import is_module_level_function_fixture
self.assertTrue(is_global_function_fixture.really_global_function)
self.assertIsNotNone(is_global_function_fixture.inner_func_is_global_function)
self.assertFalse(is_global_function_fixture.inner_func_is_global_function)
self.assertTrue(is_module_level_function_fixture.really_module_level_function)
self.assertIsNotNone(
is_module_level_function_fixture.inner_func_is_module_level_function
)
self.assertFalse(
is_module_level_function_fixture.inner_func_is_module_level_function
)
class JSONNormalizeTestCase(SimpleTestCase):