Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Parameter signatures #742

Merged
merged 16 commits into from
May 25, 2023
Merged

Improve Parameter signatures #742

merged 16 commits into from
May 25, 2023

Conversation

maximlt
Copy link
Member

@maximlt maximlt commented Apr 17, 2023

Fixes #736

This is for now just a POC, I'd like to get the opinion of others before proceeding any further. Reminder, the signatures have changed with the Sentinel PR, now all the default values are Undefined. So this PR attempts to fix that:

  • static code analysis (e.g. in VSCode): by using typing.overload on a stub __init__ method, see https://github.com/holoviz/param/commit/b9e0ce0476099e88778fee4e6ec4b12f7f79e3d2.- In this example I have not put **kwargs in the signature, contrary to the original signature. Instead I have added all the keywords defined in Parameter.__init__. I believe that's a nicer UX. That's unfortunately not DRY, but I don't think it's possible to dynamically add the keywords to the overloaded signature, it all has to be static.
    image

  • dynamic code analysis (e.g. in Jupyter Lab): by updating __signature__. Hmm I just realize that param.Parameter does not have it signature updated, I'll fix that.

image

@maximlt maximlt marked this pull request as draft April 17, 2023 07:50
Copy link
Member

@jbednar jbednar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great to me! What's draft about it?

@maximlt
Copy link
Member Author

maximlt commented May 11, 2023

Draft as it only updated the static signature of only one Parameter type. I wanted to get some feedback on the approach, which I've got now so I can keep going! I'll also attempt to write some tests.

@maximlt maximlt marked this pull request as ready for review May 24, 2023 16:08
@maximlt
Copy link
Member Author

maximlt commented May 25, 2023

This PR really accomplishes two things:

  1. The PR that added Undefined to the Parameter docstrings was hiding the real default value presented in the docstring of each Parameter, both statically (e.g. in VSCode) and dynamically (e.g. in a notebook). This PR fixes this regression.
  2. Working on 1. meant having to inspect the signature of all the Parameters. Most of them had a few specific arguments and were then routing keyword arguments (i.e. **kwargs) to their super classes, up to the base Parameter. This wasn't a great user experience, which this PR fixes for both the static (using typing.overloads) and dynamic (building an expanded signature) cases.

Notebook experience

image image

VSCode experience

image image

I'll do a last check tomorrow and merge if I don't spot any major issue.

@maximlt
Copy link
Member Author

maximlt commented May 25, 2023

I ran a doc build to check that the changes I made to the signature were not affecting them badly. I saw no warning related to that and the signature of each Parameter now contains its full list of arguments.

Before:
image

After:
image

@maximlt
Copy link
Member Author

maximlt commented May 25, 2023

This is all a bit confusing:

import warnings

warnings.warn('On Import', DeprecationWarning)

def debug_stacklevel_default():
    warnings.warn('Debug default', DeprecationWarning)

def debug_stacklevel2():
    warnings.warn('Debug stack level 2', DeprecationWarning, stacklevel=2)


if __name__ == '__main__':
    debug_stacklevel_default()
    debug_stacklevel2()
image

EDIT: same behavior in the Python REPL, so that's not specific to IPython.

@maximlt
Copy link
Member Author

maximlt commented May 25, 2023

OK I finally understand what's going on. These are the default Python warning filters:

default::DeprecationWarning:__main__
ignore::DeprecationWarning
ignore::PendingDeprecationWarning
ignore::ImportWarning
ignore::ResourceWarning

DeprecationWarnings are displayed when emitted from __main__ (see https://peps.python.org/pep-0565/).

In the REPL or in a notebook __name__ is __main__. When debug_stacklevel_default is called in the REPL, it calls warnings.warn but at this point __name__ is foo so the DeprecationWarning is not displayed. debug_stacklevel2 calls warnings.warn with a stacklevel of 2, the frame above being the notebook context in which we have __name__ as __main__, so the DeprecationWarning is displayed.

Interestingly, it means that when you set the stacklevel correctly, i.e. pointing to the line that causes the warning and not in some weird place down the stack, and if that line happens to be written directly in the REPL/notebook, the DeprecationWarning is displayed.

Param can be quite heavily used in a notebook and what we're deprecating in this PR (and others) are APIs that are used directly by Param users. As such DeprecationWarnings would be showed in their notebook. I don't think that's our intention here in the first phase of the deprecation cycle, at least I vaguely remember having a discussion about that. I will update the PR to emit PendingDeprecationWarnings instead, and in some time we can update Param to emit FutureWarnings.

@maximlt
Copy link
Member Author

maximlt commented May 25, 2023

Given there was already a positive review, I'm going to merge and we can iterate later if there's a need for it.

@maximlt maximlt merged commit 62273ef into main May 25, 2023
@maximlt maximlt deleted the fix_parameter_signatures branch May 25, 2023 20:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Fix the Parameter signatures
2 participants