-
Notifications
You must be signed in to change notification settings - Fork 96
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
Add RangeEditor support for format_func #1684
Conversation
…should be using format not format_str in this casee
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.
This approach works but I would like to see the alternative approach before choosing one over the other.
IMO, in the long term, it would be better if we deprecated and remove RangeEditor.format
and just use EditorFactory.format_str
. The right way to do that at the moment would be to make RangeEditor.format
a property that sets RangeEditor.format_str
while raising a deprecation warning.
traitsui/editors/range_editor.py
Outdated
method uses that string for formatting. If neither attribute is | ||
set, then this method just calls the appropriate text type to format. |
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.
There is no mention of the format_func
kwarg to the method in the docstring here.
Tangentially, the priority here seems a little wonky to me - shouldn't format_func
passed to the method take priority over the format_func
/format
set on the factory? I think it should because format_func
is being explicitly passed when calling string_value
- and format_func
/format
might have been set on the factory at any earlier point after instantiation.
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.
I agree, this is quite strange and unexpected behavior...
I will open an issue pointing to the origin of this method (i.e. EditorFactory.string_value
)
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.
I've opened #1695
traitsui/qt4/range_editor.py
Outdated
@@ -80,7 +80,7 @@ class SimpleSliderEditor(BaseRangeEditor): | |||
#: High value for the slider range | |||
high = Any() | |||
|
|||
#: Formatting string used to format value and labels | |||
#: Deprecated: This trait is no longer used. |
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.
I was thinking this should become a property that mirrors the editors factory_str
but I don't think that is needed / allowed? (ie an instance of an editor can't set its factory's trait). We ultimately had previously just set self.format = factory.format
in the init
method anyways.
I am worried there may be a change in behavior if a user was to try to set format
on an instance of a RangeEditor
. e.g my_editor = RangeEditor()
, my_editor.format = "something"
. Previously, because we had been using self.format
throughout instead of string_value
, so this would actually be used. Now, AFAICT, the best we can do is pass it as a kwarg to string_value
if a user tries to set it on an instance, but that will no longer take priority if the factory has its trait set...
I don't think we want to change any behavior here (even if the current behavior is strange). I am unsure how to best move forward.
@rahulporuri any thoughts on this? I hope my explanation made some sense, if not we can discuss tomorrow at standup
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.
So initially I expected this Test to pass on master, but fail on this branch:
def test_format_behavior_change(self):
# format trait has been deprecated in favor of format_str. However,
# behavior should be unchanged.
model = RangeModel()
with self.assertWarns(DeprecationWarning):
my_editor = RangeEditor(format="%s ...")
my_editor.format = "%s"
view = View(
Item(
"float_value",
editor=my_editor
)
)
tester = UITester()
with tester.create_ui(model, dict(view=view)) as ui:
float_value_field = tester.find_by_name(ui, "float_value")
float_value_text = float_value_field.locate(Textbox())
self.assertEqual(
float_value_text.inspect(DisplayedText()), "0.1"
)
but it passes on both. I then realized my_editor
is always just an instance of the traitsui.editors.RangeEditor
EditorFactory
. The actual Editor
instances are only created when e.g. the _get_simple_editor_class
method is called. If I access the Editor
directly, e.g. doing something like this:
def test_format_behavior_change(self):
# format trait has been deprecated in favor of format_str. However,
# behavior should be unchanged.
model = RangeModel()
view = View(
Item(
"float_value",
editor=RangeEditor(format="%s ...")
)
)
tester = UITester()
with tester.create_ui(model, dict(view=view)) as ui:
float_value_field = tester.find_by_name(ui, "float_value")
float_value_field._target.format = "%s"
float_value_text = float_value_field.locate(Textbox())
self.assertEqual(
float_value_text.inspect(DisplayedText()), "0.1"
)
I expected it to pass on master and fail on this branch. However, this fails on both...
So, AFAICT, behavior is not changed by this PR.
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.
EDIT: see the recently added test
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.
Can you search for users of the format
trait on this editor? I'm not even sure how one would go about specifically searching for such uses. Whether or not users exist would help us decide on whether or not we need to convert format
into a property as well - and make getting/setting format
raise warnings as well.
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.
I was unable to find any users trying to set format on the Editor instance directly.
I did see users setting it on the Factory object, ie RangeEditor(format= ...)
, but that is covered by the use of property/deprecation in traitsui/editors/range_editor.py
.
TBH I am not certain what the pattern would be to set it on the Editor instance. I guess accessing it through UIInfo
?
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.
From traitsUI docs: "Note that not every trait on every editor can react to changes: some values are only used at editor creation time; however all editors support dynamically changing the enabled, visible and invalid traits. This feature can sometimes allow developers to avoid having to create a custom Handler subclass."
traitsui/wx/range_editor.py
Outdated
@@ -74,7 +74,7 @@ class SimpleSliderEditor(BaseRangeEditor): | |||
#: High value for the slider range | |||
high = Any() | |||
|
|||
#: Formatting string used to format value and labels | |||
#: Deprecated: This trait is no longer used. |
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.
Rather than simply commenting on the deprecation, I would like to make this a property which raises a deprecation warning.
Ideally, getting the property would return the self.factory.format_str
trait, and like wise setting it would set that trait. However it feels incorrect for an editor instance to be trying to change a trait on its factory...
Also as I think more about this PR, I am worried about Hyrum's law here. Even if the behavior change seems "more" correct, it is possible that users are dependent on the current behavior.
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.
LGTM with a couple of comments.
Can you update the PR description as well? I think it is outdated as we modified the approach after the first review.
traitsui/qt4/range_editor.py
Outdated
@@ -80,7 +80,7 @@ class SimpleSliderEditor(BaseRangeEditor): | |||
#: High value for the slider range | |||
high = Any() | |||
|
|||
#: Formatting string used to format value and labels | |||
#: Deprecated: This trait is no longer used. |
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.
Can you search for users of the format
trait on this editor? I'm not even sure how one would go about specifically searching for such uses. Whether or not users exist would help us decide on whether or not we need to convert format
into a property as well - and make getting/setting format
raise warnings as well.
Co-authored-by: Poruri Sai Rahul <[email protected]>
I've updated the news fragment, although it is still a "bugfix". It really sort of belongs in "deprecation" as well... Should I include it in both (ie add another news fragment with the same message just tagged as deprecation perhaps? |
CI is failing on ubuntu-latest with pyside2:
I have a suspicion that these failures occur when we have CI running for multiple PRs at the same time. This is really a hunch, but with some quick googling I have seen some discussions about |
This comment has been minimized.
This comment has been minimized.
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.
still LGTM
@aaronayres35 can you update the PR description because it feels outdated |
closes #1650
This PR adds support for
format_func
for theRangeEditor
. It does so by calling thestring_value
method defined on the factory, rather than justself.format % _____
. See method definition here:traitsui/traitsui/editor_factory.py
Lines 190 to 208 in e2521b4
I am just realizing while opening this that although the base
EditorFactory
class defines aformat_str
trait, theRangeEditor
defines its ownformat
trait to hold the format string instead.I suspect this will cause problems, hence the WIP for now. I would like to renameformat
toformat_str
but that is part of the public api...Perhaps I will need to redefine thestring_value
method onRangeEditor
and have it be exactly the same as the base class just replacingformat_str
withformat
... 🤔~EDIT: I went with the approach mentioned of "redefine the
string_value
method onRangeEditor
...". It smells a bit, but seems necessary (?) I am not sure why RangeEditor chose to use its own trait there previously rather than usingformat_str
. ~This PR also went on to deprecate the
format
trait on theRangeEditor
EditorFactory
and also on the toolkit specificEditor
implementations. Users should transition to usingformat_str
andformat_func
on the editor factory. Theformat
trait will be removed in traitsui 8.0 (see #1704)Checklist