-
-
Notifications
You must be signed in to change notification settings - Fork 4.4k
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
set default value from signature defaults in interact #5136
Changes from 2 commits
856bcf1
cfc7753
ee4033c
077dde6
104d17b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,7 +26,9 @@ | |
ContainerWidget, DOMWidget) | ||
from IPython.display import display, clear_output | ||
from IPython.utils.py3compat import string_types, unicode_type | ||
from IPython.utils.traitlets import HasTraits, Any, Unicode | ||
from IPython.utils.traitlets import HasTraits, TraitError, Any, Unicode | ||
|
||
empty = Parameter.empty | ||
|
||
#----------------------------------------------------------------------------- | ||
# Classes and Functions | ||
|
@@ -108,12 +110,20 @@ def _widget_abbrev(o): | |
else: | ||
return _widget_abbrev_single_value(o) | ||
|
||
def _widget_from_abbrev(abbrev): | ||
"""Build a Widget intstance given an abbreviation or Widget.""" | ||
def _widget_from_abbrev(abbrev, default=empty): | ||
"""Build a Widget instance given an abbreviation or Widget.""" | ||
if isinstance(abbrev, Widget) or isinstance(abbrev, fixed): | ||
return abbrev | ||
|
||
widget = _widget_abbrev(abbrev) | ||
if default is not empty and isinstance(abbrev, (list, tuple)): | ||
# if it's not a single-value abbreviation, | ||
# set the initial value from the default | ||
try: | ||
widget.value = default | ||
except TraitError: | ||
# warn? | ||
pass | ||
if widget is None: | ||
raise ValueError("%r cannot be transformed to a Widget" % (abbrev,)) | ||
return widget | ||
|
@@ -124,50 +134,38 @@ def _yield_abbreviations_for_parameter(param, kwargs): | |
kind = param.kind | ||
ann = param.annotation | ||
default = param.default | ||
empty = Parameter.empty | ||
not_found = (None, None) | ||
if kind == Parameter.POSITIONAL_OR_KEYWORD: | ||
if name in kwargs: | ||
yield name, kwargs.pop(name) | ||
elif ann is not empty: | ||
if default is empty: | ||
yield name, ann | ||
else: | ||
yield name, ann | ||
elif default is not empty: | ||
yield name, default | ||
else: | ||
yield not_found | ||
elif kind == Parameter.KEYWORD_ONLY: | ||
not_found = (name, empty, empty) | ||
if kind in (Parameter.POSITIONAL_OR_KEYWORD, Parameter.KEYWORD_ONLY): | ||
if name in kwargs: | ||
yield name, kwargs.pop(name) | ||
value = kwargs.pop(name) | ||
elif ann is not empty: | ||
yield name, ann | ||
value = ann | ||
elif default is not empty: | ||
yield name, default | ||
value = default | ||
else: | ||
yield not_found | ||
yield (name, value, default) | ||
elif kind == Parameter.VAR_KEYWORD: | ||
# In this case name=kwargs and we yield the items in kwargs with their keys. | ||
for k, v in kwargs.copy().items(): | ||
kwargs.pop(k) | ||
yield k, v | ||
yield k, v, empty | ||
|
||
def _find_abbreviations(f, kwargs): | ||
"""Find the abbreviations for a function and kwargs passed to interact.""" | ||
new_kwargs = [] | ||
for param in signature(f).parameters.values(): | ||
for name, value in _yield_abbreviations_for_parameter(param, kwargs): | ||
if value is None: | ||
for name, value, default in _yield_abbreviations_for_parameter(param, kwargs): | ||
if value is empty: | ||
raise ValueError('cannot find widget or abbreviation for argument: {!r}'.format(name)) | ||
new_kwargs.append((name, value)) | ||
new_kwargs.append((name, value, default)) | ||
return new_kwargs | ||
|
||
def _widgets_from_abbreviations(seq): | ||
"""Given a sequence of (name, abbrev) tuples, return a sequence of Widgets.""" | ||
result = [] | ||
for name, abbrev in seq: | ||
widget = _widget_from_abbrev(abbrev) | ||
for name, abbrev, default in seq: | ||
widget = _widget_from_abbrev(abbrev, default) | ||
widget.description = name | ||
result.append(widget) | ||
return result | ||
|
@@ -187,10 +185,9 @@ def interactive(__interact_f, **kwargs): | |
# Before we proceed, let's make sure that the user has passed a set of args+kwargs | ||
# that will lead to a valid call of the function. This protects against unspecified | ||
# and doubly-specified arguments. | ||
getcallargs(f, **{n:v for n,v in new_kwargs}) | ||
getcallargs(f, **{n:v for n,v,_ in new_kwargs}) | ||
# Now build the widgets from the abbreviations. | ||
kwargs_widgets.extend(_widgets_from_abbreviations(new_kwargs)) | ||
kwargs_widgets.extend(_widgets_from_abbreviations(sorted(kwargs.items(), key = lambda x: x[0]))) | ||
|
||
# This has to be done as an assignment, not using container.children.append, | ||
# so that traitlets notices the update. We skip any objects (such as fixed) that | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why remove the sorting? Is the idea to follow the order of arguments defined in the function itself? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's not removing the sorting, it's removing the line altogether. This line did nothing because kwargs is always empty. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK, great. |
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes... I think it would be good to have an advice here...