Skip to content

also check for kwargs in async115 and async116 #384

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
4 changes: 4 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ Changelog

`CalVer, YY.month.patch <https://calver.org/>`_

25.5.3
======
- :ref:`ASYNC115 <async115>` and :ref:`ASYNC116 <async116>` now also checks kwargs.

25.5.2
======
- :ref:`ASYNC102 <async102>` and :ref:`ASYNC120 <async120>` no longer requires cancel scopes to have a timeout. `(issue #272) <https://github.com/python-trio/flake8-async/issues/272>`_
Expand Down
2 changes: 1 addition & 1 deletion docs/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ adding the following to your ``.pre-commit-config.yaml``:
minimum_pre_commit_version: '2.9.0'
repos:
- repo: https://github.com/python-trio/flake8-async
rev: 25.5.2
rev: 25.5.3
hooks:
- id: flake8-async
# args: ["--enable=ASYNC100,ASYNC112", "--disable=", "--autofix=ASYNC"]
Expand Down
2 changes: 1 addition & 1 deletion flake8_async/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@


# CalVer: YY.month.patch, e.g. first release of July 2022 == "22.7.1"
__version__ = "25.5.2"
__version__ = "25.5.3"


# taken from https://github.com/Zac-HD/shed
Expand Down
67 changes: 40 additions & 27 deletions flake8_async/visitors/visitors.py
Original file line number Diff line number Diff line change
Expand Up @@ -305,11 +305,16 @@ class Visitor115(Flake8AsyncVisitor):
}

def visit_Call(self, node: ast.Call):
if not (m := get_matching_call(node, "sleep")):
return
if (
(m := get_matching_call(node, "sleep"))
and len(node.args) == 1
len(node.args) == 1
and isinstance(node.args[0], ast.Constant)
and node.args[0].value == 0
) or (
len(node.keywords) == 1
and isinstance(node.keywords[0].value, ast.Constant)
and node.keywords[0].value.value == 0
):
self.error(node, m.base)

Expand All @@ -324,32 +329,40 @@ class Visitor116(Flake8AsyncVisitor):
}

def visit_Call(self, node: ast.Call):
if (m := get_matching_call(node, "sleep")) and len(node.args) == 1:
if not (m := get_matching_call(node, "sleep")):
return
if len(node.args) == 1:
arg = node.args[0]
if (
# `trio.sleep(math.inf)`
(isinstance(arg, ast.Attribute) and arg.attr == "inf")
# `trio.sleep(inf)`
or (isinstance(arg, ast.Name) and arg.id == "inf")
# `trio.sleep(float("inf"))`
or (
isinstance(arg, ast.Call)
and isinstance(arg.func, ast.Name)
and arg.func.id == "float"
and len(arg.args)
and isinstance(arg.args[0], ast.Constant)
and arg.args[0].value == "inf"
)
# `trio.sleep(1e999)` (constant value inf)
# `trio.sleep(86401)`
# `trio.sleep(86400.1)`
or (
isinstance(arg, ast.Constant)
and isinstance(arg.value, (int, float))
and arg.value > 86400
)
):
self.error(node, m.base)
elif len(node.keywords) == 1:
arg = node.keywords[0].value
else:
# invalid call, not our problem
return

if (
# `trio.sleep(math.inf)`
(isinstance(arg, ast.Attribute) and arg.attr == "inf")
# `trio.sleep(inf)`
or (isinstance(arg, ast.Name) and arg.id == "inf")
# `trio.sleep(float("inf"))`
or (
isinstance(arg, ast.Call)
and isinstance(arg.func, ast.Name)
and arg.func.id == "float"
and len(arg.args)
and isinstance(arg.args[0], ast.Constant)
and arg.args[0].value == "inf"
)
# `trio.sleep(1e999)` (constant value inf)
# `trio.sleep(86401)`
# `trio.sleep(86400.1)`
or (
isinstance(arg, ast.Constant)
and isinstance(arg.value, (int, float))
and arg.value > 86400
)
):
self.error(node, m.base)


@error_class
Expand Down
13 changes: 13 additions & 0 deletions tests/eval_files/async115.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,19 @@ async def afoo():
time.sleep(0)
sleep(0)

# in trio it's called 'seconds', in anyio it's 'delay', but
# we don't care about the kwarg name. #382
await trio.sleep(seconds=0) # error: 10, "trio"
await trio.sleep(delay=0) # error: 10, "trio"
await trio.sleep(anything=0) # error: 10, "trio"

await trio.sleep(seconds=1)

await trio.sleep()

# we don't care to suppress this
await trio.sleep(0, seconds=1) # error: 10, "trio"


# don't require being inside a function
trio.sleep(0) # error: 0, "trio"
Expand Down
6 changes: 6 additions & 0 deletions tests/eval_files/async116.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ async def foo():
await trio.sleep(inf.inf) # error: 10, "trio"
await trio.sleep(inf.anything)

# in trio the kwarg name is 'seconds', in anyio it's 'delay', but
# we error regardless of what it is. #382
await trio.sleep(seconds=inf) # error: 10, "trio"
await trio.sleep(delay=inf) # error: 10, "trio"
await trio.sleep(anything=inf) # error: 10, "trio"


# does not require the call to be awaited, nor in an async fun
trio.sleep(86401) # error: 0, "trio"
Expand Down
Loading