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

bump pyright, introducing warnings for tons of missing docstrings #2910

Merged
merged 9 commits into from
Mar 11, 2024

Conversation

jakkdl
Copy link
Member

@jakkdl jakkdl commented Dec 20, 2023

With microsoft/pyright#6758 released, we now have warnings for missing docstrings on ... 22 classes and 133 functions.

A lot of them are sockets and path/fileIO, which we mostly can ignore. It's maybe time to write a program that filters the output, which would also enable us to run without --ignoreexternal. At least the first ~40 should probably get some simple docstrings written for them though.

trio._core._run.Task
trio._sync.AsyncContextManagerMixin
trio._sync._LockImpl
trio._core._io_epoll._EpollStatistics
trio._core._local._NoValue
trio._core._local.RunVarToken
trio.lowlevel.RunVarToken
trio.lowlevel.Task
trio._core._ki.KIProtectionSignature
trio._core._mock_clock.MockClock.start_clock
trio._core._mock_clock.MockClock.current_time
trio._core._mock_clock.MockClock.deadline_to_sleep_time

# protocol methods
trio._subprocess.HasFileno.fileno
trio._sync._HasAcquireRelease.acquire
trio._sync._HasAcquireRelease.release

# channels
trio.MemoryReceiveChannel
trio._channel.MemoryReceiveChannel
trio._channel.MemoryReceiveChannel.statistics
trio._channel.MemoryChannelStats
trio._channel.MemoryReceiveChannel.aclose
trio.MemorySendChannel
trio._channel.MemorySendChannel
trio._channel.MemorySendChannel.statistics
trio._channel.MemorySendChannel.aclose
trio.open_memory_channel
trio._channel.open_memory_channel

# streams
trio._highlevel_socket.SocketStream.send_all
trio._highlevel_socket.SocketStream.wait_send_all_might_not_block
trio._highlevel_socket.SocketStream.send_eof
trio._highlevel_socket.SocketStream.receive_some
trio._highlevel_socket.SocketStream.aclose
trio._unix_pipes.FdStream.send_all
trio._unix_pipes.FdStream.wait_send_all_might_not_block
trio._unix_pipes.FdStream.receive_some
trio._unix_pipes.FdStream.close
trio._unix_pipes.FdStream.aclose
trio._unix_pipes.FdStream.fileno


# path / fileIO
trio._file_io._HasFileNo
trio._file_io._HasFileNo.fileno
trio._file_io.AsyncIOWrapper.fileno
trio._file_io.AsyncIOWrapper.isatty
trio._file_io.AsyncIOWrapper.readable
trio._file_io.AsyncIOWrapper.seekable
trio._file_io.AsyncIOWrapper.writable
trio._file_io.AsyncIOWrapper.getvalue
trio._file_io.AsyncIOWrapper.getbuffer
trio._file_io.AsyncIOWrapper.flush
trio._file_io.AsyncIOWrapper.read
trio._file_io.AsyncIOWrapper.read1
trio._file_io.AsyncIOWrapper.readall
trio._file_io.AsyncIOWrapper.readinto
trio._file_io.AsyncIOWrapper.readline
trio._file_io.AsyncIOWrapper.readlines
trio._file_io.AsyncIOWrapper.seek
trio._file_io.AsyncIOWrapper.tell
trio._file_io.AsyncIOWrapper.truncate
trio._file_io.AsyncIOWrapper.write
trio._file_io.AsyncIOWrapper.writelines
trio._file_io.AsyncIOWrapper.readinto1
trio._file_io.AsyncIOWrapper.peek
trio._path.Path.as_posix
trio._path.Path.as_uri
trio._path.Path.is_absolute
trio._path.Path.is_reserved
trio._path.Path.match
trio._path.Path.relative_to
trio._path.Path.with_name
trio._path.Path.with_suffix
trio._path.Path.joinpath
trio._path.Path.is_relative_to
trio._path.Path.with_stem
trio._path.Path.cwd
trio._path.Path.stat
trio._path.Path.chmod
trio._path.Path.exists
trio._path.Path.glob
trio._path.Path.is_dir
trio._path.Path.is_file
trio._path.Path.is_symlink
trio._path.Path.is_socket
trio._path.Path.is_fifo
trio._path.Path.is_block_device
trio._path.Path.is_char_device
trio._path.Path.iterdir
trio._path.Path.lchmod
trio._path.Path.lstat
trio._path.Path.mkdir
trio._path.Path.owner
trio._path.Path.group
trio._path.Path.is_mount
trio._path.Path.readlink
trio._path.Path.rename
trio._path.Path.replace
trio._path.Path.resolve
trio._path.Path.rglob
trio._path.Path.rmdir
trio._path.Path.symlink_to
trio._path.Path.hardlink_to
trio._path.Path.touch
trio._path.Path.unlink
trio._path.Path.home
trio._path.Path.absolute
trio._path.Path.expanduser
trio._path.Path.read_bytes
trio._path.Path.read_text
trio._path.Path.samefile
trio._path.Path.write_bytes
trio._path.Path.write_text
trio._path.Path.link_to
trio._path.AsyncAutoWrapperType
trio._path.AsyncAutoWrapperType.generate_forwards
trio._path.AsyncAutoWrapperType.generate_wraps
trio._path.AsyncAutoWrapperType.generate_magic
trio._path.AsyncAutoWrapperType.generate_iter

# socket
trio._socket.SocketType
trio._socket.SocketType.detach
trio._socket.SocketType.fileno
trio._socket.SocketType.getpeername
trio._socket.SocketType.getsockname
trio._socket.SocketType.listen
trio._socket.SocketType.get_inheritable
trio._socket.SocketType.set_inheritable
trio._socket.SocketType.dup
trio._socket.SocketType.close
trio._socket.SocketType.bind
trio._socket.SocketType.shutdown
trio._socket.SocketType.is_readable
trio._socket.SocketType.wait_writable
trio._socket.SocketType.accept
trio._socket.SocketType.connect
trio._socket.SocketType.recv
trio._socket.SocketType.recv_into
trio._socket.SocketType.recvfrom
trio._socket.SocketType.recvfrom_into
trio._socket.SocketType.recvmsg
trio._socket.SocketType.recvmsg_into
trio._socket.SocketType.send
trio._socket.SocketType.sendmsg
trio.socket.SocketType
trio.socket.gaierror
trio.socket.gethostname
trio.socket.herror
trio.socket.htonl
trio.socket.htons
trio.socket.inet_aton
trio.socket.inet_ntoa
trio.socket.inet_ntop
trio.socket.inet_pton
trio.socket.ntohs
trio.socket.if_indextoname
trio.socket.if_nameindex
trio.socket.if_nametoindex
trio.socket.sethostname
trio.socket.CMSG_LEN
trio.socket.CMSG_SPACE

Copy link

codecov bot commented Dec 20, 2023

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 99.64%. Comparing base (accaae4) to head (dd976ba).
Report is 3 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #2910   +/-   ##
=======================================
  Coverage   99.64%   99.64%           
=======================================
  Files         117      117           
  Lines       17634    17643    +9     
  Branches     3172     3176    +4     
=======================================
+ Hits        17572    17581    +9     
  Misses         43       43           
  Partials       19       19           
Files Coverage Δ
src/trio/_socket.py 100.00% <100.00%> (ø)

@jakkdl
Copy link
Member Author

jakkdl commented Dec 20, 2023

Oh right, pyright doesn't exit with a failing status code on missing docstrings. Probably want to fix that too

@Fuyukai
Copy link
Member

Fuyukai commented Dec 20, 2023

I think docstrings are near the bottom of things to worry about when running pyright on trio

@TeamSpen210
Copy link
Contributor

Indeed. Those public Path methods do have docstrings at runtime actually, but not in the stubs.

@CoolCat467 CoolCat467 added docs dependencies Pull requests that update a dependency file labels Dec 20, 2023
@jakkdl
Copy link
Member Author

jakkdl commented Dec 21, 2023

Indeed. Those public Path methods do have docstrings at runtime actually, but not in the stubs.

cool, yeah. Filtering out the ones that has docstrings at runtime the new count is 48 functions

@jakkdl jakkdl mentioned this pull request Feb 18, 2024
Copy link
Contributor

@A5rocks A5rocks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we split out filtering pyright issues so that doesn't have to depend on writing docstrings?

@@ -724,6 +727,22 @@ async def sendmsg(
raise NotImplementedError


# copy docstrings from socket.SocketType
Copy link
Contributor

@A5rocks A5rocks Feb 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment seems a tiny bit out of date. (given that the docstrings are copied from socket.socket or socket.SocketType, as is later mentioned)

@jakkdl
Copy link
Member Author

jakkdl commented Feb 21, 2024

Should we split out filtering pyright issues so that doesn't have to depend on writing docstrings?

filtering out errors a la #2959 falls in the same bin as filtering out docstring errors, so that's what I'm going for here. But yeah I'll open a separate issue for remaining docstrings that are missing, and have them tracked in a json/txt similar to before.

@jakkdl
Copy link
Member Author

jakkdl commented Feb 21, 2024

I kind hate this script, but this should maybe sorta do the job and hopefully not be a complete pain in the ass to maintain.
I'm not sure whether we want to run it in pre-commit, check.sh, or as a test:

  1. pre-commit: makes it much less of a pain to work with in most cases, as the json file can be very easily updated.
  2. in the test suite: makes runtime/platform-specific objects much less of a pain.
  3. check.sh: no real upside, other than it being easy to do and how I implemented it at first.

sorta remaining todos depending on if anybody wants to put in the effort (please do add commits and/or have opinions!):

  1. add more docstrings (whoop whoop)
  2. has_docstring_at_runtime
    a. check that the comment in has_docstring_at_runtime is not lying and actually check those objects has docstrings as they should on their respective platforms.
    b. Add linux objects to that list
    c. Figure out why StapledStream, SSLStream.transport_stream and _HasFileNo are being weird.
    d. Figure out a way of automatically keeping that list up to date. More complicated if running the script separately on different platforms.
  3. categorize the errors in _check_type_completeness.json between "actually missing docstrings" vs "pyright is failing to pick up on something".
    • it'd probably be good if that info could be stored alongside the objects... somehow. I guess one could maybe figure out some way of storing "comments" in the data and preserve it when running with --overwrite-file
      • alternatively: the ones that aren't current errors could be ignored by the script a la has_docstring_at_runtime.
  4. Run this against Path refactor #2959 and figure out the best place to ignore the errors from it. Will be done either way upon merging of either of them.

…nd stuff. Remove logic for 'not warned by pyright but missing docstring' cause that mostly shouldn't be a thing anymore
@jakkdl jakkdl marked this pull request as ready for review February 21, 2024 11:41
@oremanj
Copy link
Member

oremanj commented Feb 21, 2024

At least the first ~40 should probably get some simple docstrings written for them though.

The "channels" and "streams" sections are mostly derived-class implementations of ABC methods, which I don't think need a docstring if their behavior is totally described by the ABC method's docstring. Maybe pyright has an option to allow that?

@jakkdl
Copy link
Member Author

jakkdl commented Feb 21, 2024

At least the first ~40 should probably get some simple docstrings written for them though.

The "channels" and "streams" sections are mostly derived-class implementations of ABC methods, which I don't think need a docstring if their behavior is totally described by the ABC method's docstring. Maybe pyright has an option to allow that?

pyright not having options is why this PR is needed in the first place 🙃
If that's the case, we can maybe just copy them over? Either manually, or with something like

trio/src/trio/_socket.py

Lines 730 to 742 in 3b48476

# copy docstrings from socket.SocketType / socket.socket
for name, obj in SocketType.__dict__.items():
# skip dunders and already defined docstrings
if name.startswith("__") or obj.__doc__:
continue
# try both socket.socket and socket.SocketType
for stdlib_type in _stdlib_socket.socket, _stdlib_socket.SocketType:
stdlib_obj = getattr(stdlib_type, name, None)
if stdlib_obj and stdlib_obj.__doc__:
break
else:
continue
obj.__doc__ = stdlib_obj.__doc__

Copy link
Contributor

@A5rocks A5rocks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't completely follow the logic for the new script but here's some mixed comments

can resolve it, in order to check whether it has a `__doc__` at runtime and
verifytypes misses it because we're doing overly fancy stuff.
"""
assert trio.testing
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confused about the reason behind this assert

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We never directly use trio so isort wants to remove it, I had a comment to that effect previously but lost it for some reason.
Could maybe instead do it with some isort: skip, but that would also mess with import sorting.

Comment on lines 52 to 58
split_i = 1
if name_parts[1] == "tests":
return True
if name_parts[1] in ("_core", "testing"): # noqa: SIM108
split_i = 2
else:
split_i = 1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
split_i = 1
if name_parts[1] == "tests":
return True
if name_parts[1] in ("_core", "testing"): # noqa: SIM108
split_i = 2
else:
split_i = 1
if name_parts[1] == "tests":
return True
split_to = 2 if name_parts[1] in ("_core", "testing") else 2

then split_i -> split_to?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also maybe assert name_parts[0] == "trio" at the top?

if "AsyncIOWrapper" in str(exc) or name in (
# Symbols not existing on all platforms, so we can't dynamically inspect them.
# Manually confirmed to have docstrings but pyright doesn't see them due to
# export shenanigans. TODO: actually manually confirm that.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can probably add a test to make sure these symbols exist on these platforms: the issue then becomes how to keep things up to date.

I've added one possible idea as a diff.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I currently don't care enough to dynamically validate these, so I propose we postpone that to a future time ™️
The two possible issues will be:

  1. We miss one object losing a docstring
  2. somebody encounters an error and needs to do manual intervention: this will happen anyway. The best way around that is to have sufficient amounts of comments that it's not super scary for newbies to do so.

Comment on lines +72 to +76
# darwin
"trio.lowlevel.current_kqueue",
"trio.lowlevel.monitor_kevent",
"trio.lowlevel.wait_kevent",
"trio._core._io_kqueue._KqueueStatistics",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Idea:

Suggested change
# darwin
"trio.lowlevel.current_kqueue",
"trio.lowlevel.monitor_kevent",
"trio.lowlevel.wait_kevent",
"trio._core._io_kqueue._KqueueStatistics",
# --- darwin
"trio.lowlevel.current_kqueue",
"trio.lowlevel.monitor_kevent",
"trio.lowlevel.wait_kevent",
"trio._core._io_kqueue._KqueueStatistics",
# --- darwin

Then the test splits the file on # --- darwin (or whatever platform its running), takes the middle, skipped_symbols = eval('[' + middle + ']'), and check those.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hrm, this starts feeling very silly that it's separate from test_static_tool_sees_class_members.

src/trio/_tests/check_type_completeness.py Outdated Show resolved Hide resolved
src/trio/_tests/check_type_completeness.py Outdated Show resolved Hide resolved
src/trio/_tests/check_type_completeness.py Outdated Show resolved Hide resolved
Copy link
Contributor

@A5rocks A5rocks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Feel free to merge.

Copy link
Member

@CoolCat467 CoolCat467 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, makes sense

@A5rocks A5rocks merged commit b541b8b into python-trio:master Mar 11, 2024
28 checks passed
@jakkdl jakkdl deleted the bump_pyright branch March 11, 2024 10:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dependencies Pull requests that update a dependency file docs
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants