-
Notifications
You must be signed in to change notification settings - Fork 99
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
Deal with __getstate__ methods #633
Conversation
…ait on the class)
@@ -49,13 +49,6 @@ def map_data_array(self, screen_vals): | |||
# ------------------------------------------------------------------------ | |||
# Persistence-related methods | |||
# ------------------------------------------------------------------------ | |||
def __getstate__(self): | |||
state = super(AbstractMapper, self).__getstate__() | |||
for key in ["_cache_valid"]: |
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.
_cache_valid
is not a trait on this class or any of its base classes
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.
sigh. but it is a trait on the subclasses e.g. Base1DMapper
so those need to be updated
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.
Ah you are right. TBH I believe that all related traits should be transient even if they weren't perviously involved in a __getstate__
method. For example other classes have _screen_cache_valid
or _selection_cache_valid
traits. I think I will update all of these (to be specific I am going to update any privately named cache trait) to be transient as I can't see why they shouldn't all be so
It also doesn't make sense that for some objects the _cache_valid
and similar traits would be transient traits but on others not
|
||
# ------------------------------------------------------------------------- | ||
# Appearance properties (for Box mode) | ||
# ------------------------------------------------------------------------- | ||
|
||
# The pointer to use when drawing a zoom box. | ||
pointer = "magnifier" | ||
pointer = Str("magnifier", transient=True) |
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 may be bad if pointer
is meant to be a class attribute, similar to stack_index
in plot_container.py
.
I need to climb up the class hierarchy to see if it was previously defined as a trait. I remember Kit mentioning this being a point of confusion. I am not sure what the ideal way to avoid this confusion would be (aside from maybe a comment above saying if this is a class attribute or just setting a trait to a value. I guess if setting a trait to some value, you could do as I have done here? and explicitly do something like Str(___)
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.
As a quick sanity check, on master I defined a class attribute thing = "A"
on SimpleZoom
. I then ran:
from chaco.tools.simple_zoom import SimpleZoom
SimpleZoom.thing # I see 'A' printed
SimpleZoom.pointer # I get an error "type object 'SimpleZoom' has no attribute 'pointer'"
So, I believe the change made here is the right one
@@ -247,7 +254,7 @@ def test_serialization_state_no_persist(self): | |||
"_min_index", | |||
"_max_index", | |||
]: | |||
self.assertIn(key, state) | |||
self.assertNotIn(key, state) |
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.
If not persisting they should not be in state, but if we are they should be. I believe these tests are doing what they are supposed to now
if key in state: | ||
del state[key] | ||
if "stack_index" in state: | ||
del state["stack_index"] |
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.
stack_index is a class attribute not a trait, so I believe this is still needed
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
@@ -49,13 +49,6 @@ def map_data_array(self, screen_vals): | |||
# ------------------------------------------------------------------------ | |||
# Persistence-related methods | |||
# ------------------------------------------------------------------------ | |||
def __getstate__(self): | |||
state = super(AbstractMapper, self).__getstate__() | |||
for key in ["_cache_valid"]: |
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.
sigh. but it is a trait on the subclasses e.g. Base1DMapper
so those need to be updated
@@ -449,14 +449,6 @@ def _line_width_changed(self): | |||
self.invalidate_draw() | |||
self.request_redraw() | |||
|
|||
def __getstate__(self): | |||
state = super(LinePlot, self).__getstate__() | |||
for key in ["traits_view"]: |
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.
Is traits_view
a transient trait? I dont see anything in the code or in the documentation saying that it is.
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 going off wha Corran said in this issue description: "This is removing the traits_view trait from the state - under normal Traits, this will never be in the state because of special handling of Views, so this whole method can be removed."
This should certainly be documented though
"reset_zoom_key", | ||
"prev_zoom_key", | ||
"next_zoom_key", |
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.
im not sure where these traits were being magically defined
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.
me either, this is the only place I was seeing them in the codebase. Perhaps they once existed but had been removed
Looks like the CI failure on windows/pyqt from the test introduced by #636 is reproducible on every PR except the original (no idea how it didn't fail on 636).
I also find the error quite confusing, as looking in enable, the |
|
||
# Is the cached color data valid? | ||
_colors_cache_valid = Bool(False) | ||
_colors_cache_valid = Bool(False, transient=True) |
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.
If the cache valid flags arent transient, then the caches themselves should also be transient - _levels
and _colors
.
I would think HasTraits
would ignore traits that are private i.e. that start an _
. If that isn't the case, there are a lot more private traits that we will want to mark as transient.
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.
As you suggested, I printed state
inside the ArrayDataSource.__getstate__
method on master and ran the test suite. I do see _
prefixed traits, eg _data
, '_min_index', etc. So it looks like these need to be addressed
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.
If that isn't the case, there are a lot more private traits that we will want to mark as transient.
Does this mean all private traits be transient?
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.
As you suggested, I printed state inside the ArrayDataSource.getstate method on master and ran the test suite. I do see _ prefixed traits, eg _data, '_min_index', etc. So it looks like these need to be addressed
Sigh. I was afraid of that.
Does this mean all private traits be transient?
Let's not do that. Definitely not in 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.
So, I imagine the code will recreate the cache if a *cache*
is False
, which it is by default because we're marking it as a transient. So, I think we can ignore all of the traits that are recalculated based on the *cache*
flag. - i.e. nothing actionable in this PR.
# Cached list of line widths | ||
_widths = List |
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.
looks like this is technically a cache but like I said earlier, this will be ignored/recomputed because the _widths_cache_valid
trait is False
- no action required, just pointing it out.
chaco/tools/simple_zoom.py
Outdated
# Is the tool always "on"? If True, left-clicking always initiates | ||
# a zoom operation; if False, the user must press a key to enter zoom mode. |
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.
looks like you lost the #:
because of the merge conflicts.
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
closes #583, #248
This PR rermoves uses of the
__getstate__
method when it is not needed, and cleans up its use where it is.The
__setstate__
methods can be dealt with in a follow up PR