Skip to content
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

Merged
merged 14 commits into from
Jun 26, 2023

Conversation

mwcraig
Copy link
Member

@mwcraig mwcraig commented May 17, 2023

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:

@mwcraig mwcraig added the enhancement New feature or request label May 17, 2023
@mwcraig mwcraig requested review from pllim and eteq May 17, 2023 20:30
@mwcraig
Copy link
Member Author

mwcraig commented May 17, 2023

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

@pllim
Copy link
Member

pllim commented May 17, 2023

Thanks! I'll put this on my queue to review.


# Methods for loading data
@abstractmethod
def load_fits(self, file):
Copy link
Member

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.

https://docs.google.com/document/d/1sBImbw1p4mM3VYWGQJDRbj2N3uqP5Ed_Wfb8BDjJj2o/edit#heading=h.8ah2ugluz5xr

Copy link
Member Author

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.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I opened #163

Copy link
Member

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.

https://docs.google.com/document/d/1sBImbw1p4mM3VYWGQJDRbj2N3uqP5Ed_Wfb8BDjJj2o/edit#heading=h.8ah2ugluz5xr

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I opened #164 and #165

Copy link
Member

@pllim pllim left a 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"?

Comment on lines +20 to +21
# to make sure Protocol knows they are attributes. Python does not
# do any checking at all of these types.
Copy link
Member

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?

Copy link
Member

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?

Copy link
Member Author

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.

Copy link
Member

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.

Copy link
Member Author

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.

Copy link
Member

@eteq eteq left a 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 .

  1. 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.
  2. 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.

Comment on lines 52 to 56
# 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', )
Copy link
Member

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?

Copy link
Member Author

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.

Comment on lines +20 to +21
# to make sure Protocol knows they are attributes. Python does not
# do any checking at all of these types.
Copy link
Member

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?

Copy link
Member

@pllim pllim left a 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.

@mwcraig
Copy link
Member Author

mwcraig commented Jun 19, 2023

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.

May as well give it a go at a stage when the whole thing is typing. Pretty sure that isinstance won't catch that since it is a runtime check but should allow mypy checking.

@mwcraig
Copy link
Member Author

mwcraig commented Jun 19, 2023

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.

Going to implement that in this PR because I know from experience I will never come back to it...

mwcraig added 4 commits June 19, 2023 13:27
It seems like these should not, by default, be modifiable by the user.
These are present in the ginga implementation but were omitted here.
Comment on lines +20 to +21
# to make sure Protocol knows they are attributes. Python does not
# do any checking at all of these types.
Copy link
Member Author

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
Copy link
Member Author

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

@mwcraig
Copy link
Member Author

mwcraig commented Jun 26, 2023

Merging, thanks!

@mwcraig mwcraig merged commit 210d772 into astropy:main Jun 26, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
API Issues that relate to the API itself rather than implementations enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants