-
-
Notifications
You must be signed in to change notification settings - Fork 15
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
Move interface definition from base class to protocol #162
Conversation
This also contains the minimal ginga implementation, in part to illustrate how tests would be set up in other implements. See the ginga-specific test code |
Thanks! I'll put this on my queue to review. |
|
||
# Methods for loading data | ||
@abstractmethod | ||
def load_fits(self, file): |
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 know you say API change is out of scope, but I want to note that we agreed at Astropy Coordination Meeting 2023 to change load_*
methods to just load
so Astrowidgets does not dictate what file format each backend choose to support.
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.
Thanks -- I added this to the agenda in the running notes.
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 opened #163
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 know you say API change is out of scope, but I want to note that we agreed at Astropy Coordination Meeting 2023 to move backend specific implementations (ginga, bqplot, Firefly, etc) out of astrowidgets
repo.
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 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.
Looking at Astropy Coordination Meeting 2023 notes, there is a note that says @eteq was going to "split that out into two classes on the train" but I forgot what that was about. Do you remember? Could it be the "DataLoader protocol"?
# to make sure Protocol knows they are attributes. Python does not | ||
# do any checking at all of these types. |
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.
We could enforce it with third-party type checker package but is that going too far?
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.
Hmm, although it's a bit odd, when I think about it I like the cleanness of the interface not doing any checking but the APITest class doing it. So maybe if we implemented type-checking it could use this information but actually do the type checking when the APITest is invoked by a backend?
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 should clarify -- I think mypy
checking can be done, but Python never enforces type checking at runtime. If we wanted to, or maybe better, if we want an implementation to enforce run-time checking we could use pydantic
to make that happen.
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.
Not sure if we want to enforce run-time checking. Might be too controversial.
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.
Agreed -- and the way we have set things up I don't think we can.
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 like where this is going! I left an inline comment and I have two more general comments below. But I'm approving because all of them might be "lets leave that to a later PR" if you want, @mwcraig .
- Right now the API methods don't provide any context about what they are supposed to do. I'm thinking the interface is now the best place to provide that. For example,
load_fits
might get a docstring that says something like "The UI behavior expected is that the specified FITS file appear in the UI window in addition to being loaded into the application." Even though we can't guarantee that from an automated testing point of view, we can at least say in the docstring what the API is supposed to do from a UI perspective, to make it easier for a user to report variances from a backend to the expected behavior. - Maybe we should use type hinting in the methods to also show what each of the methods return? I don't think we need to go full-on with the type-hinting, but as simply a documentation mechanism of the expected return type it might be useful.
astrowidgets/ginga.py
Outdated
# Allowed locations for cursor display | ||
ALLOWED_CURSOR_LOCATIONS = ('top', 'bottom', None) | ||
|
||
# List of marker names that are for internal use only | ||
RESERVED_MARKER_SET_NAMES = ('all', ) |
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 these be imported from interface_definition
instead of defined here? Or are they meant to be disitnct for some reason I'm missing?
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.
Yeah, they should only be in one place. It feels a little inelegant to do it as constants. Will update.
# to make sure Protocol knows they are attributes. Python does not | ||
# do any checking at all of these types. |
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.
Hmm, although it's a bit odd, when I think about it I like the cleanness of the interface not doing any checking but the APITest class doing it. So maybe if we implemented type-checking it could use this information but actually do the type checking when the APITest is invoked by a backend?
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.
In principle, I think Protocol is a great idea and we should push this forward. Let's get this in. Thanks!
Matt, in case if you want to address Erik comments, I won't merge now. Feel free to merge when you think it is ready.
May as well give it a go at a stage when the whole thing is typing. Pretty sure that |
Going to implement that in this PR because I know from experience I will never come back to it... |
It seems like these should not, by default, be modifiable by the user.
These are present in the ginga implementation but were omitted here.
# to make sure Protocol knows they are attributes. Python does not | ||
# do any checking at all of these types. |
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.
Agreed -- and the way we have set things up I don't think we can.
stretch_options: tuple | ||
autocut_options: tuple | ||
cursor: str | ||
marker: Any |
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.
These were omitted the first time through:
zoom_level: float
is_marking: bool
stretch_options: tuple
autocut_options: tuple
cursor: str
Merging, thanks! |
This PR contains the minimal pieces from #142 to change the bottom layer from an abstract base class to a protocol.
There are some API changes in #142 that are not included in this PR so that we can discuss those separately.
EDIT: