Forward function signature in VSCode

Question:

Say I have a function in src/f1.py with the following signature:


def my_func(a1: int, a2: bool) -> float:
    ...

In a separate file src/f2.py I create a dictionary:

from src.f1 import my_func

my_dict = {
    "func": my_func
}

In my final file src/test1.py I call the function:

from src.f2 import my_dict

print(my_dict["func"](1, True))

I’m getting IDE auto-suggestions for my_func in src/f2.py, but not in src/test1.py. I have tried using typing.Callable, but it doesn’t create the same signature and it loses the function documentation. Is there any way I can get these in src/test1.py without changing the structure of my code?
I don’t want to change the files in which my functions, dictionaries, or tests are declared.

I use VSCode version 1.73.1 and Python version 3.8.13. I cannot change my Python version.

I tried creating different types of Callable objects, but had problems getting the desired results.

  1. They seem to have no docstring support
  2. Some types are optional. I couldn’t get that to work.
  3. They do not work with variable names, only data types. I want the variable names (argument names to the function) to be there in the IDE suggestion.

What am I trying to do really?

I am trying to implement a mechanism where a user can set the configurations for a library in a single file. That single file is where all the dictionaries are stored (and it imports all essential functions).

This "configuration dictionary" is called in the main python file (or wherever needed). I have functions in a set of files for accomplishing a specific set of tasks.
Say functions fa1 and fa2 for task A; fb1, fb2, and fb3 for task B; and fc1 for task C. I want configurations (choices) for task A, followed by B, then C. So I do

work_ABC = {"A": fa1, "B": fb2, "C": fc1};

Now, I have a function like

wd = work_ABC
def do_work_abc(i, do_B=True):
    res_a = wd["A"](i)
    res_b = res_a
    if do_B:
        res_b = wd["B"](res_a)
    res_c = wd["C"](res_b)
    return res_c

If you have a more efficient way how I can implement the same thing, I’d love to hear it.

I want IntelliSense to give me the function signature of the function set for the dictionary.

Asked By: Avneesh Mishra

||

Answers:

There is no type annotation construct in Python that covers docstrings or parameter names of functions. There isn’t even one for positional-only or keyword-only parameters (which would be actually meaningful in a type sense).

As I already mentioned in my comment, docstrings and names are not type-related. Ultimately, this is an IDE issue. PyCharm for example has no problem inferring those details with the setup you provided. I get the auto-suggestion for my_dict["func"] with the parameter names because PyCharm is smart/heavy enough to track it to the source. But it has its limits. If I change the code in f2 to this:

from src.f1 import my_func

_other_dict = {
    "func": my_func
}
my_dict = {}
my_dict.update(_other_dict)

Then the suggestion engine is lost.

The reason is simply the discrepancy between runtime and static analysis. At some point it becomes silly/unreasonable to expect a static analysis tool to essentially run the code for you. This is why I always say:

Static type checkers don’t execute your code, they just read it.

Even the fact that PyCharm "knows" the signature of my_func with your setup entails it running some non-trivial code in the background to back-track from the dictionary key to the dictionary to the actual function definition.

So in short: It appears you are out of luck with VSCode. And parameter names and docstrings are not part of the type system.

Answered By: Daniil Fajnberg