-
Notifications
You must be signed in to change notification settings - Fork 261
Enable ruff ASYNC rules #7441
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Enable ruff ASYNC rules #7441
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -207,7 +207,7 @@ async def open_async(self): | |
| raise InvalidOperation('Cannot open the transport twice') | ||
|
|
||
| if self.auth_script != 'None': | ||
| result = subprocess.run(self.auth_script, shell=True, capture_output=True, text=True, check=False) | ||
| result = subprocess.run(self.auth_script, shell=True, capture_output=True, text=True, check=False) # noqa: ASYNC221 | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This looks like a real issue that should be fixed. Quoting from ruff:
Checks that async functions do not run processes with blocking methods. Why is this bad?Blocking an async function via a blocking call will block the entire Instead of making a blocking call, use an equivalent asynchronous library or function, like Exampleimport subprocess
async def foo():
subprocess.run(cmd)Use instead: import asyncio
async def foo():
asyncio.create_subprocess_shell(cmd)
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think in general to asynchronize this function is good direction for further performance but I don't think it is safe to suspend within this open coroutine without any further changes. In this code we are already pass the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
rg -n -A10 -B10 'def validate_script|authentication_script|auth_script' src testsRepository: aiidateam/aiida-core Length of output: 12873 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "== surrounding code =="
sed -n '1,220p' src/aiida/transports/plugins/ssh_async.py
echo
echo "== similar subprocess usage =="
rg -n "subprocess\.run\(" src/aiida/transports -g '*.py'Repository: aiidateam/aiida-core Length of output: 9775 Avoid 🧰 Tools🪛 OpenGrep (1.25.0)[ERROR] 171-171: Dynamic command passed to subprocess with shell=True. Use a command list without shell=True, or use shlex.quote() to sanitize input. (coderabbit.command-injection.python-shell-true) 🪛 Ruff (0.15.21)[error] 171-171: (S602) 🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||
| if result.returncode != 0: | ||
| self.async_backend.logger.error( | ||
| f'Authentication script {self.auth_script} failed with exit code {result.returncode}\n' | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -84,7 +84,7 @@ def test_pause(self): | |
|
|
||
| async def do_pause(): | ||
| calc_node = self.runner.submit(test_processes.WaitProcess) | ||
| while calc_node.process_state != ProcessState.WAITING: | ||
| while calc_node.process_state != ProcessState.WAITING: # noqa: ASYNC110 | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suspect that in order to avoid sleeping these tests could be refactored to use the https://plumpy.readthedocs.io/en/latest/apidoc/plumpy.process_listener.html |
||
| await asyncio.sleep(0.1) | ||
|
|
||
| assert not calc_node.paused | ||
|
|
@@ -107,7 +107,7 @@ def test_pause_play(self): | |
| async def do_pause_play(): | ||
| calc_node = self.runner.submit(test_processes.WaitProcess) | ||
| assert not calc_node.paused | ||
| while calc_node.process_state != ProcessState.WAITING: | ||
| while calc_node.process_state != ProcessState.WAITING: # noqa: ASYNC110 | ||
| await asyncio.sleep(0.1) | ||
|
|
||
| pause_message = 'Take a seat' | ||
|
|
@@ -136,7 +136,7 @@ def test_kill(self): | |
| async def do_kill(): | ||
| calc_node = self.runner.submit(test_processes.WaitProcess) | ||
| assert not calc_node.is_killed | ||
| while calc_node.process_state != ProcessState.WAITING: | ||
| while calc_node.process_state != ProcessState.WAITING: # noqa: ASYNC110 | ||
| await asyncio.sleep(0.1) | ||
|
|
||
| kill_message = 'Sorry, you have to go mate' | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Checks that async functions do not call blocking
os.pathorpathlib.Pathmethods.
Why is this bad?
Calling some
os.pathorpathlib.Pathmethods in an async function will blockthe entire event loop, preventing it from executing other tasks while waiting
for the operation. This negates the benefits of asynchronous programming.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In order to resolve ASYNC230 and ASYNC240 we would need to take a dependency on a third party library that enables async file IO.