|
5 | 5 | """ |
6 | 6 |
|
7 | 7 | __all__ = [ |
| 8 | + "assert_no_if", |
| 9 | + "assert_no_for", |
| 10 | + "assert_no_while", |
| 11 | + "assert_no_loops", |
8 | 12 | "count_calls", |
9 | 13 | "count_comments", |
10 | 14 | "count_nodes", |
11 | | - "count_while_loops", |
12 | 15 | "count_regex_matches", |
13 | 16 | "get_source_code", |
14 | 17 | ] |
|
72 | 75 | ] |
73 | 76 |
|
74 | 77 |
|
| 78 | +def assert_no_if(filename, main=True): |
| 79 | + """Check that no if statements/expressions are used. |
| 80 | +
|
| 81 | + Args: |
| 82 | + filename (str): The source file to parse. |
| 83 | + main (bool): Don't count if __name__ == "__main__". |
| 84 | + """ |
| 85 | + count = 0 |
| 86 | + if main: |
| 87 | + source = get_source_code(filename) |
| 88 | + tree = ast.parse(source, filename) |
| 89 | + # Iterate top-level statements only |
| 90 | + for node in tree.body: |
| 91 | + if ( |
| 92 | + isinstance(node, ast.If) |
| 93 | + and isinstance(node.test, ast.Compare) |
| 94 | + and isinstance(node.test.left, ast.Name) |
| 95 | + and node.test.left.id == "__name__" |
| 96 | + and len(node.test.ops) == 1 |
| 97 | + and isinstance(node.test.ops[0], ast.Eq) |
| 98 | + and isinstance(node.test.comparators[0], ast.Constant) |
| 99 | + and node.test.comparators[0].value == "__main__" |
| 100 | + ): |
| 101 | + count += 1 |
| 102 | + node_count = count_nodes(filename) |
| 103 | + assert node_count["If"] == count, "If statements are not allowed" |
| 104 | + assert node_count["IfExp"] == 0, "If expressions are not allowed" |
| 105 | + |
| 106 | + |
| 107 | +def assert_no_for(filename, comps=True): |
| 108 | + """Check that no for loops are used. |
| 109 | +
|
| 110 | + Args: |
| 111 | + filename (str): The source file to parse. |
| 112 | + comps (bool): Also check for comprehensions and generator expressions. |
| 113 | + """ |
| 114 | + node_count = count_nodes(filename) |
| 115 | + assert node_count["For"] == 0, "For loops are not allowed" |
| 116 | + if comps: |
| 117 | + assert node_count["ListComp"] == 0, "List comprehensions are not allowed" |
| 118 | + assert node_count["SetComp"] == 0, "Set comprehensions are not allowed" |
| 119 | + assert node_count["DictComp"] == 0, "Dict comprehensions are not allowed" |
| 120 | + assert node_count["GeneratorExp"] == 0, "Generator expressions are not allowed" |
| 121 | + |
| 122 | + |
| 123 | +def assert_no_while(filename): |
| 124 | + """Check that no while loops are used. |
| 125 | +
|
| 126 | + Args: |
| 127 | + filename (str): The source file to parse. |
| 128 | + """ |
| 129 | + node_count = count_nodes(filename) |
| 130 | + assert node_count["While"] == 0, "While loops are not allowed" |
| 131 | + |
| 132 | + |
| 133 | +def assert_no_loops(filename): |
| 134 | + """Calls assert_no_for() and assert_no_while(). |
| 135 | +
|
| 136 | + Args: |
| 137 | + filename (str): The source file to parse. |
| 138 | + """ |
| 139 | + assert_no_for(filename) |
| 140 | + assert_no_while(filename) |
| 141 | + |
| 142 | + |
75 | 143 | def count_calls(filename, func_id): |
76 | 144 | """Count how many times a function is called. |
77 | 145 |
|
@@ -99,6 +167,9 @@ def count_calls(filename, func_id): |
99 | 167 | def count_comments(filename): |
100 | 168 | """Count the number of # comments in a program. |
101 | 169 |
|
| 170 | + Args: |
| 171 | + filename (str): The source file to parse. |
| 172 | +
|
102 | 173 | Returns: |
103 | 174 | int: Number of end-of-line comments found. |
104 | 175 | """ |
@@ -133,19 +204,6 @@ def count_nodes(filename): |
133 | 204 | return Counter(type(node).__name__ for node in ast.walk(tree)) |
134 | 205 |
|
135 | 206 |
|
136 | | -def count_while_loops(filename): |
137 | | - """Count the number of while loops in a program. |
138 | | -
|
139 | | - Args: |
140 | | - filename (str): The source file to parse. |
141 | | -
|
142 | | - Returns: |
143 | | - int: Number of while loops found. |
144 | | - """ |
145 | | - nodes = count_nodes(filename) |
146 | | - return nodes['While'] |
147 | | - |
148 | | - |
149 | 207 | def count_regex_matches(filename, pattern, strip_comments=True): |
150 | 208 | """Count the number of regex pattern matches in code. |
151 | 209 |
|
|
0 commit comments