Add __slots__ to structs
This is an excellent tool and just what I was looking for. Thank you.
In order for the IDEs to recognize the fields as valid inputs we add __slots__ to all of our ctype.Structs.
Would it be possible to add a step to each struct def to add the slots?
e.g.:
class struct_c__SA_my_struct_t(Structure):
pass
class struct_c__SA_my_struct_t._pack_ = 1 # source:True
class struct_c__SA_my_struct_t._fields_ = [
('my_var1', ctypes.c_ubyte),
('my_var2', ctypes.c_uint16),
]
class struct_c__SA_my_struct_t.__slots__ = ('my_var1','my_var2')
Note that __slots__ must be defined in the actual class body in order to be effective, that's very important.
The above post-definition assignment does nothing except set a casual attribute, i.e. won't enable the special slots feature.
Minimal repro:
>>> from ctypes import *
>>>
>>> class TestStruct (Structure): pass
...
>>> TestStruct.__slots__ = ["a", "b"]
>>> s = TestStruct()
>>> s.c = 1
>>>
>>> class TestStruct (Structure):
... __slots__ = ["a", "b"]
...
>>> s = TestStruct()
>>> s.c = 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'TestStruct' object has no attribute 'c'
@corby Shouldn't this be kept open? I don't think ctypeslib provides slots yet?
The latest commit on master dates a year back, and searching for __slots__ yields nothing.
Apologies. I thought the point of the note was adding slots to the system would be pointless since it won't enforce frozen attributes.
I thought the point of the note was adding slots to the system would be pointless since it won't enforce frozen attributes.
No: Slots are fine, you just have to get the declaration right. What the above example was supposed to express is that assigning slots to a class after definition (as in your initial post) takes no effect beyond setting a casual attribute, whereas declaring them during class creation[^1] does.
It's quite easy to shoot yourself in the foot with a typo in a struct field name, so it is a good idea to (correctly) set up slots on bindings generation to prevent assignment of non-existent fields.
(Defining slots in the class body is not an issue with forward declarations, because they contain just the field names, no actual references.)
[^1]: e.g. in the class body itself, or in a metaclass