Search code examples
pythonmypy

mypy plugin callback not being called


I'm trying to make my first mypy plugin to add typechecking for this code

adt.py

from dataclasses import make_dataclass

def adt(datatype, *ctrs: str):
    basecls = type(datatype, (), {})
    klass = lambda x: x.split()[0]
    fields = lambda x: x.split()[1:]
    clss = (make_dataclass(klass(cls),
                           bases=(basecls,),
                           fields=fields(cls))
            for cls in ctrs)
    return (basecls, *clss)


Maybe, Just, None_ = adt("Maybe", "Just x", "None")

j = Just(1)


def foo(m: Maybe):
    pass

I create a adt_plugin.py file saved to disk and configured mypy.ini to load it, it's being loaded (I can see some of the prints), but it seems that my plugin callback is not being called, what I'm missing?

My plugin code doesn't do nothing, it just fails by now

adt_plugin.py

from typing import *
from mypy.plugin import Plugin, DynamicClassDefContext

T = TypeVar('T')
CB = Optional[Callable[[T], None]]


class AdtPlugin(Plugin):
    def get_dynamic_class_hook(self, fullname: str) -> 'CB[DynamicClassDefContext]':
        print(fullname)
        if fullname == "adt.adt":
            print("foo")
            print(decl_info_hook)
            return decl_info_hook
        return None


def plugin(version: str):
    # ignore version argument if the plugin works with all mypy versions.
    return AdtPlugin

def decl_info_hook(ctx : DynamicClassDefContext) -> None:
    ctx.api.fail("Not able to calculate MRO for declarative base", ctx.call)

mypy.ini (on the current folder)

[mypy]
plugins = /home/geckos/code/python/adt_plugin.py

When I run mypy adt.py I see:

 python mypy --no-incremental adt.py
builtins.object
builtins.object
builtins.object
builtins.object
builtins.object
builtins.object
builtins.object
builtins.object
builtins.object
builtins.object
builtins.object
builtins.object
builtins.object
builtins.object
adt.adt
foo
<function decl_info_hook at 0x7f55cabf9ab0>
adt.Just
builtins.type
adt.py:19: error: Variable "adt.Maybe" is not valid as a type
adt.py:19: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
Found 1 error in 1 file (checked 1 source file)

So there is foo, so that AdtPlugin.get_dynamic_class_hook is being called, and it's returning the decl_info_hook too, the function name is right, we can see it in the print, but the function is not called at all, I put an error on it, I also tried raise Exception("foooo") inside of it but nothings happens.

Any idea how to debug this?


Solution

  • Okay, I got the problem, mypy won't detect this x, y, ..., z = something() as a dynamic class creation. The statement need to have the form a = f() where a single value is assigned, otherwise it won't call the plugin hook.