Skip to content

Commit

Permalink
Enable ruff flake8-builtins rule (python-trio#2930)
Browse files Browse the repository at this point in the history
* Minor formatting

* Sort `select` and `extend-ignore` lists

* Enable `flake8-builtins` rule

* Fix or ignore names shadowing python builtins

* Ignore "Name shadows builtin" errors because astor gets rid of noqa comments

* Move ignoring `A002` to config file instead of `gen_exports`

* Remove now-unused noqa

* Apply suggestions from code review

Co-authored-by: jakkdl <h6+github@pm.me>

---------

Co-authored-by: jakkdl <h6+github@pm.me>
  • Loading branch information
CoolCat467 and jakkdl authored Jan 25, 2024
1 parent 556df86 commit 05c5df2
Show file tree
Hide file tree
Showing 12 changed files with 85 additions and 56 deletions.
2 changes: 1 addition & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ def add_mapping(

# General information about the project.
project = "Trio"
copyright = "2017, Nathaniel J. Smith"
copyright = "2017, Nathaniel J. Smith" # noqa: A001 # Name shadows builtin
author = "Nathaniel J. Smith"

# The version info for the project you're documenting, acts as replacement for
Expand Down
6 changes: 3 additions & 3 deletions notes-to-self/trace.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,17 +94,17 @@ def task_scheduled(self, task):
except RuntimeError:
pass
else:
id = next(self.ids)
id_ = next(self.ids)
self._write(
ph="s",
cat="wakeup",
id=id,
id=id_,
tid=waker._counter,
)
self._write(
cat="wakeup",
ph="f",
id=id,
id=id_,
tid=task._counter,
)

Expand Down
5 changes: 5 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ allowed-confusables = ["–"]
src = ["src/trio", "notes-to-self"]

select = [
"A", # flake8-builtins
"ASYNC", # flake8-async
"B", # flake8-bugbear
"C4", # flake8-comprehensions
Expand All @@ -108,6 +109,7 @@ select = [
"YTT", # flake8-2020
]
extend-ignore = [
'A002', # builtin-argument-shadowing
'E402', # module-import-not-at-top-of-file (usually OS-specific)
'E501', # line-too-long
'F403', # undefined-local-with-import-star
Expand All @@ -124,6 +126,9 @@ extend-exclude = [
]

[tool.ruff.per-file-ignores]
# F401 is ignoring unused imports. For these particular files,
# these are public APIs where we are importing everything we want
# to export for public use.
'src/trio/__init__.py' = ['F401']
'src/trio/_core/__init__.py' = ['F401']
'src/trio/abc.py' = ['F401']
Expand Down
21 changes: 15 additions & 6 deletions src/trio/_core/_io_kqueue.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,9 @@ def current_kqueue(self) -> select.kqueue:
@contextmanager
@_public
def monitor_kevent(
self, ident: int, filter: int
self,
ident: int,
filter: int,
) -> Iterator[_core.UnboundedQueue[select.kevent]]:
"""TODO: these are implemented, but are currently more of a sketch than
anything real. See `#26
Expand All @@ -138,7 +140,10 @@ def monitor_kevent(

@_public
async def wait_kevent(
self, ident: int, filter: int, abort_func: Callable[[RaiseCancelT], Abort]
self,
ident: int,
filter: int,
abort_func: Callable[[RaiseCancelT], Abort],
) -> Abort:
"""TODO: these are implemented, but are currently more of a sketch than
anything real. See `#26
Expand All @@ -160,7 +165,11 @@ def abort(raise_cancel: RaiseCancelT) -> Abort:
# wait_task_rescheduled does not have its return type typed
return await _core.wait_task_rescheduled(abort) # type: ignore[no-any-return]

async def _wait_common(self, fd: int | _HasFileNo, filter: int) -> None:
async def _wait_common(
self,
fd: int | _HasFileNo,
filter: int,
) -> None:
if not isinstance(fd, int):
fd = fd.fileno()
flags = select.KQ_EV_ADD | select.KQ_EV_ONESHOT
Expand Down Expand Up @@ -260,15 +269,15 @@ def notify_closing(self, fd: int | _HasFileNo) -> None:
if not isinstance(fd, int):
fd = fd.fileno()

for filter in [select.KQ_FILTER_READ, select.KQ_FILTER_WRITE]:
key = (fd, filter)
for filter_ in [select.KQ_FILTER_READ, select.KQ_FILTER_WRITE]:
key = (fd, filter_)
receiver = self._registered.get(key)

if receiver is None:
continue

if type(receiver) is _core.Task:
event = select.kevent(fd, filter, select.KQ_EV_DELETE)
event = select.kevent(fd, filter_, select.KQ_EV_DELETE)
self._kqueue.control([event], 0)
exc = _core.ClosedResourceError("another task closed this fd")
_core.reschedule(receiver, outcome.Error(exc))
Expand Down
26 changes: 13 additions & 13 deletions src/trio/_core/_tests/test_asyncgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,11 @@ async def async_main() -> None:
await _core.wait_all_tasks_blocked()
assert collected.pop() == "abandoned"

aiter = example("exhausted 1")
aiter_ = example("exhausted 1")
try:
assert await aiter.asend(None) == 42
assert await aiter_.asend(None) == 42
finally:
await aiter.aclose()
await aiter_.aclose()
assert collected.pop() == "exhausted 1"

# Also fine if you exhaust it at point of use
Expand All @@ -65,12 +65,12 @@ async def async_main() -> None:
gc_collect_harder()

# No problems saving the geniter when using either of these patterns
aiter = example("exhausted 3")
aiter_ = example("exhausted 3")
try:
saved.append(aiter)
assert await aiter.asend(None) == 42
saved.append(aiter_)
assert await aiter_.asend(None) == 42
finally:
await aiter.aclose()
await aiter_.aclose()
assert collected.pop() == "exhausted 3"

# Also fine if you exhaust it at point of use
Expand Down Expand Up @@ -132,10 +132,10 @@ async def funky_agen() -> AsyncGenerator[int, None]:
await funky_agen().asend(None)

async def async_main() -> None:
aiter = funky_agen()
saved.append(aiter)
assert await aiter.asend(None) == 1
assert await aiter.asend(None) == 2
aiter_ = funky_agen()
saved.append(aiter_)
assert await aiter_.asend(None) == 1
assert await aiter_.asend(None) == 2

_core.run(async_main)
assert record == ["cleanup 2", "cleanup 1"]
Expand Down Expand Up @@ -239,7 +239,7 @@ async def async_main() -> None:
)


async def step_outside_async_context(aiter: AsyncGenerator[int, None]) -> None:
async def step_outside_async_context(aiter_: AsyncGenerator[int, None]) -> None:
# abort_fns run outside of task context, at least if they're
# triggered by a deadline expiry rather than a direct
# cancellation. Thus, an asyncgen first iterated inside one
Expand All @@ -256,7 +256,7 @@ def abort_fn(_: _core.RaiseCancelT) -> _core.Abort:
del abort_fn.aiter # type: ignore[attr-defined]
return _core.Abort.SUCCEEDED

abort_fn.aiter = aiter # type: ignore[attr-defined]
abort_fn.aiter = aiter_ # type: ignore[attr-defined]

async with _core.open_nursery() as nursery:
nursery.start_soon(_core.wait_task_rescheduled, abort_fn)
Expand Down
4 changes: 2 additions & 2 deletions src/trio/_highlevel_open_tcp_listeners.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,9 @@ async def open_tcp_listeners(
listeners = []
unsupported_address_families = []
try:
for family, type, proto, _, sockaddr in addresses:
for family, type_, proto, _, sockaddr in addresses:
try:
sock = tsocket.socket(family, type, proto)
sock = tsocket.socket(family, type_, proto)
except OSError as ex:
if ex.errno == errno.EAFNOSUPPORT:
# If a system only supports IPv4, or only IPv6, it
Expand Down
22 changes: 12 additions & 10 deletions src/trio/_socket.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,8 +300,8 @@ def fromfd(
proto: int = 0,
) -> SocketType:
"""Like :func:`socket.fromfd`, but returns a Trio socket object."""
family, type, proto = _sniff_sockopts_for_fileno(family, type, proto, index(fd))
return from_stdlib_socket(_stdlib_socket.fromfd(fd, family, type, proto))
family, type_, proto = _sniff_sockopts_for_fileno(family, type, proto, index(fd))
return from_stdlib_socket(_stdlib_socket.fromfd(fd, family, type_, proto))


if sys.platform == "win32" or (
Expand Down Expand Up @@ -356,14 +356,16 @@ def socket(
if sf is not None:
return sf.socket(family, type, proto)
else:
family, type, proto = _sniff_sockopts_for_fileno(family, type, proto, fileno)
family, type, proto = _sniff_sockopts_for_fileno( # noqa: A001
family, type, proto, fileno
)
stdlib_socket = _stdlib_socket.socket(family, type, proto, fileno)
return from_stdlib_socket(stdlib_socket)


def _sniff_sockopts_for_fileno(
family: AddressFamily | int,
type: SocketKind | int,
type_: SocketKind | int,
proto: int,
fileno: int | None,
) -> tuple[AddressFamily | int, SocketKind | int, int]:
Expand All @@ -372,23 +374,23 @@ def _sniff_sockopts_for_fileno(
# This object might have the wrong metadata, but it lets us easily call getsockopt
# and then we'll throw it away and construct a new one with the correct metadata.
if sys.platform != "linux":
return family, type, proto
return family, type_, proto
from socket import ( # type: ignore[attr-defined]
SO_DOMAIN,
SO_PROTOCOL,
SO_TYPE,
SOL_SOCKET,
)

sockobj = _stdlib_socket.socket(family, type, proto, fileno=fileno)
sockobj = _stdlib_socket.socket(family, type_, proto, fileno=fileno)
try:
family = sockobj.getsockopt(SOL_SOCKET, SO_DOMAIN)
proto = sockobj.getsockopt(SOL_SOCKET, SO_PROTOCOL)
type = sockobj.getsockopt(SOL_SOCKET, SO_TYPE)
type_ = sockobj.getsockopt(SOL_SOCKET, SO_TYPE)
finally:
# Unwrap it again, so that sockobj.__del__ doesn't try to close our socket
sockobj.detach()
return family, type, proto
return family, type_, proto


################################################################
Expand Down Expand Up @@ -448,7 +450,7 @@ async def wrapper(self: _SocketType, *args: P.args, **kwargs: P.kwargs) -> T:
# @overload likely works, but is extremely verbose.
# NOTE: this function does not always checkpoint
async def _resolve_address_nocp(
type: int,
type_: int,
family: AddressFamily,
proto: int,
*,
Expand Down Expand Up @@ -502,7 +504,7 @@ async def _resolve_address_nocp(
# flags |= AI_ADDRCONFIG
if family == _stdlib_socket.AF_INET6 and not ipv6_v6only:
flags |= _stdlib_socket.AI_V4MAPPED
gai_res = await getaddrinfo(host, port, family, type, proto, flags)
gai_res = await getaddrinfo(host, port, family, type_, proto, flags)
# AFAICT from the spec it's not possible for getaddrinfo to return an
# empty list.
assert len(gai_res) >= 1
Expand Down
10 changes: 5 additions & 5 deletions src/trio/_subprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -682,13 +682,13 @@ async def my_deliver_cancel(process):
"since that's the only way to access the pipe"
)
if isinstance(stdin, (bytes, bytearray, memoryview)):
input = stdin
input_ = stdin
options["stdin"] = subprocess.PIPE
else:
# stdin should be something acceptable to Process
# (None, DEVNULL, a file descriptor, etc) and Process
# will raise if it's not
input = None
input_ = None
options["stdin"] = stdin

if capture_stdout:
Expand All @@ -713,8 +713,8 @@ async def my_deliver_cancel(process):
async def feed_input(stream: SendStream) -> None:
async with stream:
try:
assert input is not None
await stream.send_all(input)
assert input_ is not None
await stream.send_all(input_)
except trio.BrokenResourceError:
pass

Expand All @@ -732,7 +732,7 @@ async def read_output(
proc = await open_process(command, **options) # type: ignore[arg-type, call-overload, unused-ignore]
async with trio.open_nursery() as nursery:
try:
if input is not None:
if input_ is not None:
assert proc.stdin is not None
nursery.start_soon(feed_input, proc.stdin)
proc.stdin = None
Expand Down
6 changes: 3 additions & 3 deletions src/trio/_tests/test_highlevel_open_tcp_listeners.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,16 +210,16 @@ class FakeSocketFactory(SocketFactory):
def socket(
self,
family: AddressFamily | int | None = None,
type: SocketKind | int | None = None,
type_: SocketKind | int | None = None,
proto: int = 0,
) -> tsocket.SocketType:
assert family is not None
assert type is not None
assert type_ is not None
if isinstance(family, int) and not isinstance(family, AddressFamily):
family = AddressFamily(family) # pragma: no cover
if family in self.raise_on_family:
raise OSError(self.raise_on_family[family], "nope")
sock = FakeSocket(family, type, proto)
sock = FakeSocket(family, type_, proto)
self.poison_after -= 1
if self.poison_after == 0:
sock.poison_listen = True
Expand Down
6 changes: 3 additions & 3 deletions src/trio/_tests/test_highlevel_open_tcp_stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,16 +265,16 @@ def __init__(
def socket(
self,
family: AddressFamily | int | None = None,
type: SocketKind | int | None = None,
type_: SocketKind | int | None = None,
proto: int | None = None,
) -> SocketType:
assert isinstance(family, AddressFamily)
assert isinstance(type, SocketKind)
assert isinstance(type_, SocketKind)
assert proto is not None
if family not in self.supported_families:
raise OSError("pretending not to support this family")
self.socket_count += 1
return FakeSocket(self, family, type, proto)
return FakeSocket(self, family, type_, proto)

def _ip_to_gai_entry(
self, ip: str
Expand Down
21 changes: 15 additions & 6 deletions src/trio/_tests/test_socket.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,8 @@ def interesting_fields(
tuple[str, int] | tuple[str, int, int] | tuple[str, int, int, int],
]:
# (family, type, proto, canonname, sockaddr)
family, type, proto, canonname, sockaddr = gai_tup
return (family, type, sockaddr)
family, type_, proto, canonname, sockaddr = gai_tup
return (family, type_, sockaddr)

def filtered(
gai_list: GetAddrInfoResponse,
Expand Down Expand Up @@ -323,8 +323,8 @@ async def test_sniff_sockopts() -> None:
# generate the combinations of families/types we're testing:
sockets = []
for family in [AF_INET, AF_INET6]:
for type in [SOCK_DGRAM, SOCK_STREAM]:
sockets.append(stdlib_socket.socket(family, type))
for type_ in [SOCK_DGRAM, SOCK_STREAM]:
sockets.append(stdlib_socket.socket(family, type_))
for socket in sockets:
# regular Trio socket constructor
tsocket_socket = tsocket.socket(fileno=socket.fileno())
Expand Down Expand Up @@ -977,7 +977,13 @@ async def test_custom_hostname_resolver(monkeygai: MonkeypatchedGAI) -> None:
# This intentionally breaks the signatures used in HostnameResolver
class CustomResolver:
async def getaddrinfo(
self, host: str, port: str, family: int, type: int, proto: int, flags: int
self,
host: str,
port: str,
family: int,
type: int,
proto: int,
flags: int,
) -> tuple[str, str, str, int, int, int, int]:
return ("custom_gai", host, port, family, type, proto, flags)

Expand Down Expand Up @@ -1029,7 +1035,10 @@ async def getnameinfo(
async def test_custom_socket_factory() -> None:
class CustomSocketFactory:
def socket(
self, family: AddressFamily, type: SocketKind, proto: int
self,
family: AddressFamily,
type: SocketKind,
proto: int,
) -> tuple[str, AddressFamily, SocketKind, int]:
return ("hi", family, type, proto)

Expand Down
Loading

0 comments on commit 05c5df2

Please sign in to comment.