From 3d2f43772262060fdb1921933da6dc8c7d8ad8a1 Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Wed, 31 May 2023 12:20:23 +0200 Subject: [PATCH] Fix crash with custom ErrorCodes (#15327) A class marked with `allow_interpreted_subclasses=True` implicitly supports serialization while also allowing it to be subclassed by pure Python code. Fixes #15255 https://mypyc.readthedocs.io/en/latest/differences_from_python.html#pickling-and-copying-objects https://mypyc.readthedocs.io/en/latest/native_classes.html#inheritance --- mypy/errorcodes.py | 2 +- test-data/unit/check-custom-plugin.test | 12 ++++++++++++ test-data/unit/plugins/custom_errorcode.py | 20 ++++++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 test-data/unit/plugins/custom_errorcode.py diff --git a/mypy/errorcodes.py b/mypy/errorcodes.py index fe460fdec744..50a82be9816d 100644 --- a/mypy/errorcodes.py +++ b/mypy/errorcodes.py @@ -14,7 +14,7 @@ sub_code_map: dict[str, set[str]] = defaultdict(set) -@mypyc_attr(serializable=True) +@mypyc_attr(allow_interpreted_subclasses=True) class ErrorCode: def __init__( self, diff --git a/test-data/unit/check-custom-plugin.test b/test-data/unit/check-custom-plugin.test index d7beea0390e7..c81de675d808 100644 --- a/test-data/unit/check-custom-plugin.test +++ b/test-data/unit/check-custom-plugin.test @@ -1014,3 +1014,15 @@ reveal_type(MyClass.foo_staticmethod) # N: Revealed type is "def (builtins.int) [file mypy.ini] \[mypy] plugins=/test-data/unit/plugins/add_classmethod.py + +[case testCustomErrorCodePlugin] +# flags: --config-file tmp/mypy.ini --show-error-codes +def main() -> int: + return 2 + +main() # E: Custom error [custom] +reveal_type(1) # N: Revealed type is "Literal[1]?" + +[file mypy.ini] +\[mypy] +plugins=/test-data/unit/plugins/custom_errorcode.py diff --git a/test-data/unit/plugins/custom_errorcode.py b/test-data/unit/plugins/custom_errorcode.py new file mode 100644 index 000000000000..0e2209a32eca --- /dev/null +++ b/test-data/unit/plugins/custom_errorcode.py @@ -0,0 +1,20 @@ +from mypy.errorcodes import ErrorCode +from mypy.plugin import Plugin +from mypy.types import AnyType, TypeOfAny + +CUSTOM_ERROR = ErrorCode(code="custom", description="", category="Custom") + + +class CustomErrorCodePlugin(Plugin): + def get_function_hook(self, fullname): + if fullname.endswith(".main"): + return self.emit_error + return None + + def emit_error(self, ctx): + ctx.api.fail("Custom error", ctx.context, code=CUSTOM_ERROR) + return AnyType(TypeOfAny.from_error) + + +def plugin(version): + return CustomErrorCodePlugin