Wrong `win32clipboard.GetClipboardData` return type annotations
Transferred from https://github.com/mhammond/pywin32/issues/2411 by @KJH-x
Expected behavior and actual behavior
In vscode pylance lint (hover hint), the description of function GetClipboardData is:
(function) def GetClipboardData(
_format: Unknown,
/
) -> str
But infact, the type of clipboard data is not only string, for example the CF_DIB (and other dib formats, are bitmaps), it should be bytes rather than a string.
Steps to reproduce the problem
This is not a runtime bug, This type annotations can be locate at file:
~\.vscode\extensions\ms-python.vscode-pylance-2024.10.1\dist\typeshed-fallback\stubs\pywin32\win32\win32clipboard.pyi
line 8
to confirm this type, copy an image and run
import win32clipboard
from win32.win32clipboard import CF_DIB
win32clipboard.OpenClipboard()
# Get the clipboard data in CF_DIB format
# CF_DIB = 8
if win32clipboard.IsClipboardFormatAvailable(CF_DIB):
dib_data = win32clipboard.GetClipboardData(CF_DIB)
print(type(dib_data))
win32clipboard.CloseClipboard()
After further searching, I found the relevant document: standard-clipboard-formats(MS doc)
After testing, I think it would be better to return typing.Any, since the clipboard format can be customized.
I asked ai for help and tried to validate the format I came across.
| Format Name | Format ID | Format Return Type (AI generated) | Detail Format Using Python Typing | Manual Check? | example |
|---|---|---|---|---|---|
| CF_BITMAP | 2 | HBITMAP | int |
yes | -1257946354 |
| CF_DIB | 8 | BITMAPINFO and bitmap bits | bytes(a fp can be read by PIL image.open(BytesIO( data )) |
yes | b'(...\x07...\x05...\x01. .\x03...\x8c.....................*..*..*......*...*...*...*...*...*...*...*...*...*...*...*...*...*...*...*...*...*...*...*...*...*...*...*...*...*...*...*...*...*...*...*...*...*...*'.=\x00, *=\xff |
| CF_DIBV5 | 17 | BITMAPV5HEADER, color space, bits | bytes(a fp can be read by PIL image.open(BytesIO( data )) |
yes | b'|...\x01...\x07...\x01. .\x03...\x1c.....................*..*..*.......BGRs................................................\x04.................*..*..*......*...*...*...*...*...*...*'.=\x00, *=\xff |
| CF_DIF | 5 | Software Arts' Data Interchange | str |
||
| CF_DSPBITMAP | 0x0082 | Data in bitmap display format | bytes |
||
| CF_DSPENHMETAFILE | 0x008E | Data in enhanced metafile format | bytes |
||
| CF_DSPMETAFILEPICT | 0x0083 | Data in metafile-picture format | bytes |
||
| CF_DSPTEXT | 0x0081 | Data in text format | str |
||
| CF_ENHMETAFILE | 14 | HENHMETAFILE | int |
||
| CF_GDIOBJFIRST | 0x0300 | Application-defined GDI object | Any |
||
| CF_GDIOBJLAST | 0x03FF | Application-defined GDI object | Any |
||
| CF_HDROP | 15 | HDROP (file list) | tuple[str] |
('C:\Users\...',) | |
| CF_LOCALE | 16 | HGLOBAL (locale identifier) LCID | bytes |
yes | b'\x04\x08\x00\x00' |
| CF_METAFILEPICT | 3 | Handle to metafile picture format | int |
||
| CF_OEMTEXT | 7 | OEM character set text | bytes |
yes | b'example string' |
| CF_OWNERDISPLAY | 0x0080 | Owner-display format | None |
||
| CF_PALETTE | 9 | Handle to color palette | int |
||
| CF_PENDATA | 10 | Pen data | bytes |
||
| CF_PRIVATEFIRST | 0x0200 | Private clipboard format | Any |
||
| CF_PRIVATELAST | 0x02FF | Private clipboard format | Any |
||
| CF_RIFF | 11 | Complex audio data (RIFF) | bytes |
||
| CF_SYLK | 4 | Microsoft Symbolic Link (SYLK) | str |
||
| CF_TEXT | 1 | ANSI text | bytes |
yes | b'example string' |
| CF_TIFF | 6 | Tagged Image File Format (TIFF) | bytes |
||
| CF_UNICODETEXT | 13 | Unicode text | str |
yes | 'example string' |
| CF_WAVE | 12 | Standard WAVE audio data | bytes |
||
| UNICODE | True | Not in doc but in win32clipboard.pyi |
bytes |
yes | b'example string' |
W/o overloads I agree for a return type Any. But it shouldn't be too hard to overload, although those constants should also be made literal with Final in https://github.com/python/typeshed/blob/main/stubs/pywin32/win32/win32clipboard.pyi to be truly useful.
Sidenote: The CF_METAFILEPICT format is currently not supported by pywin32 and will always raise.
See: https://github.com/mhammond/pywin32/issues/1589