| 34 | return t.name |
| 35 | |
| 36 | class PythonStubFuncDeclVisitor(c_ast.NodeVisitor): |
| 37 | def __init__(self): |
| 38 | self.sigs = {} |
| 39 | self.sources = {} |
| 40 | |
| 41 | def get_source_snippet_lines(self, coord: pycparser.plyparser.Coord) -> Tuple[list[str], list[str]]: |
| 42 | if coord.file not in self.sources: |
| 43 | with open(coord.file, 'rt') as f: |
| 44 | self.sources[coord.file] = f.readlines() |
| 45 | source_lines = self.sources[coord.file] |
| 46 | ncomment_lines = len(list(itertools.takewhile(lambda i: re.search(r'^\s*(//|/\*)', source_lines[i]), range(coord.line - 2, -1, -1)))) |
| 47 | comment_lines = [l.strip() for l in source_lines[coord.line - 1 - ncomment_lines:coord.line - 1]] |
| 48 | decl_lines = [] |
| 49 | for line in source_lines[coord.line - 1:]: |
| 50 | decl_lines.append(line.rstrip()) |
| 51 | if (';' in line) or ('{' in line): break |
| 52 | return (comment_lines, decl_lines) |
| 53 | |
| 54 | def visit_Enum(self, node: Enum): |
| 55 | if node.values is not None: |
| 56 | for e in node.values.enumerators: |
| 57 | self.sigs[e.name] = f' @property\n def {e.name}(self) -> int: ...' |
| 58 | |
| 59 | def visit_Typedef(self, node: Typedef): |
| 60 | pass |
| 61 | |
| 62 | def visit_FuncDecl(self, node: FuncDecl): |
| 63 | ret_type = node.type |
| 64 | is_ptr = False |
| 65 | while isinstance(ret_type, PtrDecl): |
| 66 | ret_type = ret_type.type |
| 67 | is_ptr = True |
| 68 | |
| 69 | fun_name = ret_type.declname |
| 70 | if fun_name.startswith('__'): |
| 71 | return |
| 72 | |
| 73 | args = [] |
| 74 | argnames = [] |
| 75 | def gen_name(stem): |
| 76 | i = 1 |
| 77 | while True: |
| 78 | new_name = stem if i == 1 else f'{stem}{i}' |
| 79 | if new_name not in argnames: return new_name |
| 80 | i += 1 |
| 81 | |
| 82 | for a in node.args.params: |
| 83 | if isinstance(a, EllipsisParam): |
| 84 | arg_name = gen_name('args') |
| 85 | argnames.append(arg_name) |
| 86 | args.append('*' + gen_name('args')) |
| 87 | elif format_type(a.type) == 'None': |
| 88 | continue |
| 89 | else: |
| 90 | arg_name = a.name or gen_name('arg') |
| 91 | argnames.append(arg_name) |
| 92 | args.append(f'{arg_name}: {format_type(a.type)}') |
| 93 | |