[hacking] N374 do not use time.sleep(0) to yield

We have a centralized nova.utils.cooperative_yield() instead of
time.sleep(0). It is better as it allows to turn off the sleep calls
when the service runs in threaded mode.

Change-Id: I625daec79ee5b7f8b92116f450e21f997cef0546
Signed-off-by: Balazs Gibizer <gibi@redhat.com>
This commit is contained in:
Balazs Gibizer
2025-05-27 15:20:34 +02:00
parent 858494997e
commit d265faed2c
5 changed files with 35 additions and 2 deletions

View File

@@ -79,6 +79,8 @@ Nova Specific Commandments
- [N372] Don't use the setDaemon method. Use the daemon attribute instead.
- [N373] Don't use eventlet specific concurrency primitives. Use the one
from stdlib instead. E.g. eventlet.sleep => time.sleep
- [N374] Don't use time.sleep(0) to trigger eventlet yielding.
Use nova.utils.cooperative_yield() instead.
Creating Unit Tests
-------------------

View File

@@ -145,6 +145,7 @@ six_re = re.compile(r"^(import six(\..*)?|from six(\..*)? import .*)$")
set_daemon_re = re.compile(r"\.setDaemon\(")
eventlet_stdlib_primitives_re = re.compile(
r".*(eventlet|greenthread)\.sleep\(.*")
eventlet_yield_re = re.compile(r".*time\.sleep\(0\).*")
class BaseASTChecker(ast.NodeVisitor):
@@ -1111,10 +1112,26 @@ def check_eventlet_primitives(logical_line, filename):
N373
"""
msg = (
"N373: Use the stdlib concurrency primitive instead of the Eventelt "
"N373: Use the stdlib concurrency primitive instead of the Eventlet "
"specific one")
match = re.match(eventlet_stdlib_primitives_re, logical_line)
if match:
yield (0, msg)
@core.flake8ext
def check_eventlet_yield(logical_line, filename):
"""Check for use of time.sleep(0) triggering eventlet yield
N374
"""
msg = (
"N374: Use the nova.utils.cooperative_yield instead of time.sleep(0) "
"to trigger an eventlet context switch")
match = re.match(eventlet_yield_re, logical_line)
if match:
yield (0, msg)

View File

@@ -1078,3 +1078,16 @@ class HackingTestCase(test.NoDBTestCase):
time.sleep(1)
"""
self._assert_has_no_errors(code, checks.check_eventlet_primitives)
def test_check_eventlet_yield(self):
code = """
time.sleep(0)
"""
errors = [(x + 1, 0, 'N374') for x in range(1)]
self._assert_has_errors(
code, checks.check_eventlet_yield, expected_errors=errors)
code = """
time.sleep(1)
"""
self._assert_has_no_errors(code, checks.check_eventlet_yield)

View File

@@ -85,7 +85,7 @@ def cooperative_yield():
# TODO(ksambor) Remove all cooperative_yield calls after dropping Eventlet
# support.
if not concurrency_mode_threading():
time.sleep(0)
time.sleep(0) # noqa: N374
def destroy_default_executor():

View File

@@ -380,6 +380,7 @@ extension =
N371 = checks:import_stock_mock
N372 = checks:check_set_daemon
N373 = checks:check_eventlet_primitives
N374 = checks:check_eventlet_yield
paths =
./nova/hacking