-
Notifications
You must be signed in to change notification settings - Fork 156
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
alignedmapping repr & delete methods for anndata attrs #242
Conversation
Hmm, you know the plan is to unify |
I know that's something you're looking at doing, but I don't think I have an idea of what exactly that means from an API stand-point. My inclination would be not to do that yet. Any idea what's up with that black error on travis? I don't get that locally. |
The idea is that mostly people want to include X when iterating over layers, rarely not, and in any case: for key, val in ad.layers.items():
if key is None: continue
...
# or
for key, val in {k, v in ad.layers.items() if k is not None}:
... is easier to get right and come up with than: for key, val in ChainMap({None: ad.X}, ad.layers).items():
...
# or
for key, val in chain([(None, ad.X)], ad.layers.items()):
... It’s relevant for this PR as everything cementing “X isn’t a real layer” makes migration to the new way harder.
It’s psf/black#1139, circumvented on anndata master. |
Issue with
|
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 great! I think we can increase maintainability a bit:
anndata/core/anndata.py
Outdated
if self.isview: | ||
self._init_as_actual(self.copy()) |
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 see those lines repeated a lot. How about a decorator actualizes_view
or so?
@layers.deleter
@actualizes_view
def layers(self):
self._layers = Layers(self, vals=dict())
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 about that while I wrote this. I would prefer a private method, not a decorator, so you can validate the input before calling _init_as_actual
. Many of the setter
have examples of this.
The only other thing is that it might be better to modify the copy, then call _init_as_actual
– just to make sure all possible checks occurred before modifying the object. This is harder to put in a method.
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.
Thoughts on this?
If it were to be a method, how about this being the no-argument version of self._init_as_actual()
? The only thing I'm worried about there is whether's it's obvious that it would be a no-op if the object isn't a 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.
That would make sense! Just make _init_as_actual
work without arguments and make it do nothing if self
is actualized. Then it would be
self._init_as_actual()
instead of
if self.isview:
self._init_as_actual(self.copy())
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 do feel bad every time I make the _init_as_*
methods more complicated. Someday they'll be refactored. Someday...
d230667
to
ba69649
Compare
OK, so I rebased this using git rebase master
# collapse “Simplify deleters” into “Add deleter methods …”
git rebase -i $first_hash
# Make sure every commit is formatted
git filter-branch --tree-filter 'black .' -- $first_hash..HEAD The last step got rid of the “Formatting” commit. I think a procedure like this is simple enough to do so we can avoid a messy commit hierarchy. |
Previously, the aligned mapping repr would throw an error if called since it starting a recursion loop. This has been fixed and tested. To make sure reprs worked, I added some tests, but found out it'd be easier to do this if I could remove attributes. This led me to implement deleter methods for the main attributes (except
raw
).Now you can do: