I was writing some Python code that uses [ctypes][] for interfacing with the [Windows ToolHelp API](https://docs.microsoft.com/en-us/windows/win32/api/_toolhelp/). Specifically, I had to [define a Python equivalent][structs] for the [PROCESSENTRY32](https://docs.microsoft.com/en-us/windows/win32/api/tlhelp32/ns-tlhelp32-processentry32) struct. Now, the [ctypes][] [struct definitions][structs] are a little annoying because they do not give you type hints. You can add the type hints _on top_ of the `_fields_` attribute but that looks a little silly because you _literally_ [write everything twice][wet]. In Python 3.7+ ((Starting in Python 3.7, dictionaries keep the insertion order.)), you can solve this using a metaclass, and one stigma of metaclasses is that they have very few applications, so I decided to blog about this one: ```python class FieldsFromTypeHints(type(ctypes.Structure)): def __new__(cls, name, bases, namespace): from typing import get_type_hints class AnnotationDummy: __annotations__ = namespace.get('__annotations__', {}) annotations = get_type_hints(AnnotationDummy) namespace['_fields_'] = list(annotations.items()) return type(ctypes.Structure).__new__(cls, name, bases, namespace) ``` and now you can write: ```python class PROCESSENTRY32(ctypes.Structure, metaclass=FieldsFromTypeHints): dwSize : ctypes.c_uint32 cntUsage : ctypes.c_uint32 th32ProcessID : ctypes.c_uint32 th32DefaultHeapID : ctypes.POINTER(ctypes.c_ulong) th32ModuleID : ctypes.c_uint32 cntThreads : ctypes.c_uint32 th32ParentProcessID : ctypes.c_uint32 pcPriClassBase : ctypes.c_long dwFlags : ctypes.c_uint32 szExeFile : ctypes.c_char * 260 ``` The metaclass simply deduces the `_fields_` attribute of the new class for you before the class is _even created_. It might make sense to think of metaclasses as "class creation hooks", i.e. you get to modify what you have written before the class is actually being defined. The following bit is just to be compatible with [PEP-563](https://www.python.org/dev/peps/pep-0563/): ```python from typing import get_type_hints class AnnotationDummy: __annotations__ = namespace.get('__annotations__', {}) annotations = get_type_hints(AnnotationDummy) ``` And then, the following is the actual magic line: ```python namespace['_fields_'] = list(annotations.items()) ``` This adds the attribute `_fields_` before the class is created. [ctypes]: https://docs.python.org/3/library/ctypes.html [structs]: https://docs.python.org/3/library/ctypes.html#structures-and-unions [wet]: https://en.wikipedia.org/wiki/Don%27t_repeat_yourself <a href="https://blag.nullteilerfrei.de/2021/06/20/prettier-struct-definitions-for-python-ctypes/#more-5700" class="more-link">Do you want to know what I was coding?</a>


So you develop in [Microsoft Visual Studio Community Edition](https://www.visualstudio.com/de/vs/community/) and you long for the old days when there was a way to get the [MSDN Library](https://msdn.microsoft.com/en-us/library/) as an offline help file? Fear not, you still can. Open Visual Studio, type `Ctrl`+`Q` to open the quick access bar, usually located in the upper right corner of your interface. Enter `Help Viewer`, it should yield one result by that name, marked as an *"individual component"*. Selecting that entry should allow you to download and install the Help Viewer. Now relaunch Visual Studio and start the Help Viewer via quick access in the same way. You will be prompted whether you want to download some *content* - and I bet you do.