|
16 | 16 | # specific language governing permissions and limitations |
17 | 17 | # under the License. |
18 | 18 |
|
| 19 | +import ast |
19 | 20 | import os |
20 | 21 | import sys |
21 | 22 | import subprocess |
@@ -61,6 +62,27 @@ def find_thrift(): |
61 | 62 | return None |
62 | 63 |
|
63 | 64 |
|
| 65 | +def find_keyword_literal_except_types(py_files): |
| 66 | + """ |
| 67 | + "True"/"False"/"None" are valid Python expression atoms (unlike most |
| 68 | + other reserved words), so an unescaped "except True as e:" parses fine |
| 69 | + -- it just silently tries to catch the literal bool/None instead of the |
| 70 | + intended exception class, and would raise a runtime TypeError once hit. |
| 71 | + py_compile can't see this; walk the AST instead. |
| 72 | + """ |
| 73 | + problems = [] |
| 74 | + for py_file in py_files: |
| 75 | + with open(py_file) as f: |
| 76 | + try: |
| 77 | + tree = ast.parse(f.read(), filename=py_file) |
| 78 | + except SyntaxError: |
| 79 | + continue # already reported by the compile check |
| 80 | + for node in ast.walk(tree): |
| 81 | + if isinstance(node, ast.ExceptHandler) and isinstance(node.type, ast.Constant): |
| 82 | + problems.append((py_file, node.lineno, repr(node.type.value))) |
| 83 | + return problems |
| 84 | + |
| 85 | + |
64 | 86 | def test_keyword_escape_compilation(): |
65 | 87 | """ |
66 | 88 | Test that the Python generator produces valid Python code |
@@ -118,6 +140,13 @@ def test_keyword_escape_compilation(): |
118 | 140 | print(" " + file_path + ": " + error) |
119 | 141 | return 1 |
120 | 142 |
|
| 143 | + keyword_literal_excepts = find_keyword_literal_except_types(py_files) |
| 144 | + if keyword_literal_excepts: |
| 145 | + print("ERROR: Generated code catches a keyword literal instead of an exception class:") |
| 146 | + for file_path, lineno, value in keyword_literal_excepts: |
| 147 | + print(" " + file_path + ":" + str(lineno) + ": except " + value + " as ...") |
| 148 | + return 1 |
| 149 | + |
121 | 150 | print("OK: All " + str(len(all_files)) + " generated Python files compile successfully") |
122 | 151 | return 0 |
123 | 152 |
|
|
0 commit comments