summaryrefslogtreecommitdiff
path: root/tests/test_typestubs.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_typestubs.py')
-rw-r--r--tests/test_typestubs.py53
1 files changed, 53 insertions, 0 deletions
diff --git a/tests/test_typestubs.py b/tests/test_typestubs.py
new file mode 100644
index 0000000..6a8d75f
--- /dev/null
+++ b/tests/test_typestubs.py
@@ -0,0 +1,53 @@
1import ast
2import re
3
4
5def read_stubfile():
6 with open("adblock/adblock.pyi", encoding="utf-8") as file:
7 node = ast.parse(file.read())
8 return node
9
10
11def get_functions_and_methods(node):
12 functions = [n for n in node.body if isinstance(n, ast.FunctionDef)]
13 classes = [n for n in node.body if isinstance(n, ast.ClassDef)]
14
15 methods = {}
16 for c in classes:
17 methods[c.name] = [n for n in c.body if isinstance(n, ast.FunctionDef)]
18
19 return functions, methods
20
21
22def pattern_exists_in_file(filename, regex):
23 """
24 Checks if the given regex is present in the given file
25 """
26 with open(filename, "r", encoding="utf-8") as f:
27 for line in f:
28 if re.search(regex, line):
29 return True
30 return False
31
32
33def test_functions_and_methods_exist_in_rust():
34 """
35 Check that for each of the functions and methods present in the Python
36 typestub file, there is a line in `src/lib.rs` containing a matching
37 definition. Since we're doing a naive grep search, without access to the
38 Rust AST, there may be false negatives.
39 """
40 stubfile_node = read_stubfile()
41 functions, methods = get_functions_and_methods(stubfile_node)
42
43 methods_flattened = []
44 for class_methods in methods.values():
45 methods_flattened += class_methods
46
47 for f in functions + methods_flattened:
48 if f.name.startswith("__"):
49 # Skip dunder methods since their names are the same for every
50 # class, making the test not particularly useful. They are also not
51 # marked `pub` in Rust.
52 continue
53 assert pattern_exists_in_file("src/lib.rs", r"pub fn {}".format(f.name))