The problem with this approach is that at runtime, the attributes return types like int or bytes, while type checkers interpret them as returning c_int or c_char.
Below is the simplest example of a structure created for explanation purposes.
At runtime, the types of these fields are ctypes.CField. In the example below, x is a data descriptor that returns int as the getter and accepts both c_int and int as the setter.
Having stubs with types that deviate from the runtime is not an ideal situation.
Therefore, I propose modifying CField as shown below for use in annotating fields.
I thought it elegant to specify only subclasses of _SimpleCData[_T] as type parameters, given the potential for inferring _T, as shown below.
classBar(Structure):
x: ClassVar[CField[c_int]] # returns `int`, can take `int` or `c_int`
However, current static type system cannot that.
Moreover, considering that there exist not only subclasses of _SimpleCData defined within ctypes, but also third-party developers who define _SimpleCData subclasses within their own projects.
There is the redundancy, but I believe that utilizing the two type parameters would enhance flexibility.
I've only looked briefly at your proposal, but using the descriptor protocol looks indeed to be the right solution in this case. An exploratory PR to judge the effects of such a change would be welcome!
While working, I noticed something.
In fields like Array[c_wchar], we cannot assign an instance of the Array[c_wchar] type; we can only assign types like str.
In the initial PR, I intend to make changes only to _ctypes, ctypes, and wintypes.
For other third-party libraries, as I am not well-versed in their specifications, I would prefer to leave that topic to other maintainers.
Activity
junkmd commented on Aug 13, 2023
I know python/cpython#104533. It might be necessary to communicate with stakeholders in https://discuss.python.org/t/annotation-based-sugar-for-ctypes/26579/ .
srittau commented on Aug 14, 2023
I've only looked briefly at your proposal, but using the descriptor protocol looks indeed to be the right solution in this case. An exploratory PR to judge the effects of such a change would be welcome!
junkmd commented on Aug 16, 2023
While working, I noticed something.
In fields like Array[c_wchar], we cannot assign an instance of the Array[c_wchar] type; we can only assign types like str.
Therefore, I believe it would be more appropriate to have a descriptor protocol with below three type parameters;
They are such as CField[_CT, _RetT, _SetT].
junkmd commented on Aug 16, 2023
In the initial PR, I intend to make changes only to _ctypes, ctypes, and wintypes.
For other third-party libraries, as I am not well-versed in their specifications, I would prefer to leave that topic to other maintainers.
junkmd commented on Aug 17, 2023
I PRed #10595.
junkmd commented on Sep 1, 2023
#10595 is merged.
einarwar commented on Sep 13, 2023
Sorry to comment on a closed issue. I posted the following issue on pyright: microsoft/pyright#5932 (comment) which redirected me back here.
In the following example, both using from_buffer_copy() inside something() and calling it directly on the MyStruct object gives a pyright error
I have not used the ctypes library a lot, am i doing something wrong by calling a classmethod (e.g from_buffer_copy() on a Structure object directly?
junkmd commented on Sep 13, 2023
The curious thing is that Structure is a subclass of _ctypes._CData, which has a from_buffer_copy class method, yet it ended up in this situation.
_StructUnionMeta has __getattr__, and when we access attributes not statically defined in _StructUnionBase, it returns _CField.
However, _StructUnionBase is a subclass of _CData, so from_buffer_copy is already defined.
Before I changed the type stubs, _CField has not been Callable.
Is there some interaction between the descriptor protocol and metaclasses that I'm not aware of?
junkmd commented on Oct 7, 2023
I have the understanding that the issue has been resolved, as mentioned below.
#10777
#10795
microsoft/pyright#5932 (comment), microsoft/pyright#5932 (comment)
https://github.com/microsoft/pyright/releases/tag/1.1.330