Parametrize ParamSpec or TypedDicts with callables to provide signature data

I figure that was discussed before, but I haven’t been able to find the relevant topics, maybe I can revive the discussion

TL;DR (skip to idea section)

Motivation

One should prefer explicit over implicit, but what if you cannot be explicit?

Lets say I am using a 3rd party library for example seaborn.lineplot, which in turn uses matplotlib as a 4th party library.

seaborn.lineplot(data=None, *, <explicity_keywords>, err_kws=None, **kwargs)

Without consulting the matplotlib documentation I do not know what is possible for err_kws and kwargs. Static type-checkers and autocompletion cannot help me (without special casing) and if I write a wrapper I also cannot provide explicit annotations to inform my users on allowed keywords.

What can we currently do?

The best tool we have currently at our disposal is kwargs hinting with TypedDicts (PEP 692). For example to type such a function currently we could need two TypedDicts for two the keyword arguments:

seaborn.lineplot(data=None, *, err_kws: ErrorBarsKeywords=None, **kwargs: **AxesPlotKeywords)

However, to maintain such TypedDicts is an infeasible task and has to align with the API. For each function synced TypedDict must be mainted, this will bloat the code and needs maintainers.


Idea

A new usage for ParamSpec or TypedDict to be parametrized with a callable to provide information about the signature in a PEP 692 manner, for example:

def my_plot(data, fig_kws: ParamSpec[plt.figure], **plot_kws: **ParamSpec[plt.plot]):
    fig =plt.figure(**fig_kws)
    plt.plot(data, **plot_kws)
    return fig

# Annotate as a keyword dictionary from the signature of plt.figure
figure_parameters: ParamSpec[plt.figure] = {
    'figsize' : (5, 5)
    'color' = "blue"  # <-- Report invalid keyword for plt.figure
}

# autocomplete and checks against plt.figure and plt.plot
my_plot(data, 
    figure_parameters,
    linestyle="--")

In this example autocompleters can fill in possible keywords by copying their knowledge about the 3rd party functions plt.figure (resp. plt.plot), likewise can functions parameters be checked for correctness. A tooltip could fill in all the keywords from plt.plot and provide go-to-definition for plt.figure.


Runtime

Extending ParamSpec to support the parametrization ParamSpec[some_callable] would not require a new public symbol and is semantically meaningful.
Weather the resulting object should be a TypedDict or a new (private) class that is treated similar is open to discussion.
Possibly should the dunder attributes be lazily evaluated or just be a proxy to access attributes of the callable and hence not follow the TypedDict interface.


What are your ideas on this?
Would you welcome such a new feature to be picked up?
What are your concerns, helpful ideas?

2 Likes

Variants of this idea have indeed been discussed, like in Extract kwargs types from a function signature (and I vaguely remember other related topics in the Typing category).

I definitely think there’s something needed in this space, but it may need to wait until the bases of typing specification are stable enough.

2 Likes