Repository navigation
Conversation
|
Hello @nstarman 👋! It looks like you've made some changes in your pull request, so I've checked the code again for style.
Comment last updated at 2022-06-25 20:55:56 UTC |
|
👋 Thank you for your draft pull request! Do you know that you can use |
mhvk
left a comment
There was a problem hiding this comment.
This looks really nice! I was a bit doubtful at first when I saw the approach with the metaclass, but it is clear it makes a lot of sense, with __init__ and __call__ both very logically used.
I have not had a chance yet to see what goes wrong...
8a4a1b4 to
683fa13
Compare
|
Solved! |
683fa13 to
9a0b438
Compare
|
@adrn, this might be used to solve JAX/Dask/etc + units.
|
a04da84 to
ebd08a5
Compare
|
The RTD error is real, but all I've done is import |
|
@pllim I don't think putting the wrapper meta class in |
I guess it doesn't hurt... |
|
What about |
|
I think |
|
I called the new file |
4f8e40b to
63a28de
Compare
Signed-off-by: Nathaniel Starkman (@nstarman) <[email protected]>
Signed-off-by: Nathaniel Starkman (@nstarman) <[email protected]>
Signed-off-by: Nathaniel Starkman (@nstarman) <[email protected]>
Signed-off-by: Nathaniel Starkman (@nstarman) <[email protected]>
Signed-off-by: Nathaniel Starkman (@nstarman) <[email protected]>
Signed-off-by: Nathaniel Starkman (@nstarman) <[email protected]>
Signed-off-by: Nathaniel Starkman (@nstarman) <[email protected]>
Signed-off-by: Nathaniel Starkman (@nstarman) <[email protected]>
1f8c895 to
be3f9e6
Compare
mhvk
left a comment
There was a problem hiding this comment.
This is looking very nice! It seems clear to me that having subclasses of FactoryMeta is the right solution.
With that, one now can get to bikeshedding about names... My general sense would be that the metaclass names do not have to have the _inmix prefix, and in principle could even be public.
One a bit larger thing is that I worry at times a little too much moved to the metaclasses. I also have a sense some things could be simpler (the weak dicts being a particular example). But I really need a bit more time to look through this properly! As I'm off tomorrow, I'm not quite sure when I'll have time, but I'll try! So, I'll send the comments I have so far (somewhat random, I fear).
|
|
||
| def __init_subclass__(cls, base_cls=None, data_cls=None, **kwargs): | ||
| """Register a Masked subclass. | ||
| def from_unmasked( |
There was a problem hiding this comment.
I feel this should remain as a class method on Masked proper - after all, it was a public method, and currently it can be used from a masked instance.
There was a problem hiding this comment.
It's reasonable to not want to change the API. I'll move it back.
| mask = getattr(self.mask, method)(*args, **kwargs) | ||
|
|
||
| result = self.from_unmasked(data, mask, copy=False) | ||
| result = type(self).from_unmasked(data, mask, copy=False) |
There was a problem hiding this comment.
Keeping from_unmasked as a class method, this change would not be necessary.
| class FactoryMeta(ABCMeta): | ||
| """Meta-class for generating classes of a data class. | ||
|
|
||
| Classes derived from this metaclass. |
| name: str, | ||
| bases: tuple[type, ...], | ||
| namespace: dict[str, Any], | ||
| base_cls: type | None=None, |
There was a problem hiding this comment.
Maybe add a * so base_cls and data_cls are keyword only (works by default, of course, but maybe clearer?)
|
|
||
| # inject data_cls into namespace before `__new__` so | ||
| # `__init_subclass__` can use it. | ||
| namespace["__intomixclass__"] = data_cls |
There was a problem hiding this comment.
Doesn't __init_subclass__ get whatever is passed in to the class anyway?
| """Astropy's ABCs.""" | ||
|
|
||
| from __future__ import annotations | ||
| from ast import Raise |
There was a problem hiding this comment.
Opening this file in emacs showed wiggly red lines: Raise is not used.
There was a problem hiding this comment.
Ah. yes. One of the less desirable side effects of VSCode auto-imports. I must have typed a Raise with capital and it tried to help. I try to pair VSCode with flake's detect-unused-imports in pre-commit to catch these. But we don't have that enabled... 🤔
| import sys | ||
| import weakref | ||
| from abc import ABCMeta | ||
| from typing import Sequence, Dict, Any, Tuple, TypeVar, Union |
| namespace: dict[str, Any], | ||
| base_cls: type | None=None, | ||
| data_cls: type | None=None, | ||
| **_: Any |
There was a problem hiding this comment.
Why not **kwargs and actually pass them on? In case someone inherits and puts something in between.
| self.__inmixbase__ = self | ||
| """Base class for generating new intermixed classes.""" | ||
|
|
||
| self.__inmixed_base_classes = weakref.WeakKeyDictionary() |
There was a problem hiding this comment.
Using WeakKeyDictionary here seems to add a lot of complication for what seems very little gain: generally, if, say, a Masked subclass is created, it will happen again soon enough. Similarly for SkyOffsetFrame and Distribution. Plus, these dictionaries cannot get very big. I'd suggest to just use dict
|
|
||
| For subclasses of these unmasked classes, masked counterparts can be generated. | ||
| """ | ||
| masked_cls = self._inmix_get_subclass(data.__class__) |
There was a problem hiding this comment.
Just
return super()._inmix_make_instance(data, mask, copy=copy)
Alternatively, keep it as a class method _get_masked_instance, which can call this directly. Or, perhaps even better, in that case just call cls(data, mask, copy=copy), which I think will do the right thing.
|
Hi humans 👋 - this pull request hasn't had any new commits for approximately 4 months. I plan to close this in 30 days if the pull request doesn't have any new commits by then. In lieu of a stalled pull request, please consider closing this and open an issue instead if a reminder is needed to revisit in the future. Maintainers may also choose to add keep-open label to keep this PR open but it is discouraged unless absolutely necessary. If this PR still needs to be reviewed, as an author, you can rebase it to reset the clock. If you believe I commented on this pull request incorrectly, please report this here. |
|
I'm going to close this pull request as per my previous message. If you think what is being added/fixed here is still important, please remember to open an issue to keep track of it. Thanks! If this is the first time I am commenting on this issue, or if you believe I closed this issue incorrectly, please report this here. |
|
@nstarman - working on |
|
I am interested in doing that. One major drawback I found is that we are missing an underlying piece of the mechanics: a resolution order of the class generation. Let's say we make class InterpolatedCoordinate that adds an affine parameter to a Coordinate so that it describes a path. Then |
|
Yes, indeed, it is all a bit tricky. For p.s. It may also be that |
|
Not that this isn't useful, I just think a more studied approach is needed. |
The class generator is factored out of Masked and Distribution as a meta class.
Fixes #12912
todo:
There's some residual weirdness with
__init_subclass__and a metaclasses that I haven't solved. Solutions / input appreciated.Checklist for package maintainer(s)
This checklist is meant to remind the package maintainer(s) who will review this pull request of some common things to look for. This list is not exhaustive.
Extra CIlabel.no-changelog-entry-neededlabel. If this is a manual backport, use theskip-changelog-checkslabel unless special changelog handling is necessary.astropy-botcheck might be missing; do not let the green checkmark fool you.backport-X.Y.xlabel(s) before merge.