forked from earth-system-radiation/pyRTE-RRTMGP
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcheck_binds.py
More file actions
110 lines (82 loc) · 3.01 KB
/
check_binds.py
File metadata and controls
110 lines (82 loc) · 3.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
"""Compare C function declarations with Pybind11 bindings.
Example usage:
```
python check_binds.py \
--c_headers /path/to/rrtmgp_kernels.h /path/to/rte_kernels.h \
--pybind /path/to/pybind_interface.cpp
```
"""
import argparse
import re
def extract_c_functions(file_paths): # type: ignore
"""Extract C function names from the given header files.
Args:
file_paths (list of str): List of paths to C header files.
Returns:
set: A set of C function names.
"""
functionNames = set()
for filePath in file_paths:
try:
with open(filePath, "r", encoding="utf-8") as file:
content = file.read()
functionPattern = re.findall(r'extern "C" \{([\s\S]*?)\}', content)
if not functionPattern:
print(f"Warning: No 'extern \"C\"' block found in {filePath}")
# Skip to the next file
continue
functions = re.findall(r"\bvoid\s+(\w+)\s*\(", functionPattern[0])
functionNames.update(functions)
except FileNotFoundError:
print(f"Error: File not found: {filePath}")
return functionNames
def extract_pybind_functions(pybind_file): # type: ignore
"""Extract function names bound using Pybind11 from the given file.
Args:
pybind_file (str): Path to the Pybind11 binding file.
Returns:
set: A set of function names bound using Pybind11.
"""
try:
with open(pybind_file, "r", encoding="utf-8") as file:
content = file.read()
boundFunctions = set(re.findall(r'm\.def\("(\w+)"', content))
return boundFunctions
except FileNotFoundError:
print(f"Error: Pybind11 file not found: {pybind_file}")
return set()
def main(): # type: ignore
"""Compare C function declarations with Pybind11 bindings."""
parser = argparse.ArgumentParser(
description="Compare C function declarations with Pybind11 bindings."
)
parser.add_argument(
"--c_headers",
nargs="+",
required=True,
help="List of C header files to check.",
)
parser.add_argument(
"--pybind",
required=True,
help="Path to the Pybind11 binding file.",
)
args = parser.parse_args()
cFunctions = extract_c_functions(args.c_headers)
pybindFunctions = extract_pybind_functions(args.pybind)
missingPyBindings = cFunctions - pybindFunctions
missingCBindings = pybindFunctions - cFunctions
print(f"Total C functions found: {len(cFunctions)}")
print(f"Total Py functions bound: {len(pybindFunctions)}")
if missingCBindings:
print("\nWarning: Missing C function bindings:")
for func in sorted(missingCBindings):
print(f"- {func}")
if missingPyBindings:
print("\nWarning: Missing Py function bindings:")
for func in sorted(missingPyBindings):
print(f"- {func}")
else:
print("\nAll C functions are properly bound.")
if __name__ == "__main__":
main()