|
| 1 | +from typing import Optional |
| 2 | +from mypy.plugin import Plugin, FunctionContext |
| 3 | +from mypy.types import Type, Instance |
| 4 | +from mypy.nodes import ARG_POS |
| 5 | + |
| 6 | +class CompileFilenamePlugin(Plugin): |
| 7 | + def get_function_hook(self, fullname: str): |
| 8 | + # Hook only the built-in compile function |
| 9 | + if fullname == "builtins.compile": |
| 10 | + return compile_hook |
| 11 | + return None |
| 12 | + |
| 13 | +def compile_hook(ctx: FunctionContext) -> Type: |
| 14 | + # Arguments to compile: source, filename, mode, ... |
| 15 | + # filename is arg index 1 (zero-based) |
| 16 | + if len(ctx.arg_types) > 1 and ctx.arg_types[1]: |
| 17 | + filename_type = ctx.arg_types[1][0] # first argument passed for filename param |
| 18 | + if is_bytearray_type(filename_type): |
| 19 | + ctx.api.fail( |
| 20 | + "Passing 'bytearray' as filename to 'compile()' is not allowed", |
| 21 | + ctx.args[1][0] |
| 22 | + ) |
| 23 | + return ctx.default_return_type |
| 24 | + |
| 25 | +def is_bytearray_type(typ: Type) -> bool: |
| 26 | + # Check if the type is exactly bytearray |
| 27 | + if isinstance(typ, Instance): |
| 28 | + # The full name for builtins.bytearray is 'builtins.bytearray' |
| 29 | + return typ.type.fullname == "builtins.bytearray" |
| 30 | + return False |
| 31 | + |
| 32 | +def plugin(version: str): |
| 33 | + return CompileFilenamePlugin |
0 commit comments