-
Notifications
You must be signed in to change notification settings - Fork 83
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
Rework of struct definition #209
base: master
Are you sure you want to change the base?
Rework of struct definition #209
Conversation
If I'm not mistaken the definition of anonymous fields in |
Yes, I think so.
It may address some of the points I mentioned, but I still don't like the idea of complicating ctypesgen on behalf of type hints. If this PR were addressed at my fork I'd most likely reject it. That said, could you wait for #205 and then rebase ? |
I would consider calling a seven line function in a place that is not time critical a bearable complication for having type hints.
Maybe I missed something, but it seems to me that you're saying that static analyzers should look for packages that include type information in some non-standard way instead of sticking to well established conventions about type hinting. In this case I strongly disagree. Also in the general case, the assignment of
Thank you for the suggestion, but tbh I won't look into it. I'm already happy. I have my own fork that works for me. This PR is just to give the option to the maintainers to pick stuff that I found helpful. The amount I use ctypesgen does not justify reimplementing my stuff in another way.
I don't think that I'm the right person to address concerning that regard ;) Not that my opinion would matter but I think that the change set is small enough for a single PR. However, I of course agree that a clean separation of individual changes would be marginally better 🤷 |
No. I just mean it's silly from a human POV -- all the info is in there already, and we aren't crafting it dynamically, just declaring it in a slightly different fashion.
Sure, the dumbness lies not in the implementation, but in the nature of the concept.
I understand, but IMO we need another way for optional type hints. |
Historically, the problem has been that ctypesgen got so cluttered with templates over time that the codebase and output became a real mess. My design goal is to revert that and stick to lean ctypes, and keep things simple in the future.
Having to do non-standard things like splitting up fields info, resolving annotations, and fusing it back together through a template decorator at import time (or alternatively duplicating all the content) just doesn't align with my idea of clean code. |
@zwergziege For the record, can you clarify which python version the generated output would now require? |
Or probably easier, declare the type hints in ctypesgen, but behind an opt-in guard, and in that case just accept the duplication with fields. That at least should be a really simple and template-free change. – While this patch results in a smaller output file, it's hard to make optional. PYI would also mean duplication and probably take more code to do (yet that could be done without touching ctypesgen). (Edit: That's considering structs only. I don't know how the situation is for functions. It might be that this couldn't be done without wrappers, so maybe PYI would be better anyway...) |
Using
Thank you for sharing your thoughts on PYI. While I don't particularly like the idea of creating stubs when we also create the actual source, I think it could be a good middle ground solution that can be made optional and not overly ugly to implement. Especially for covering type annotations for primitives (where it would be nice to have union types like |
You can accomplish something similar with a metaclass: from typing import get_type_hints
class TypedStruct(type(ctypes.Structure)):
def __new__(cls, name, bases, namespace):
class _TempClass:
__annotations__ = namespace.get('__annotations__', {})
annotations = get_type_hints(_TempClass)
namespace['_fields_'] = tuple(annotations.items())
namespace['__slots__'] = tuple(annotations.keys())
return type(ctypes.Structure).__new__(cls, name, bases, namespace) Becomes: class struct_MyStruct(Structure, metaclass=TypedStruct):
firstValue: c_float It's a little cleaner. |
@caffeinepills I don't see how this handles the bitfields? Also, will the slots actually work? (i.e. prevent assignment of nonexistent fields?) |
I gave this only a cursory glance but slots should work and adapting for bitfields should be easy. |
This PR is a rework of how structs are defined and is an improvement in three points:
__slots__
(addressing Correct definition of__slots__
on structs (must be defined in class body) #183)This PR supersedes / is based on #185, which already contains some discussion of the changes introduced in this PR. It should mitigate the concerns raised by @mara004 related to #185 but has a slightly larger change set.