Skip to content
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

Re-code flake8-trio and flake8-async rules to match upstream #10416

Merged
merged 22 commits into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,6 @@ quality tools, including:
- [flake8-super](https://pypi.org/project/flake8-super/)
- [flake8-tidy-imports](https://pypi.org/project/flake8-tidy-imports/)
- [flake8-todos](https://pypi.org/project/flake8-todos/)
- [flake8-trio](https://pypi.org/project/flake8-trio/)
- [flake8-type-checking](https://pypi.org/project/flake8-type-checking/)
- [flake8-use-pathlib](https://pypi.org/project/flake8-use-pathlib/)
- [flynt](https://pypi.org/project/flynt/) ([#2102](https://github.com/astral-sh/ruff/issues/2102))
Expand Down
30 changes: 17 additions & 13 deletions crates/ruff_linter/resources/test/fixtures/flake8_async/ASYNC100.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
import urllib.request
import requests
import httpx
import trio


async def foo():
urllib.request.urlopen("http://example.com/foo/bar").read()
async def func():
with trio.fail_after():
...


async def foo():
requests.get()
async def func():
with trio.fail_at():
await ...


async def foo():
httpx.get()
async def func():
with trio.move_on_after():
...


async def foo():
requests.post()
async def func():
with trio.move_at():
await ...


async def foo():
httpx.post()
async def func():
with trio.move_at():
async with trio.open_nursery() as nursery:
...

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ async def func() -> None:
await trio.lowlevel.wait_task_rescheduled(foo)
await trio.lowlevel.wait_writable(foo)

# TRIO105
# ASYNC105
trio.aclose_forcefully(foo)
trio.open_file(foo)
trio.open_ssl_over_tcp_listeners(foo, foo)
Expand Down Expand Up @@ -55,10 +55,10 @@ async def func() -> None:
async with await trio.open_file(foo): # Ok
pass

async with trio.open_file(foo): # TRIO105
async with trio.open_file(foo): # ASYNC105
pass


def func() -> None:
# TRIO105 (without fix)
# ASYNC105 (without fix)
trio.open_file(foo)
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@ async def func():
import trio
from trio import sleep

await trio.sleep(0) # TRIO115
await trio.sleep(0) # ASYNC115
await trio.sleep(1) # OK
await trio.sleep(0, 1) # OK
await trio.sleep(...) # OK
await trio.sleep() # OK

trio.sleep(0) # TRIO115
trio.sleep(0) # ASYNC115
foo = 0
trio.sleep(foo) # OK
trio.sleep(1) # OK
time.sleep(0) # OK

sleep(0) # TRIO115
sleep(0) # ASYNC115

bar = "bar"
trio.sleep(bar)
Expand Down Expand Up @@ -45,18 +45,18 @@ async def func():
def func():
import trio

trio.run(trio.sleep(0)) # TRIO115
trio.run(trio.sleep(0)) # ASYNC115


from trio import Event, sleep


def func():
sleep(0) # TRIO115
sleep(0) # ASYNC115


async def func():
await sleep(seconds=0) # TRIO115
await sleep(seconds=0) # ASYNC115


def func():
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import urllib
import requests
import httpx
import urllib3


async def foo():
urllib.request.urlopen("http://example.com/foo/bar").read() # ASYNC210


async def foo():
requests.get() # ASYNC210


async def foo():
httpx.get() # ASYNC210


async def foo():
requests.post() # ASYNC210


async def foo():
httpx.post() # ASYNC210


async def foo():
requests.get() # ASYNC210
requests.get(...) # ASYNC210
requests.get # Ok
print(requests.get()) # ASYNC210
print(requests.get(requests.get())) # ASYNC210

requests.options() # ASYNC210
requests.head() # ASYNC210
requests.post() # ASYNC210
requests.put() # ASYNC210
requests.patch() # ASYNC210
requests.delete() # ASYNC210
requests.foo()

httpx.options("") # ASYNC210
httpx.head("") # ASYNC210
httpx.post("") # ASYNC210
httpx.put("") # ASYNC210
httpx.patch("") # ASYNC210
httpx.delete("") # ASYNC210
httpx.foo() # Ok

urllib3.request() # ASYNC210
urllib3.request(...) # ASYNC210

urllib.request.urlopen("") # ASYNC210

r = {}
r.get("not a sync http client") # Ok


async def bar():

def request():
pass

request() # Ok

def urlopen():
pass

urlopen() # Ok
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import os
import subprocess

# Violation cases:


async def func():
subprocess.run("foo") # ASYNC221


async def func():
subprocess.call("foo") # ASYNC221


async def func():
subprocess.foo(0) # OK


async def func():
os.wait4(10) # ASYNC222


async def func():
os.wait(12) # ASYNC222


async def foo():
await async_fun(
subprocess.getoutput() # ASYNC221
)
subprocess.Popen() # ASYNC220
os.system() # ASYNC221

system()
os.system.anything()
os.anything()

subprocess.run() # ASYNC221
subprocess.call() # ASYNC221
subprocess.check_call() # ASYNC221
subprocess.check_output() # ASYNC221
subprocess.getoutput() # ASYNC221
subprocess.getstatusoutput() # ASYNC221

await async_fun(
subprocess.getoutput() # ASYNC221
)

subprocess.anything()
subprocess.foo()
subprocess.bar.foo()
subprocess()

os.posix_spawn() # ASYNC221
os.posix_spawnp() # ASYNC221

os.spawn()
os.spawn
os.spawnllll()

os.spawnl() # ASYNC221
os.spawnle() # ASYNC221
os.spawnlp() # ASYNC221
os.spawnlpe() # ASYNC221
os.spawnv() # ASYNC221
os.spawnve() # ASYNC221
os.spawnvp() # ASYNC221
os.spawnvpe() # ASYNC221

P_NOWAIT = os.P_NOWAIT

# if mode is given, and is not os.P_WAIT: ASYNC220
os.spawnl(os.P_NOWAIT) # ASYNC220
os.spawnl(P_NOWAIT) # ASYNC220
os.spawnl(mode=os.P_NOWAIT) # ASYNC220
os.spawnl(mode=P_NOWAIT) # ASYNC220

P_WAIT = os.P_WAIT

# if it is P_WAIT, ASYNC221
os.spawnl(P_WAIT) # ASYNC221
os.spawnl(mode=os.P_WAIT) # ASYNC221
os.spawnl(mode=P_WAIT) # ASYNC221

# other weird cases: ASYNC220
os.spawnl(0) # ASYNC220
os.spawnl(1) # ASYNC220
os.spawnl(foo()) # ASYNC220

# ASYNC222
os.wait() # ASYNC222
os.wait3() # ASYNC222
os.wait4() # ASYNC222
os.waitid() # ASYNC222
os.waitpid() # ASYNC222

os.waitpi()
os.waiti()
Original file line number Diff line number Diff line change
@@ -1,67 +1,62 @@
import os
import subprocess
import time
import io
from pathlib import Path

# Violation cases:


async def func():
open("foo")


async def func():
time.sleep(1)

async def foo():
open("") # ASYNC230
io.open_code("") # ASYNC230

async def func():
subprocess.run("foo")
with open(""): # ASYNC230
...

with open("") as f: # ASYNC230
...

async def func():
subprocess.call("foo")
with foo(), open(""): # ASYNC230
...

async with open(""): # ASYNC230
...

async def func():
subprocess.foo(0)

def foo_sync():
open("")

async def func():
os.wait4(10)
# Violation cases:


async def func():
os.wait(12)
open("foo") # ASYNC230


# Violation cases for pathlib:


async def func():
Path("foo").open() # ASYNC101
Path("foo").open() # ASYNC230


async def func():
p = Path("foo")
p.open() # ASYNC101
p.open() # ASYNC230


async def func():
with Path("foo").open() as f: # ASYNC101
with Path("foo").open() as f: # ASYNC230
pass


async def func() -> None:
p = Path("foo")

async def bar():
p.open() # ASYNC101
p.open() # ASYNC230


async def func() -> None:
(p1, p2) = (Path("foo"), Path("bar"))

p1.open() # ASYNC101
p1.open() # ASYNC230


# Non-violation cases for pathlib:
Expand Down
Loading
Loading