[clang] Fix all mypy --strict errors in clang python binding (PR #101784)

via cfe-commits cfe-commits at lists.llvm.org
Sat Aug 3 16:15:49 PDT 2024


github-actions[bot] wrote:

<!--LLVM CODE FORMAT COMMENT: {darker}-->


:warning: Python code formatter, darker found issues in your code. :warning:

<details>
<summary>
You can test this locally with the following command:
</summary>

``````````bash
darker --check --diff -r 98e4413a38f286147b863a6ead9625228ab0ec7d...c3ebad6a3447101cb307d5ca118d28d1b78b4dbe clang/bindings/python/clang/ctyped.py clang/bindings/python/tests/ctyped/__init__.py clang/bindings/python/tests/ctyped/test_stub_conversion.py clang/bindings/python/clang/cindex.py clang/bindings/python/tests/cindex/test_translation_unit.py clang/bindings/python/tests/cindex/test_type.py
``````````

</details>

<details>
<summary>
View the diff from darker here.
</summary>

``````````diff
--- clang/cindex.py	2024-08-03 14:40:40.000000 +0000
+++ clang/cindex.py	2024-08-03 23:15:21.593600 +0000
@@ -60,14 +60,33 @@
 # o cleanup ctypes wrapping, would be nice to separate the ctypes details more
 #   clearly, and hide from the external interface (i.e., help(cindex)).
 #
 # o implement additional SourceLocation, SourceRange, and File methods.
 
-from ctypes import (c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint, c_long,  # pyright: ignore[reportUnusedImport]
-                    c_ulong, c_longlong,c_ulonglong, c_size_t, c_ssize_t,  # pyright: ignore[reportUnusedImport]
-                    c_bool, c_char, c_wchar, c_float, c_double, c_longdouble,  # pyright: ignore[reportUnusedImport]
-                    c_char_p, c_wchar_p, c_void_p)  # pyright: ignore[reportUnusedImport]
+from ctypes import (
+    c_byte,
+    c_ubyte,
+    c_short,
+    c_ushort,
+    c_int,
+    c_uint,
+    c_long,  # pyright: ignore[reportUnusedImport]
+    c_ulong,
+    c_longlong,
+    c_ulonglong,
+    c_size_t,
+    c_ssize_t,  # pyright: ignore[reportUnusedImport]
+    c_bool,
+    c_char,
+    c_wchar,
+    c_float,
+    c_double,
+    c_longdouble,  # pyright: ignore[reportUnusedImport]
+    c_char_p,
+    c_wchar_p,
+    c_void_p,
+)  # pyright: ignore[reportUnusedImport]
 from ctypes import py_object, Structure, POINTER, byref, cast, cdll
 from .ctyped import *
 from .ctyped import ANNO_CONVERTIBLE, generate_metadata
 
 import os
@@ -114,11 +133,11 @@
             ...
 
 
 # Python 3 strings are unicode, translate them to/from utf8 for C-interop.
 class c_interop_string(c_char_p):
-    def __init__(self, p: 'CInteropString' = None):
+    def __init__(self, p: "CInteropString" = None):
         if p is None:
             p = ""
         if isinstance(p, str):
             p = p.encode("utf8")
         super(c_char_p, self).__init__(p)
@@ -132,11 +151,11 @@
         if val is None:
             return None
         return val.decode("utf8")
 
     @classmethod
-    def from_param(cls, param: 'CInteropString') -> c_interop_string:
+    def from_param(cls, param: "CInteropString") -> c_interop_string:
         if isinstance(param, str):
             return cls(param)
         if isinstance(param, bytes):
             return cls(param)
         if param is None:
@@ -168,11 +187,11 @@
 
 ### Exception Classes ###
 
 
 class CXError(Exception):
-    '''Represents C error of type enum CXErrorCode.'''
+    """Represents C error of type enum CXErrorCode."""
 
     # A generic error code, no further details are available.
     #
     # Errors of this kind can get their own specific error codes in future
     # libclang versions.
@@ -297,11 +316,15 @@
 
     def __del__(self) -> None:
         conf.lib.clang_disposeString(self)
 
     @staticmethod
-    def from_result(res: _CXString, fn: Optional[Callable[..., _CXString]] = None, args: Optional[Tuple[Any, ...]] = None) -> str:
+    def from_result(
+        res: _CXString,
+        fn: Optional[Callable[..., _CXString]] = None,
+        args: Optional[Tuple[Any, ...]] = None,
+    ) -> str:
         assert isinstance(res, _CXString)
         pystr: str | None = conf.lib.clang_getCString(res)
         if pystr is None:
             return ""
         return pystr
@@ -329,11 +352,13 @@
                 f = None
             self._data = (f, int(l.value), int(c.value), int(o.value))
         return self._data
 
     @staticmethod
-    def from_position(tu: TranslationUnit, file: File, line: int, column: int) -> SourceLocation:
+    def from_position(
+        tu: TranslationUnit, file: File, line: int, column: int
+    ) -> SourceLocation:
         """
         Retrieve the source location associated with a given file/line/column in
         a particular translation unit.
         """
         return conf.lib.clang_getLocation(tu, file, line, column)
@@ -445,12 +470,14 @@
             return False
         if (
             other.file is not None
             and self.start.file is not None
             and self.end.file is not None
-            and (other.file.name != self.start.file.name
-                 or other.file.name != self.end.file.name)
+            and (
+                other.file.name != self.start.file.name
+                or other.file.name != self.end.file.name
+            )
         ):
             # same file name
             return False
         # same file, in between lines
         if self.start.line < other.line < self.end.line:
@@ -655,11 +682,13 @@
 
     def __del__(self) -> None:
         conf.lib.clang_disposeTokens(self._tu, self._memory, self._count)
 
     @staticmethod
-    def get_tokens(tu: TranslationUnit, extent: SourceRange) -> Generator[Token, None, None]:
+    def get_tokens(
+        tu: TranslationUnit, extent: SourceRange
+    ) -> Generator[Token, None, None]:
         """Helper method to return all tokens in an extent.
 
         This functionality is needed multiple places in this module. We define
         it here because it seems like a logical place.
         """
@@ -692,11 +721,12 @@
 ### Cursor Kinds ###
 class BaseEnumeration(Enum):
     """
     Common base class for named enumerations held in sync with Index.h values.
     """
-    value: int # pyright: ignore[reportIncompatibleMethodOverride]
+
+    value: int  # pyright: ignore[reportIncompatibleMethodOverride]
 
     def from_param(self) -> int:
         return self.value
 
     @classmethod
@@ -744,10 +774,11 @@
         return conf.lib.clang_isReference(self)
 
     def is_expression(self) -> bool:
         """Test if this is an expression kind."""
         return conf.lib.clang_isExpression(self)
+
     def is_statement(self) -> bool:
         """Test if this is a statement kind."""
         return conf.lib.clang_isStatement(self)
 
     def is_attribute(self) -> bool:
@@ -2214,11 +2245,13 @@
         Retrieve the width of a bitfield.
         """
         return conf.lib.clang_getFieldDeclBitWidth(self)
 
     @staticmethod
-    def from_result(res: Cursor, fn: Callable[..., Cursor], args: Tuple[Any, ...]) -> Optional[Cursor]:
+    def from_result(
+        res: Cursor, fn: Callable[..., Cursor], args: Tuple[Any, ...]
+    ) -> Optional[Cursor]:
         assert isinstance(res, Cursor)
         # FIXME: There should just be an isNull method.
         if res == conf.lib.clang_getNullCursor():
             return None
 
@@ -2238,11 +2271,13 @@
 
         res._tu = tu
         return res
 
     @staticmethod
-    def from_cursor_result(res: Cursor, fn: Callable[..., Cursor], args: Tuple[Any, ...]) -> Optional[Cursor]:
+    def from_cursor_result(
+        res: Cursor, fn: Callable[..., Cursor], args: Tuple[Any, ...]
+    ) -> Optional[Cursor]:
         assert isinstance(res, Cursor)
         if res == conf.lib.clang_getNullCursor():
             return None
 
         res._tu = args[0]._tu
@@ -2527,11 +2562,13 @@
 
                 return self.length
 
             def __getitem__(self, key: int) -> Type:
                 # FIXME Support slice objects.
-                if not isinstance(key, int): # pyright: ignore[reportUnnecessaryIsInstance]
+                if not isinstance(
+                    key, int
+                ):  # pyright: ignore[reportUnnecessaryIsInstance]
                     raise TypeError("Must supply a non-negative int.")
 
                 if key < 0:
                     raise IndexError("Only non-negative indexes are accepted.")
 
@@ -2580,11 +2617,11 @@
     @property
     def translation_unit(self) -> TranslationUnit:
         """The TranslationUnit to which this Type is associated."""
         # If this triggers an AttributeError, the instance was not properly
         # instantiated.
-        return self._tu # type: ignore[no-any-return]
+        return self._tu  # type: ignore[no-any-return]
 
     @staticmethod
     def from_result(res: Type, fn: Callable[..., Type], args: Tuple[Any, ...]) -> Type:
         assert isinstance(res, Type)
 
@@ -2728,11 +2765,11 @@
 
         def visitor(field: Cursor, children: List[Cursor]) -> int:
             assert field != conf.lib.clang_getNullCursor()
 
             # Create reference to TU so it isn't GC'd before Cursor.
-            field._tu = self._tu # pyright: ignore[reportPrivateUsage]
+            field._tu = self._tu  # pyright: ignore[reportPrivateUsage]
             fields.append(field)
             return 1  # continue
 
         fields: List[Cursor] = []
         conf.lib.clang_Type_visitFields(self, fields_visit_callback(visitor), fields)
@@ -2751,11 +2788,11 @@
     def spelling(self) -> str:
         """Retrieve the spelling of this Type."""
         return conf.lib.clang_getTypeSpelling(self)
 
     def __eq__(self, other: object) -> bool:
-        if other is None: # in case user write `x.type == None`
+        if other is None:  # in case user write `x.type == None`
             return False
         elif not isinstance(other, Type):
             return NotImplemented
         else:
             return conf.lib.clang_equalTypes(self, other)
@@ -2774,21 +2811,25 @@
 class ClangObject:
     """
     A helper for Clang objects. This class helps act as an intermediary for
     the ctypes library and the Clang CIndex library.
     """
+
     obj: CObjectP
     _as_parameter_: CObjectP
 
     def __init__(self, obj: CObjectP):
         assert isinstance(obj, c_object_p) and obj
         self.obj = self._as_parameter_ = obj
 
     def from_param(self) -> CObjectP:
         return self._as_parameter_
 
-ClangObjectParam = Annotated[TUnion[CObjectP, ClangObject], ANNO_CONVERTIBLE, c_object_p]
+
+ClangObjectParam = Annotated[
+    TUnion[CObjectP, ClangObject], ANNO_CONVERTIBLE, c_object_p
+]
 
 
 class _CXUnsavedFile(Structure):
     """Helper for passing unsaved file arguments."""
 
@@ -2796,11 +2837,14 @@
 
     name: r_char_p
     contents: r_char_p
     length: r_ulong
 
-UnsavedFileInfo: TypeAlias = Tuple['FsPath', TUnion['StrOrBytes', 'SupportsReadStringData']]
+
+UnsavedFileInfo: TypeAlias = Tuple[
+    "FsPath", TUnion["StrOrBytes", "SupportsReadStringData"]
+]
 
 # Functions calls through the python interface are rather slow. Fortunately,
 # for most symboles, we do not need to perform a function call. Their spelling
 # never changes and is consequently provided by this spelling cache.
 SpellingCache = {
@@ -2955,15 +2999,15 @@
 
     @property
     def brief_comment(self) -> str:
         if conf.function_exists("clang_getCompletionBriefComment"):
             return conf.lib.clang_getCompletionBriefComment(self.obj)
-        return ''
+        return ""
 
     def __repr__(self) -> str:
         return (
-            " | ".join([str(a) for a in self]) # type: ignore[attr-defined]
+            " | ".join([str(a) for a in self])  # type: ignore[attr-defined]
             + " || Priority: "
             + str(self.priority)
             + " || Availability: "
             + str(self.availability)
             + " || Brief comment: "
@@ -3010,20 +3054,22 @@
         if len(self) <= key:
             raise IndexError
         # FIXME: Current type stub of ctypes does not provide signature of
         #        __getitem__ in class _Pointer. Remove this ignore when they
         #        fixed that.
-        return self.results[key] # type: ignore[no-any-return]
+        return self.results[key]  # type: ignore[no-any-return]
 
 
 class CodeCompletionResults(ClangObject):
-    obj: CPointer[CCRStructure] # type: ignore[assignment]
-    _as_parameter_: CPointer[CCRStructure] # type: ignore[assignment]
+    obj: CPointer[CCRStructure]  # type: ignore[assignment]
+    _as_parameter_: CPointer[CCRStructure]  # type: ignore[assignment]
 
     def __init__(self, ptr: CPointer[CCRStructure]):
         assert isinstance(ptr, POINTER(CCRStructure)) and ptr
-        self.obj = self._as_parameter_ = ptr # pyright: ignore[reportIncompatibleVariableOverride]
+        self.obj = (
+            self._as_parameter_
+        ) = ptr  # pyright: ignore[reportIncompatibleVariableOverride]
 
     def __del__(self) -> None:
         conf.lib.clang_disposeCodeCompleteResults(self)
 
     @property
@@ -3069,11 +3115,12 @@
     def read(self, path: FsPath) -> TranslationUnit:
         """Load a TranslationUnit from the given AST file."""
         return TranslationUnit.from_ast_file(path, self)
 
     def parse(
-        self, path: Optional[FsPath],
+        self,
+        path: Optional[FsPath],
         args: Optional[List[str]] = None,
         unsaved_files: Optional[List[UnsavedFileInfo]] = None,
         options: int = 0,
     ) -> TranslationUnit:
         """Load the translation unit from the given source code file by running
@@ -3131,30 +3178,33 @@
     PARSE_INCLUDE_BRIEF_COMMENTS_IN_CODE_COMPLETION = 128
 
     index: Index
 
     @staticmethod
-    def process_unsaved_files(unsaved_files: List[UnsavedFileInfo]) -> Optional[CArray[_CXUnsavedFile]]:
+    def process_unsaved_files(
+        unsaved_files: List[UnsavedFileInfo],
+    ) -> Optional[CArray[_CXUnsavedFile]]:
         unsaved_array = None
         if len(unsaved_files):
             unsaved_array = (_CXUnsavedFile * len(unsaved_files))()
             for i, (name, contents) in enumerate(unsaved_files):
                 if hasattr(contents, "read"):
-                    contents = tcast('SupportsReadStringData', contents).read()
-                binary_contents = b(tcast('StrOrBytes', contents))
+                    contents = tcast("SupportsReadStringData", contents).read()
+                binary_contents = b(tcast("StrOrBytes", contents))
                 unsaved_array[i].name = b(os.fspath(name))
                 unsaved_array[i].contents = binary_contents
                 unsaved_array[i].length = len(binary_contents)
         return unsaved_array
 
     @classmethod
     def from_source(
-        cls, filename: Optional[FsPath],
+        cls,
+        filename: Optional[FsPath],
         args: Optional[List[str]] = None,
         unsaved_files: Optional[List[UnsavedFileInfo]] = None,
         options: int = 0,
-        index: Optional[Index] = None
+        index: Optional[Index] = None,
     ) -> Self:
         """Create a TranslationUnit by parsing source.
 
         This is capable of processing source code both from files on the
         filesystem as well as in-memory contents.
@@ -3277,11 +3327,16 @@
         this sequence is always the input file. Note that this method will not
         recursively iterate over header files included through precompiled
         headers.
         """
 
-        def visitor(fobj: CObjectP, lptr: CPointer[SourceLocation], depth: int, includes: List[FileInclusion]) -> None:
+        def visitor(
+            fobj: CObjectP,
+            lptr: CPointer[SourceLocation],
+            depth: int,
+            includes: List[FileInclusion],
+        ) -> None:
             if depth > 0:
                 loc = lptr.contents
                 includes.append(FileInclusion(loc.file, File(fobj), loc, depth))
 
         # Automatically adapt CIndex/ctype pointers to python objects
@@ -3295,11 +3350,13 @@
     def get_file(self, filename: FsPath) -> File:
         """Obtain a File from this translation unit."""
 
         return File.from_name(self, filename)
 
-    def get_location(self, filename: FsPath, position: Tuple[int, int]) -> SourceLocation:
+    def get_location(
+        self, filename: FsPath, position: Tuple[int, int]
+    ) -> SourceLocation:
         """Obtain a SourceLocation for a file in this translation unit.
 
         The position can be specified by passing:
 
           - Integer file offset. Initial file offset is 0.
@@ -3312,11 +3369,14 @@
             return SourceLocation.from_offset(self, f, position)
 
         return SourceLocation.from_position(self, f, position[0], position[1])
 
     _Location = TUnion[int, Tuple[int, int], SourceLocation]
-    def get_extent(self, filename: FsPath, locations: Tuple[_Location, _Location]) -> SourceRange:
+
+    def get_extent(
+        self, filename: FsPath, locations: Tuple[_Location, _Location]
+    ) -> SourceRange:
         """Obtain a SourceRange from this translation unit.
 
         The bounds of the SourceRange must ultimately be defined by a start and
         end SourceLocation. For the locations argument, you can pass:
 
@@ -3378,11 +3438,13 @@
                     raise IndexError
                 return Diagnostic(diag)
 
         return DiagIterator(self)
 
-    def reparse(self, unsaved_files: Optional[List[UnsavedFileInfo]] = None, options: int = 0) -> None:
+    def reparse(
+        self, unsaved_files: Optional[List[UnsavedFileInfo]] = None, options: int = 0
+    ) -> None:
         """
         Reparse an already parsed translation unit.
 
         In-memory contents for files can be provided by passing a list of pairs
         as unsaved_files, the first items should be the filenames to be mapped
@@ -3395,11 +3457,11 @@
         unsaved_files_array = self.process_unsaved_files(unsaved_files)
         result = conf.lib.clang_reparseTranslationUnit(
             self, len(unsaved_files), unsaved_files_array, options
         )
         if result != 0:
-            raise CXError(result, 'Error reparsing TranslationUnit.')
+            raise CXError(result, "Error reparsing TranslationUnit.")
 
     def save(self, filename: FsPath) -> None:
         """Saves the TranslationUnit to a file.
 
         This is equivalent to passing -emit-ast to the clang frontend. The
@@ -3413,13 +3475,11 @@
         TranslationUnit.diagnostics().
 
         filename -- The path to save the translation unit to (str or PathLike).
         """
         options = conf.lib.clang_defaultSaveOptions(self)
-        result = conf.lib.clang_saveTranslationUnit(
-            self, os.fspath(filename), options
-        )
+        result = conf.lib.clang_saveTranslationUnit(self, os.fspath(filename), options)
         if result != 0:
             raise TranslationUnitSaveError(result, "Error saving TranslationUnit.")
 
     def codeComplete(
         self,
@@ -3465,25 +3525,31 @@
         )
         if ptr:
             return CodeCompletionResults(ptr)
         return None
 
-    def get_tokens(self, locations: Optional[Tuple[SourceLocation, SourceLocation]] = None, extent: Optional[SourceRange] = None) -> Generator[Token, None, None]:
+    def get_tokens(
+        self,
+        locations: Optional[Tuple[SourceLocation, SourceLocation]] = None,
+        extent: Optional[SourceRange] = None,
+    ) -> Generator[Token, None, None]:
         """Obtain tokens in this translation unit.
 
         This is a generator for Token instances. The caller specifies a range
         of source code to obtain tokens for. The range can be specified as a
         2-tuple of SourceLocation or as a SourceRange. If both are defined,
         behavior is undefined.
         """
-        
+
         if locations is not None:
-            final_extent = SourceRange.from_locations(start=locations[0], end=locations[1])
+            final_extent = SourceRange.from_locations(
+                start=locations[0], end=locations[1]
+            )
         elif extent is not None:
             final_extent = extent
         else:
-            raise ValueError('no extent given')
+            raise ValueError("no extent given")
 
         return TokenGroup.get_tokens(self, final_extent)
 
 
 class File(ClangObject):
@@ -3516,13 +3582,15 @@
 
     def __repr__(self) -> str:
         return "<File: %s>" % (self.name)
 
     @staticmethod
-    def from_result(res: CObjectP, fn: Callable[..., CObjectP], args: Tuple[Any, ...]) -> File:
+    def from_result(
+        res: CObjectP, fn: Callable[..., CObjectP], args: Tuple[Any, ...]
+    ) -> File:
         assert isinstance(res, c_object_p)
-        resobj = File(res) # pyright: ignore
+        resobj = File(res)  # pyright: ignore
 
         # Copy a reference to the TranslationUnit to prevent premature GC.
         resobj._tu = args[0]._tu
         return resobj
 
@@ -3640,11 +3708,13 @@
         if not cc:
             raise IndexError
         return CompileCommand(cc, self)
 
     @staticmethod
-    def from_result(res: CObjectP, fn: Callable[..., CObjectP], args: Tuple[Any, ...]) -> Optional[CompileCommands]:
+    def from_result(
+        res: CObjectP, fn: Callable[..., CObjectP], args: Tuple[Any, ...]
+    ) -> Optional[CompileCommands]:
         if not res:
             return None
         return CompileCommands(res)
 
 
@@ -3658,11 +3728,13 @@
 
     def __del__(self) -> None:
         conf.lib.clang_CompilationDatabase_dispose(self)
 
     @staticmethod
-    def from_result(res: CObjectP, fn: Callable[..., CObjectP], args: Tuple[Any, ...]) -> CompilationDatabase:
+    def from_result(
+        res: CObjectP, fn: Callable[..., CObjectP], args: Tuple[Any, ...]
+    ) -> CompilationDatabase:
         if not res:
             raise CompilationDatabaseError(0, "CompilationDatabase loading failed")
         return CompilationDatabase(res)
 
     @staticmethod
@@ -3737,11 +3809,11 @@
 
     @property
     def cursor(self) -> Cursor:
         """The Cursor this Token corresponds to."""
         cursor = Cursor()
-        cursor._tu = self._tu # pyright: ignore[reportPrivateUsage]
+        cursor._tu = self._tu  # pyright: ignore[reportPrivateUsage]
 
         conf.lib.clang_annotateTokens(self._tu, byref(self), 1, byref(cursor))
 
         return cursor
 
@@ -3806,15 +3878,19 @@
 
 
 # Now comes the plumbing to hook up the C library.
 
 # Register callback types
-TranslationUnitIncludesCallback = Annotated[CFuncPointer, None, c_object_p, CPointer[SourceLocation], c_uint, py_object]
+TranslationUnitIncludesCallback = Annotated[
+    CFuncPointer, None, c_object_p, CPointer[SourceLocation], c_uint, py_object
+]
 CursorVisitCallback = Annotated[CFuncPointer, c_int, Cursor, Cursor, py_object]
 FieldsVisitCallback = Annotated[CFuncPointer, c_int, Cursor, py_object]
 
-translation_unit_includes_callback: TType[CFuncPointer] = convert_annotation(TranslationUnitIncludesCallback)
+translation_unit_includes_callback: TType[CFuncPointer] = convert_annotation(
+    TranslationUnitIncludesCallback
+)
 cursor_visit_callback: TType[CFuncPointer] = convert_annotation(CursorVisitCallback)
 fields_visit_callback: TType[CFuncPointer] = convert_annotation(FieldsVisitCallback)
 
 
 # Functions strictly alphabetical order.
@@ -3823,26 +3899,38 @@
 #   - If Config.compatibility_check is set to `False`, then a function is allowed to be missing.
 #   - If a function is missing in C library, it will not be replaced, thus causing NotImplementedError when called.
 #   - Missing functions are given a `_missing_` attribute, you can check it with `hasattr(conf.lib.xxx, '_missing_')`.
 #   - These stub functions are generated with a script from old data and manually corrected, so parameter names are missing.
 class LibclangExports:
-    def clang_annotateTokens(self, p1: TranslationUnit, p2: CPointerParam[Token], p3: p_ulong, p4: CPointerParam[Cursor]) -> r_long:
+    def clang_annotateTokens(
+        self,
+        p1: TranslationUnit,
+        p2: CPointerParam[Token],
+        p3: p_ulong,
+        p4: CPointerParam[Cursor],
+    ) -> r_long:
         raise NotImplementedError
 
     def clang_CompilationDatabase_dispose(self, p1: ClangObjectParam) -> r_long:
         raise NotImplementedError
 
     @with_errcheck(CompilationDatabase.from_result)
-    def clang_CompilationDatabase_fromDirectory(self, p1: CInteropString, p2: CPointerParam[c_ulong]) -> CObjectP:
+    def clang_CompilationDatabase_fromDirectory(
+        self, p1: CInteropString, p2: CPointerParam[c_ulong]
+    ) -> CObjectP:
         raise NotImplementedError
 
     @with_errcheck(CompileCommands.from_result)
-    def clang_CompilationDatabase_getAllCompileCommands(self, p1: ClangObjectParam) -> CObjectP:
+    def clang_CompilationDatabase_getAllCompileCommands(
+        self, p1: ClangObjectParam
+    ) -> CObjectP:
         raise NotImplementedError
 
     @with_errcheck(CompileCommands.from_result)
-    def clang_CompilationDatabase_getCompileCommands(self, p1: ClangObjectParam, p2: CInteropString) -> CObjectP:
+    def clang_CompilationDatabase_getCompileCommands(
+        self, p1: ClangObjectParam, p2: CInteropString
+    ) -> CObjectP:
         raise NotImplementedError
 
     def clang_CompileCommands_dispose(self, p1: CObjectP) -> r_long:
         raise NotImplementedError
 
@@ -3865,14 +3953,25 @@
         raise NotImplementedError
 
     def clang_CompileCommand_getNumArgs(self, p1: CObjectP) -> r_ulong:
         raise NotImplementedError
 
-    def clang_codeCompleteAt(self, p1: TranslationUnit, p2: CInteropString, p3: p_long, p4: p_long, p5: CPointerParam[_CXUnsavedFile], p6: p_long, p7: p_long) -> CPointer[CCRStructure]:
-        raise NotImplementedError
-
-    def clang_codeCompleteGetDiagnostic(self, p1: CodeCompletionResults, p2: p_long) -> Diagnostic:
+    def clang_codeCompleteAt(
+        self,
+        p1: TranslationUnit,
+        p2: CInteropString,
+        p3: p_long,
+        p4: p_long,
+        p5: CPointerParam[_CXUnsavedFile],
+        p6: p_long,
+        p7: p_long,
+    ) -> CPointer[CCRStructure]:
+        raise NotImplementedError
+
+    def clang_codeCompleteGetDiagnostic(
+        self, p1: CodeCompletionResults, p2: p_long
+    ) -> Diagnostic:
         raise NotImplementedError
 
     def clang_codeCompleteGetNumDiagnostics(self, p1: CodeCompletionResults) -> r_long:
         raise NotImplementedError
 
@@ -3886,20 +3985,24 @@
         raise NotImplementedError
 
     def clang_CXRewriter_dispose(self, p1: Rewriter) -> r_long:
         raise NotImplementedError
 
-    def clang_CXRewriter_insertTextBefore(self, p1: Rewriter, p2: SourceLocation, p3: CInteropString) -> r_long:
+    def clang_CXRewriter_insertTextBefore(
+        self, p1: Rewriter, p2: SourceLocation, p3: CInteropString
+    ) -> r_long:
         raise NotImplementedError
 
     def clang_CXRewriter_overwriteChangedFiles(self, p1: Rewriter) -> r_long:
         raise NotImplementedError
 
     def clang_CXRewriter_removeText(self, p1: Rewriter, p2: SourceRange) -> r_long:
         raise NotImplementedError
 
-    def clang_CXRewriter_replaceText(self, p1: Rewriter, p2: SourceRange, p3: CInteropString) -> r_long:
+    def clang_CXRewriter_replaceText(
+        self, p1: Rewriter, p2: SourceRange, p3: CInteropString
+    ) -> r_long:
         raise NotImplementedError
 
     def clang_CXRewriter_writeMainFileToStdOut(self, p1: Rewriter) -> r_long:
         raise NotImplementedError
 
@@ -3970,11 +4073,13 @@
         raise NotImplementedError
 
     def clang_disposeString(self, p1: _CXString) -> r_long:
         raise NotImplementedError
 
-    def clang_disposeTokens(self, p1: TranslationUnit, p2: CPointer[Token], p3: p_uint) -> r_long:
+    def clang_disposeTokens(
+        self, p1: TranslationUnit, p2: CPointer[Token], p3: p_uint
+    ) -> r_long:
         raise NotImplementedError
 
     def clang_disposeTranslationUnit(self, p1: TranslationUnit) -> r_long:
         raise NotImplementedError
 
@@ -4027,11 +4132,13 @@
 
     @with_errcheck(_CXString.from_result)
     def clang_getCompletionBriefComment(self, p1: CObjectP) -> _CXString:
         raise NotImplementedError
 
-    def clang_getCompletionChunkCompletionString(self, p1: CObjectP, p2: p_long) -> CObjectP:
+    def clang_getCompletionChunkCompletionString(
+        self, p1: CObjectP, p2: p_long
+    ) -> CObjectP:
         raise NotImplementedError
 
     def clang_getCompletionChunkKind(self, p1: CObjectP, p2: p_long) -> r_long:
         raise NotImplementedError
 
@@ -4078,11 +4185,13 @@
 
     @with_errcheck(Cursor.from_result)
     def clang_getCursorReferenced(self, p1: Cursor) -> Cursor:
         raise NotImplementedError
 
-    def clang_getCursorReferenceNameRange(self, p1: Cursor, p2: p_ulong, p3: p_ulong) -> SourceRange:
+    def clang_getCursorReferenceNameRange(
+        self, p1: Cursor, p2: p_ulong, p3: p_ulong
+    ) -> SourceRange:
         raise NotImplementedError
 
     @with_errcheck(Type.from_result)
     def clang_getCursorResultType(self, p1: Cursor) -> Type:
         raise NotImplementedError
@@ -4126,11 +4235,13 @@
     @with_errcheck(_CXString.from_result)
     def clang_getDiagnosticCategoryText(self, p1: Diagnostic) -> _CXString:
         raise NotImplementedError
 
     @with_errcheck(_CXString.from_result)
-    def clang_getDiagnosticFixIt(self, p1: Diagnostic, p2: p_ulong, p3: CPointerParam[SourceRange]) -> _CXString:
+    def clang_getDiagnosticFixIt(
+        self, p1: Diagnostic, p2: p_ulong, p3: CPointerParam[SourceRange]
+    ) -> _CXString:
         raise NotImplementedError
 
     def clang_getDiagnosticInSet(self, p1: CObjectP, p2: p_ulong) -> CObjectP:
         raise NotImplementedError
 
@@ -4142,11 +4253,13 @@
 
     def clang_getDiagnosticNumRanges(self, p1: Diagnostic) -> r_ulong:
         raise NotImplementedError
 
     @with_errcheck(_CXString.from_result)
-    def clang_getDiagnosticOption(self, p1: Diagnostic, p2: CPointerParam[_CXString]) -> _CXString:
+    def clang_getDiagnosticOption(
+        self, p1: Diagnostic, p2: CPointerParam[_CXString]
+    ) -> _CXString:
         raise NotImplementedError
 
     def clang_getDiagnosticRange(self, p1: Diagnostic, p2: p_ulong) -> SourceRange:
         raise NotImplementedError
 
@@ -4190,20 +4303,36 @@
 
     @with_errcheck(File.from_result)
     def clang_getIncludedFile(self, p1: Cursor) -> CObjectP:
         raise NotImplementedError
 
-    def clang_getInclusions(self, p1: TranslationUnit, p2: TranslationUnitIncludesCallback, p3: CPyObject[List[FileInclusion]]) -> r_long:
-        raise NotImplementedError
-
-    def clang_getInstantiationLocation(self, p1: SourceLocation, p2: CPointerParam[CObjectP], p3: CPointerParam[c_ulong], p4: CPointerParam[c_ulong], p5: CPointerParam[c_ulong]) -> r_long:
-        raise NotImplementedError
-
-    def clang_getLocation(self, p1: TranslationUnit, p2: File, p3: p_ulong, p4: p_ulong) -> SourceLocation:
-        raise NotImplementedError
-
-    def clang_getLocationForOffset(self, p1: TranslationUnit, p2: File, p3: p_ulong) -> SourceLocation:
+    def clang_getInclusions(
+        self,
+        p1: TranslationUnit,
+        p2: TranslationUnitIncludesCallback,
+        p3: CPyObject[List[FileInclusion]],
+    ) -> r_long:
+        raise NotImplementedError
+
+    def clang_getInstantiationLocation(
+        self,
+        p1: SourceLocation,
+        p2: CPointerParam[CObjectP],
+        p3: CPointerParam[c_ulong],
+        p4: CPointerParam[c_ulong],
+        p5: CPointerParam[c_ulong],
+    ) -> r_long:
+        raise NotImplementedError
+
+    def clang_getLocation(
+        self, p1: TranslationUnit, p2: File, p3: p_ulong, p4: p_ulong
+    ) -> SourceLocation:
+        raise NotImplementedError
+
+    def clang_getLocationForOffset(
+        self, p1: TranslationUnit, p2: File, p3: p_ulong
+    ) -> SourceLocation:
         raise NotImplementedError
 
     def clang_getNullCursor(self) -> Cursor:
         raise NotImplementedError
 
@@ -4350,23 +4479,48 @@
         raise NotImplementedError
 
     def clang_isVolatileQualifiedType(self, p1: Type) -> bool:
         raise NotImplementedError
 
-    def clang_parseTranslationUnit(self, p1: Index, p2: CInteropString, p3: CPointerParam[c_char_p], p4: p_long, p5: CPointerParam[_CXUnsavedFile], p6: p_long, p7: p_long) -> CObjectP:
-        raise NotImplementedError
-
-    def clang_reparseTranslationUnit(self, p1: TranslationUnit, p2: p_long, p3: CPointerParam[_CXUnsavedFile], p4: p_long) -> r_long:
-        raise NotImplementedError
-
-    def clang_saveTranslationUnit(self, p1: TranslationUnit, p2: CInteropString, p3: p_ulong) -> r_long:
-        raise NotImplementedError
-
-    def clang_tokenize(self, p1: TranslationUnit, p2: SourceRange, p3: CPointerParam[CPointer[Token]], p4: CPointerParam[c_ulong]) -> r_long:
-        raise NotImplementedError
-
-    def clang_visitChildren(self, p1: Cursor, p2: CursorVisitCallback, p3: CPyObject[List[Cursor]]) -> r_ulong:
+    def clang_parseTranslationUnit(
+        self,
+        p1: Index,
+        p2: CInteropString,
+        p3: CPointerParam[c_char_p],
+        p4: p_long,
+        p5: CPointerParam[_CXUnsavedFile],
+        p6: p_long,
+        p7: p_long,
+    ) -> CObjectP:
+        raise NotImplementedError
+
+    def clang_reparseTranslationUnit(
+        self,
+        p1: TranslationUnit,
+        p2: p_long,
+        p3: CPointerParam[_CXUnsavedFile],
+        p4: p_long,
+    ) -> r_long:
+        raise NotImplementedError
+
+    def clang_saveTranslationUnit(
+        self, p1: TranslationUnit, p2: CInteropString, p3: p_ulong
+    ) -> r_long:
+        raise NotImplementedError
+
+    def clang_tokenize(
+        self,
+        p1: TranslationUnit,
+        p2: SourceRange,
+        p3: CPointerParam[CPointer[Token]],
+        p4: CPointerParam[c_ulong],
+    ) -> r_long:
+        raise NotImplementedError
+
+    def clang_visitChildren(
+        self, p1: Cursor, p2: CursorVisitCallback, p3: CPyObject[List[Cursor]]
+    ) -> r_ulong:
         raise NotImplementedError
 
     def clang_Cursor_getNumArguments(self, p1: Cursor) -> r_long:
         raise NotImplementedError
 
@@ -4383,14 +4537,18 @@
 
     @with_errcheck(Type.from_result)
     def clang_Cursor_getTemplateArgumentType(self, p1: Cursor, p2: p_ulong) -> Type:
         raise NotImplementedError
 
-    def clang_Cursor_getTemplateArgumentValue(self, p1: Cursor, p2: p_ulong) -> r_longlong:
-        raise NotImplementedError
-
-    def clang_Cursor_getTemplateArgumentUnsignedValue(self, p1: Cursor, p2: p_ulong) -> r_ulonglong:
+    def clang_Cursor_getTemplateArgumentValue(
+        self, p1: Cursor, p2: p_ulong
+    ) -> r_longlong:
+        raise NotImplementedError
+
+    def clang_Cursor_getTemplateArgumentUnsignedValue(
+        self, p1: Cursor, p2: p_ulong
+    ) -> r_ulonglong:
         raise NotImplementedError
 
     def clang_Cursor_isAnonymous(self, p1: Cursor) -> bool:
         raise NotImplementedError
 
@@ -4439,11 +4597,13 @@
 
     @with_errcheck(Type.from_result)
     def clang_Type_getNamedType(self, p1: Type) -> Type:
         raise NotImplementedError
 
-    def clang_Type_visitFields(self, p1: Type, p2: FieldsVisitCallback, p3: CPyObject[List[Cursor]]) -> r_ulong:
+    def clang_Type_visitFields(
+        self, p1: Type, p2: FieldsVisitCallback, p3: CPyObject[List[Cursor]]
+    ) -> r_ulong:
         raise NotImplementedError
 
 
 class LibclangError(Exception):
     m: str
@@ -4553,15 +4713,15 @@
             raise LibclangError(msg)
 
         return library
 
     def function_exists(self, name: str) -> bool:
-        return not hasattr(getattr(self.lib, name), '_missing_')
+        return not hasattr(getattr(self.lib, name), "_missing_")
 
 
 def generate_metadata_debug() -> Dict[str, Dict[str, Any]]:
-    ''' Generate ctypes metadata for debugging purpose. '''
+    """Generate ctypes metadata for debugging purpose."""
     return {name: info for name, info in generate_metadata(LibclangExports, globals())}
 
 
 conf = Config()
 
--- clang/ctyped.py	2024-08-03 14:41:42.000000 +0000
+++ clang/ctyped.py	2024-08-03 23:15:21.802497 +0000
@@ -1,48 +1,94 @@
-from ctypes import (CFUNCTYPE, POINTER, WINFUNCTYPE, c_bool, c_byte, c_char,
-                    c_char_p, c_double, c_float, c_int, c_long, c_longdouble,
-                    c_longlong, c_short, c_size_t, c_ssize_t, c_ubyte, c_uint,
-                    c_ulong, c_ulonglong, c_ushort, c_void_p, c_wchar,
-                    c_wchar_p, py_object)
+from ctypes import (
+    CFUNCTYPE,
+    POINTER,
+    WINFUNCTYPE,
+    c_bool,
+    c_byte,
+    c_char,
+    c_char_p,
+    c_double,
+    c_float,
+    c_int,
+    c_long,
+    c_longdouble,
+    c_longlong,
+    c_short,
+    c_size_t,
+    c_ssize_t,
+    c_ubyte,
+    c_uint,
+    c_ulong,
+    c_ulonglong,
+    c_ushort,
+    c_void_p,
+    c_wchar,
+    c_wchar_p,
+    py_object,
+)
 from inspect import Parameter, signature
-from typing import (TYPE_CHECKING, Any, Callable, Dict, Generator, Generic,
-                    List, Optional, Tuple, Type, TypeVar, Union, cast)
+from typing import (
+    TYPE_CHECKING,
+    Any,
+    Callable,
+    Dict,
+    Generator,
+    Generic,
+    List,
+    Optional,
+    Tuple,
+    Type,
+    TypeVar,
+    Union,
+    cast,
+)
 
 from typing_extensions import Annotated, ParamSpec, TypeAlias
 
-_T = TypeVar('_T')
+_T = TypeVar("_T")
 
 if TYPE_CHECKING:
     from ctypes import _CArgObject  # pyright: ignore[reportPrivateUsage]
     from ctypes import _CData  # pyright: ignore[reportPrivateUsage]
 
-AnyCData = TypeVar('AnyCData', bound='_CData')
+AnyCData = TypeVar("AnyCData", bound="_CData")
 
 if TYPE_CHECKING:
     from ctypes import Array as _Array  # pyright: ignore[reportPrivateUsage]
-    from ctypes import \
-        _FuncPointer as _FuncPointer  # pyright: ignore[reportPrivateUsage]
-    from ctypes import \
-        _Pointer as _Pointer  # pyright: ignore[reportPrivateUsage]
+    from ctypes import (
+        _FuncPointer as _FuncPointer,
+    )  # pyright: ignore[reportPrivateUsage]
+    from ctypes import _Pointer as _Pointer  # pyright: ignore[reportPrivateUsage]
 
     # ctypes documentation noted implicit conversion for pointers:
     # "For example, you can pass compatible array instances instead of pointer
     #  types. So, for POINTER(c_int), ctypes accepts an array of c_int:"
     # "In addition, if a function argument is explicitly declared to be a
     #  pointer type (such as POINTER(c_int)) in argtypes, an object of the
     #  pointed type (c_int in this case) can be passed to the function. ctypes
     #  will apply the required byref() conversion in this case automatically."
     # also, current ctype typeshed thinks byref returns _CArgObject
-    _PointerCompatible: TypeAlias = Union['_CArgObject', _Pointer[AnyCData], None, _Array[AnyCData], AnyCData]
-    _PyObject: TypeAlias = Union['py_object[_T]', _T]
+    _PointerCompatible: TypeAlias = Union[
+        "_CArgObject", _Pointer[AnyCData], None, _Array[AnyCData], AnyCData
+    ]
+    _PyObject: TypeAlias = Union["py_object[_T]", _T]
 else:
     # at runtime we don't really import those symbols
-    class _Array(Generic[AnyCData]): ...
-    class _Pointer(Generic[AnyCData]): ...
-    class _PointerCompatible(Generic[AnyCData]): ...
-    class _FuncPointer: ...
-    class _PyObject(Generic[AnyCData]): ...
+    class _Array(Generic[AnyCData]):
+        ...
+
+    class _Pointer(Generic[AnyCData]):
+        ...
+
+    class _PointerCompatible(Generic[AnyCData]):
+        ...
+
+    class _FuncPointer:
+        ...
+
+    class _PyObject(Generic[AnyCData]):
+        ...
 
 
 # ANNO_CONVETIBLE can be used to declare that a class have a `from_param`
 # method which can convert other types when used as `argtypes`.
 # For example: `CClass = Annotated[bytes, ANNO_CONVERTIBLE, c_class]` means
@@ -100,13 +146,17 @@
 p_size_t = Annotated[Union[c_size_t, int], ANNO_BASIC, c_size_t]
 p_ssize_t = Annotated[Union[c_ssize_t, int], ANNO_BASIC, c_ssize_t]
 p_float = Annotated[Union[c_float, float], ANNO_BASIC, c_float]
 p_double = Annotated[Union[c_double, float], ANNO_BASIC, c_double]
 p_longdouble = Annotated[Union[c_longdouble, float], ANNO_BASIC, c_longdouble]
-p_char_p = Annotated[Union[c_char_p, _Array[c_wchar], bytes, None], ANNO_BASIC, c_char_p]
-p_wchar_p = Annotated[Union[c_wchar_p, _Array[c_wchar], str, None], ANNO_BASIC, c_wchar_p]
-p_void_p = Annotated[Union['_CArgObject', c_void_p, int, None], ANNO_BASIC, c_void_p]
+p_char_p = Annotated[
+    Union[c_char_p, _Array[c_wchar], bytes, None], ANNO_BASIC, c_char_p
+]
+p_wchar_p = Annotated[
+    Union[c_wchar_p, _Array[c_wchar], str, None], ANNO_BASIC, c_wchar_p
+]
+p_void_p = Annotated[Union["_CArgObject", c_void_p, int, None], ANNO_BASIC, c_void_p]
 
 # export Pointer, PointerCompatible, Array and FuncPointer annotation
 
 CArray = Annotated[_Array[AnyCData], ANNO_ARRAY]
 CPointer = Annotated[_Pointer[AnyCData], ANNO_POINTER]
@@ -114,163 +164,196 @@
 CFuncPointer = Annotated[_FuncPointer, ANNO_CFUNC]
 WinFuncPointer = Annotated[_FuncPointer, ANNO_WINFUNC]
 CPyObject = Annotated[_PyObject[_T], ANNO_PYOBJ]
 
 
-_Params = ParamSpec('_Params')
-_OrigRet = TypeVar('_OrigRet')
-_NewRet = TypeVar('_NewRet')
-
-def with_errcheck(checker: Callable[[_OrigRet, Callable[..., _OrigRet], Tuple[Any, ...]], _NewRet]) -> Callable[[Callable[_Params, _OrigRet]], Callable[_Params, _NewRet]]:
-    ''' Decorates a stub function with an error checker. '''
+_Params = ParamSpec("_Params")
+_OrigRet = TypeVar("_OrigRet")
+_NewRet = TypeVar("_NewRet")
+
+
+def with_errcheck(
+    checker: Callable[[_OrigRet, Callable[..., _OrigRet], Tuple[Any, ...]], _NewRet]
+) -> Callable[[Callable[_Params, _OrigRet]], Callable[_Params, _NewRet]]:
+    """Decorates a stub function with an error checker."""
+
     def decorator(wrapped: Callable[_Params, _OrigRet]) -> Callable[_Params, _NewRet]:
         def wrapper(*args: _Params.args, **kwargs: _Params.kwargs) -> _NewRet:
             raise NotImplementedError
 
         # attach original declaration and error checker to wrapper
-        setattr(wrapper, '_decl_errcheck_', (wrapped, checker))
+        setattr(wrapper, "_decl_errcheck_", (wrapped, checker))
         return wrapper
 
     return decorator
+
 
 # NOTE: Actually, converter is a deprecated form of `restype`.
 # According to ctypes documentation:
 # "It is possible to assign a callable Python object that is not a ctypes
 #  type, in this case the function is assumed to return a C int, and the
 #  callable will be called with this integer, allowing further processing
 #  or error checking. Using this is deprecated, for more flexible post
 #  processing or error checking use a ctypes data type as restype and
 #  assign a callable to the errcheck attribute."
 
-def with_converter(converter: Callable[[int], _NewRet]) -> Callable[[Callable[_Params, r_int]], Callable[_Params, _NewRet]]:
-    ''' Decorates a stub function with a converter, its return type MUST be `r_int`. '''
+
+def with_converter(
+    converter: Callable[[int], _NewRet]
+) -> Callable[[Callable[_Params, r_int]], Callable[_Params, _NewRet]]:
+    """Decorates a stub function with a converter, its return type MUST be `r_int`."""
+
     def decorator(wrapped: Callable[_Params, r_int]) -> Callable[_Params, _NewRet]:
         def wrapper(*args: _Params.args, **kwargs: _Params.kwargs) -> _NewRet:
             raise NotImplementedError
 
         # attach original declaration and converter to wrapper
-        setattr(wrapper, '_decl_converter_', (wrapped, converter))
+        setattr(wrapper, "_decl_converter_", (wrapped, converter))
         return wrapper
 
     return decorator
 
 
-def convert_annotation(typ: Any, global_ns: Optional[Dict[str, Any]] = None) -> Type[Any]:
-    ''' Convert an annotation to effective runtime type. '''
+def convert_annotation(
+    typ: Any, global_ns: Optional[Dict[str, Any]] = None
+) -> Type[Any]:
+    """Convert an annotation to effective runtime type."""
     if global_ns is None:
         global_ns = globals()
 
     if isinstance(typ, str):
-        try: typ = eval(typ, global_ns)
+        try:
+            typ = eval(typ, global_ns)
         except Exception as exc:
-            raise ValueError('Evaluation of delayed annotation failed!') from exc
-
-    if not hasattr(typ, '__metadata__'):
+            raise ValueError("Evaluation of delayed annotation failed!") from exc
+
+    if not hasattr(typ, "__metadata__"):
         return cast(Type[Any], typ)
 
     # type is Annotated
     ident, *detail = typ.__metadata__
     if ident is ANNO_CONVERTIBLE:
-        ctyp, = detail
+        (ctyp,) = detail
         return cast(Type[Any], ctyp)
     elif ident is ANNO_ARRAY:
-        try: count, = detail
+        try:
+            (count,) = detail
         except ValueError:
-            raise ValueError('CArray needs to be annotated with its size')
-        ctyp, = typ.__args__[0].__args__
+            raise ValueError("CArray needs to be annotated with its size")
+        (ctyp,) = typ.__args__[0].__args__
         return cast(Type[Any], convert_annotation(ctyp, global_ns=global_ns) * count)
     elif ident is ANNO_POINTER:
         assert not detail
-        ctyp, = typ.__args__[0].__args__
-        return POINTER(convert_annotation(ctyp, global_ns=global_ns)) # pyright: ignore
+        (ctyp,) = typ.__args__[0].__args__
+        return POINTER(convert_annotation(ctyp, global_ns=global_ns))  # pyright: ignore
     elif ident is ANNO_CFUNC:
         if not detail:
-            raise ValueError('CFuncPointer needs to be annotated with its signature')
+            raise ValueError("CFuncPointer needs to be annotated with its signature")
         return CFUNCTYPE(*(convert_annotation(t, global_ns=global_ns) for t in detail))
     elif ident is ANNO_WINFUNC:
         if not detail:
-            raise ValueError('WinFuncPointer needs to be annotated with its signature')
-        return WINFUNCTYPE(*(convert_annotation(t, global_ns=global_ns) for t in detail))
+            raise ValueError("WinFuncPointer needs to be annotated with its signature")
+        return WINFUNCTYPE(
+            *(convert_annotation(t, global_ns=global_ns) for t in detail)
+        )
     elif ident is ANNO_PYOBJ:
         assert not detail
         return py_object
     else:
-        raise ValueError(f'Unexpected annotated type {typ}')
-
-
-def convert_func_decl(decl: Callable[..., Any], global_ns: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
-    ''' Converts a stub function to ctypes metadata. '''
+        raise ValueError(f"Unexpected annotated type {typ}")
+
+
+def convert_func_decl(
+    decl: Callable[..., Any], global_ns: Optional[Dict[str, Any]] = None
+) -> Dict[str, Any]:
+    """Converts a stub function to ctypes metadata."""
     if global_ns is None:
         global_ns = globals()
 
     result: Dict[str, Any] = {}
 
     errcheck = None
     converter = None
 
     while True:
-        if hasattr(decl, '_decl_errcheck_'):
+        if hasattr(decl, "_decl_errcheck_"):
             if errcheck is not None:
-                raise ValueError('duplicate errcheck in stub function')
-            decl, errcheck = getattr(decl, '_decl_errcheck_')
+                raise ValueError("duplicate errcheck in stub function")
+            decl, errcheck = getattr(decl, "_decl_errcheck_")
             continue
 
-        if hasattr(decl, '_decl_converter_'):
+        if hasattr(decl, "_decl_converter_"):
             if converter is not None:
-                raise ValueError('duplicate converter in stub function')
-            decl, converter = getattr(decl, '_decl_converter_')
+                raise ValueError("duplicate converter in stub function")
+            decl, converter = getattr(decl, "_decl_converter_")
             continue
 
         break
 
     sig = signature(decl)
 
-    param_annos = [p.annotation for p in sig.parameters.values() if p.name != 'self']
+    param_annos = [p.annotation for p in sig.parameters.values() if p.name != "self"]
     if all(anno is not Parameter.empty for anno in param_annos):
-        result['argtypes'] = [convert_annotation(anno, global_ns=global_ns) for anno in param_annos] or None
+        result["argtypes"] = [
+            convert_annotation(anno, global_ns=global_ns) for anno in param_annos
+        ] or None
 
     if sig.return_annotation is not Parameter.empty:
-        result['restype'] = convert_annotation(sig.return_annotation, global_ns=global_ns)
-
-    if errcheck is not None: result['errcheck'] = errcheck
-    if converter is not None: result['restype'] = converter
+        result["restype"] = convert_annotation(
+            sig.return_annotation, global_ns=global_ns
+        )
+
+    if errcheck is not None:
+        result["errcheck"] = errcheck
+    if converter is not None:
+        result["restype"] = converter
 
     return result
 
 
 if TYPE_CHECKING:
     from ctypes import CDLL, WinDLL
-    _DLLT = TypeVar('_DLLT', bound=CDLL)
-_LibDecl = TypeVar('_LibDecl')
-
-
-def generate_metadata(decl_cls: Type[_LibDecl], global_ns: Optional[Dict[str, Any]] = None) -> Generator[Tuple[str, Dict[str, Any]], None, None]:
-    ''' Generate ctypes metadata for a stub class. '''
+
+    _DLLT = TypeVar("_DLLT", bound=CDLL)
+_LibDecl = TypeVar("_LibDecl")
+
+
+def generate_metadata(
+    decl_cls: Type[_LibDecl], global_ns: Optional[Dict[str, Any]] = None
+) -> Generator[Tuple[str, Dict[str, Any]], None, None]:
+    """Generate ctypes metadata for a stub class."""
     if global_ns is None:
         global_ns = globals()
 
     for name in dir(decl_cls):
-        if name.startswith('_'): continue
+        if name.startswith("_"):
+            continue
         value = getattr(decl_cls, name)
-        if not callable(value): continue
+        if not callable(value):
+            continue
 
         yield name, convert_func_decl(value, global_ns=global_ns)
 
 
-def load_annotated_library(loader: 'Union[CDLL, WinDLL]', decl_cls: Type[_LibDecl], global_ns: Optional[Dict[str, Any]] = None) -> Tuple[_LibDecl, List[str]]:
-    ''' Load a library and set signature metadata according to python type hints.
-        `decl_cls` is a class which should only contain method declarations.
-        Note: you should only name `self` as `self`, the converter depends on this.
-    '''
+def load_annotated_library(
+    loader: "Union[CDLL, WinDLL]",
+    decl_cls: Type[_LibDecl],
+    global_ns: Optional[Dict[str, Any]] = None,
+) -> Tuple[_LibDecl, List[str]]:
+    """Load a library and set signature metadata according to python type hints.
+    `decl_cls` is a class which should only contain method declarations.
+    Note: you should only name `self` as `self`, the converter depends on this.
+    """
     if global_ns is None:
         global_ns = globals()
 
     result = decl_cls()
     missing: List[str] = []
 
     for name, info in generate_metadata(decl_cls, global_ns=global_ns):
-        try: func = getattr(loader, name)
+        try:
+            func = getattr(loader, name)
         except AttributeError:
             stub = getattr(result, name)
             stub._missing_ = True
             missing.append(name)
             continue
@@ -282,64 +365,60 @@
 
     return result, missing
 
 
 __all__ = [
-    'ANNO_CONVERTIBLE',
-    'AnyCData',
-
-    'p_bool',
-    'p_char',
-    'p_wchar',
-    'p_byte',
-    'p_ubyte',
-    'p_short',
-    'p_ushort',
-    'p_int',
-    'p_uint',
-    'p_long',
-    'p_ulong',
-    'p_longlong',
-    'p_ulonglong',
-    'p_size_t',
-    'p_ssize_t',
-    'p_float',
-    'p_double',
-    'p_longdouble',
-    'p_char_p',
-    'p_wchar_p',
-    'p_void_p',
-
-    'r_bool',
-    'r_char',
-    'r_wchar',
-    'r_byte',
-    'r_ubyte',
-    'r_short',
-    'r_ushort',
-    'r_int',
-    'r_uint',
-    'r_long',
-    'r_ulong',
-    'r_longlong',
-    'r_ulonglong',
-    'r_size_t',
-    'r_ssize_t',
-    'r_float',
-    'r_double',
-    'r_longdouble',
-    'r_char_p',
-    'r_wchar_p',
-    'r_void_p',
-
-    'CArray',
-    'CPointer',
-    'CPointerParam',
-    'CFuncPointer',
-    'WinFuncPointer',
-    'CPyObject',
-
-    'convert_annotation',
-    'with_errcheck',
-    'with_converter',
-    'load_annotated_library',
+    "ANNO_CONVERTIBLE",
+    "AnyCData",
+    "p_bool",
+    "p_char",
+    "p_wchar",
+    "p_byte",
+    "p_ubyte",
+    "p_short",
+    "p_ushort",
+    "p_int",
+    "p_uint",
+    "p_long",
+    "p_ulong",
+    "p_longlong",
+    "p_ulonglong",
+    "p_size_t",
+    "p_ssize_t",
+    "p_float",
+    "p_double",
+    "p_longdouble",
+    "p_char_p",
+    "p_wchar_p",
+    "p_void_p",
+    "r_bool",
+    "r_char",
+    "r_wchar",
+    "r_byte",
+    "r_ubyte",
+    "r_short",
+    "r_ushort",
+    "r_int",
+    "r_uint",
+    "r_long",
+    "r_ulong",
+    "r_longlong",
+    "r_ulonglong",
+    "r_size_t",
+    "r_ssize_t",
+    "r_float",
+    "r_double",
+    "r_longdouble",
+    "r_char_p",
+    "r_wchar_p",
+    "r_void_p",
+    "CArray",
+    "CPointer",
+    "CPointerParam",
+    "CFuncPointer",
+    "WinFuncPointer",
+    "CPyObject",
+    "convert_annotation",
+    "with_errcheck",
+    "with_converter",
+    "load_annotated_library",
 ]
--- tests/ctyped/test_stub_conversion.py	2024-08-03 03:21:33.000000 +0000
+++ tests/ctyped/test_stub_conversion.py	2024-08-03 23:15:22.143008 +0000
@@ -7,14 +7,20 @@
 
 from dictdiffer import diff as dictdiff  # type: ignore
 
 from clang.cindex import *
 from clang.cindex import _CXString  # pyright: ignore[reportPrivateUsage]
-from clang.cindex import (CCRStructure, Rewriter, c_interop_string, c_object_p,
-                          cursor_visit_callback, fields_visit_callback,
-                          generate_metadata_debug,
-                          translation_unit_includes_callback)
+from clang.cindex import (
+    CCRStructure,
+    Rewriter,
+    c_interop_string,
+    c_object_p,
+    cursor_visit_callback,
+    fields_visit_callback,
+    generate_metadata_debug,
+    translation_unit_includes_callback,
+)
 
 
 # Functions strictly alphabetical order.
 # This is previous version of ctypes metadata, we check equality to this so
 # that we can ensure `ctyped` doesn't break anything in its conversion.
@@ -304,56 +310,73 @@
 ]
 
 
 # Sadly, ctypes provides no API to check if type is pointer or array.
 # Here we use regex to check type name.
-arr_regex = re.compile(r'(?P<typ>[A-Za-z0-9_]+)_Array_(?P<count>[0-9]+)')
-ptr_regex = re.compile(r'LP_(?P<typ>[A-Za-z0-9_]+)')
+arr_regex = re.compile(r"(?P<typ>[A-Za-z0-9_]+)_Array_(?P<count>[0-9]+)")
+ptr_regex = re.compile(r"LP_(?P<typ>[A-Za-z0-9_]+)")
+
 
 def is_ptr_type(typ: Any):
-    return typ in (c_void_p, c_char_p, c_wchar_p) or ptr_regex.fullmatch(typ.__name__) is not None
+    return (
+        typ in (c_void_p, c_char_p, c_wchar_p)
+        or ptr_regex.fullmatch(typ.__name__) is not None
+    )
+
 
 def is_arr_type(typ: Any):
     return arr_regex.fullmatch(typ.__name__) is not None
+
 
 # If we change a c_void_p parameter to a more exact pointer types, it
 # should still be working.
 def is_void_specialization(old_type: Any, new_type: Any):
     return old_type == c_void_p and is_ptr_type(new_type)
 
 
 def old_data_to_dict(data: List[Any]):
     result: Dict[str, Any] = {}
-    result['argtypes'], *data = data
-    if not result['argtypes']: result['argtypes'] = None
-    if data: result['restype'], *data = data
-    else: result['restype'] = c_int
-    if data: result['errcheck'], *data = data
+    result["argtypes"], *data = data
+    if not result["argtypes"]:
+        result["argtypes"] = None
+    if data:
+        result["restype"], *data = data
+    else:
+        result["restype"] = c_int
+    if data:
+        result["errcheck"], *data = data
     return result
 
 
 def is_incompatible_diff(diff: Any):
-    kind, path, detail = diff # pyright: ignore[reportUnusedVariable]
-    if kind == 'add': return True
+    kind, path, detail = diff  # pyright: ignore[reportUnusedVariable]
+    if kind == "add":
+        return True
     old_type, new_type = detail
-    if is_void_specialization(old_type, new_type): return False
+    if is_void_specialization(old_type, new_type):
+        return False
     return True
 
 
 class TestStubConversion(unittest.TestCase):
     def test_equality(self):
         """Ensure that ctyped does not break anything."""
-        old_function_dict: Dict[str, Dict[str, Any]] = {name: old_data_to_dict(val) for name, *val in FUNCTION_LIST}
+        old_function_dict: Dict[str, Dict[str, Any]] = {
+            name: old_data_to_dict(val) for name, *val in FUNCTION_LIST
+        }
         new_function_dict = generate_metadata_debug()
 
         missing_functions = set(old_function_dict.keys())
         stable_functions: Set[str] = set()
         for new_func in new_function_dict:
             if new_func in missing_functions:
                 missing_functions.remove(new_func)
                 stable_functions.add(new_func)
 
-        type_diff = [list(dictdiff(old_function_dict[name], new_function_dict[name])) for name in stable_functions] # type: ignore
-        type_break = [diffset for diffset in type_diff if diffset and any(is_incompatible_diff(diff) for diff in diffset)] # type: ignore
-
-        self.assertTrue(not missing_functions, f'Functions {missing_functions} are missing after stub conversion!')
-        self.assertTrue(not type_break, f'Type break happens after stub conversion!')
+        type_diff = [list(dictdiff(old_function_dict[name], new_function_dict[name])) for name in stable_functions]  # type: ignore
+        type_break = [diffset for diffset in type_diff if diffset and any(is_incompatible_diff(diff) for diff in diffset)]  # type: ignore
+
+        self.assertTrue(
+            not missing_functions,
+            f"Functions {missing_functions} are missing after stub conversion!",
+        )
+        self.assertTrue(not type_break, f"Type break happens after stub conversion!")

``````````

</details>


https://github.com/llvm/llvm-project/pull/101784


More information about the cfe-commits mailing list