Skip to content

[pycurl] Fill in missing/Incomplete annotations#15919

Open
Psychosoc1al wants to merge 3 commits into
python:mainfrom
Psychosoc1al:pycurl_update_missing
Open

[pycurl] Fill in missing/Incomplete annotations#15919
Psychosoc1al wants to merge 3 commits into
python:mainfrom
Psychosoc1al:pycurl_update_missing

Conversation

@Psychosoc1al

Copy link
Copy Markdown
Contributor

This PR fills in missing/incomplete type annotations for pycurl package.

Reasoning

Missing annotations:

  • Curl.setopt() (docs, source code): Since this method accepts a wide variety of types, I was a bit scared of a huge annotation. It would include all kinds of objects, ranging from int, str and file-like objects to multiple signatures of Callable and something like [(str | bytes, (str, bytes, (int, str | bytes)))] (for legacy, but supported HTTPPOST). For now, I have annotated it with Any | None. I am open to suggestions on how to structure this more strictly.
  • CurlMulti.setopt() (docs, source code): This method is much more restricted than previous one. I went through documentation and source code and did a small brute-force over all available 12 options for this method to ensure.
  • CurlShare.setopt() (docs, source code): Similar to the above, but only limited to two options that only accept int. Also ensured with a simple brute-force check.
  • CurlMulti.assign() (docs, source code): The value parameter is Any | None by design. None is used to unassign, and other Python objectscan be passed to store their reference so they can be retrieved later in a callback without any processing by curl itself (works roughly like this: store "socket: object" relation -> *something happens on that socket* -> callback called -> object related to that socket is passed to callback).

Incomplete annotations:

  • version_info() (docs, source code): These Incomplete fields use the same underlying string conversion function (vi_str()) as other string-returning fields in the structure. However, these two specific values can also be None, which seems to match libcurl documentation.
  • CurlMulti.perform() (docs, source code): The "status" returned is just an int, similar to other functions: libcurl docs.
  • CurlMulti.fdset() (docs, source code): The C-level file descriptor sets (fd_set) are translated to Python list[int], here source code is pretty straightforward.
  • CurlMulti.info_read() (docs, source code): The return structure is a bit more complex, but described in details in documentation

@github-actions

This comment has been minimized.

@Psychosoc1al Psychosoc1al marked this pull request as draft June 16, 2026 12:00
@github-actions

Copy link
Copy Markdown
Contributor

Diff from mypy_primer, showing the effect of this PR on open source code:

tornado (https://github.com/tornadoweb/tornado)
+ tornado/curl_httpclient.py:55: error: Argument 2 to "setopt" of "CurlMulti" has incompatible type "Callable[[int, int, Any, bytes], None]"; expected "bool | int | list[str | bytes] | tuple[str | bytes, ...] | Callable[[int], Literal[-1, 0] | None] | Callable[[int, int, CurlMulti, Any | None], Literal[-1, 0] | None] | None"  [arg-type]

@Psychosoc1al

Copy link
Copy Markdown
Contributor Author

The first error mentioned in #15919 (comment) was indeed a bug on my end: I had mixed up the unsupported SOCKOPTFUNCTION with the supported SOCKETFUNCTION. I have corrected this, and the annotation now matches the documentation.

However, the failure in #15919 (comment) appears to be a downstream issue. It stems from a loosely annotated, unused multi: Any parameter in Tornado's implementation (tornado/curl_httpclient.py:93), which is now conflicting with the tightened types in pycurl.

How should I proceed with this conflict?

@Psychosoc1al Psychosoc1al marked this pull request as ready for review June 16, 2026 12:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant