Skip to content

Mypy plugins: Changing class signature impossible here? #19195

Open
@eliegoudout

Description

@eliegoudout

Hello,

I'm trying to write a plugin for my paramclasses library. I already posted about it on gitter to ask a few questions (without answer at the moment).

I'm still trying to get to work on my library's typing issues whilst being a complete noob on the subject.

So I started by writing a logger-like dummy plugin which shows the called hooked with their args/kwargs (so that I understand the mechanisms a bit better), and trying to solve the signature problem.

1. Nonparamclass MWE: looks OK

Here's a MWE:

class A:
    def __init__(self, *args: object, **kwargs: object) -> None:
    """Takes anything at runtime but raises unless only 'foo' kwarg."""
        if args or list(kwargs) != ["foo"]:
            msg = "Only 'foo' kwarg is acceptable"
            raise ValueError(msg)

        self.foo = kwargs.get("foo")


A(bar="should fail")

I would like mypy to pick up the fact that the signature is in fact A(*, foo). The logger picks up this (filtered to keep only signature related hooks):
(removing the report hook):

[get_function_signature_hook] → ('builtins.list',), {}
[get_method_signature_hook] → ('builtins.list.__ne__',), {}
[get_function_signature_hook] → ('builtins.ValueError',), {}
[get_method_signature_hook] → ('builtins.dict.get',), {}
[get_method_signature_hook] → ('builtins.dict.get',), {}
[get_method_signature_hook] → ('builtins.object.__init_subclass__',), {}
[get_function_signature_hook] → ('mwe.A',), {}

Q1. Am I right to assume that I logically should use get_function_signature_hook with mwe.A for this example?If so, I think this works fine since I have a way to write a plugin to do what I want.

Now on to my use case

2. Paramclass MWE: not OK

My usecase MWE would be:

from paramclasses import ParamClass


class A(ParamClass):
    foo: int


A(bar="should fail")

When I filter out the logger plugin output, to keep only the "signature" hook, I only get this which refers to internals that seem unrelated:

[get_function_signature_hook] → ('paramclasses.paramclasses._MissingType',), {}
[get_function_signature_hook] → ('paramclasses.paramclasses._run_once',), {}
[get_function_signature_hook] → ('paramclasses.paramclasses._run_once',), {}
[get_function_signature_hook] → ('paramclasses.paramclasses._run_once',), {}

So in the end, I'm completely lost on what I should/could do.

Q2. Is there a way to think about understanding the problem? Note that if useful, the __signature__ attribute returns the desired result at runtim.


Thanks in advance!
Élie

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions