-
Notifications
You must be signed in to change notification settings - Fork 2
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
Massive overhaul of core functionality #113
Conversation
Sorry to rain on your asteroid mining parade 😄 |
The error is raised by |
@@ -1,6 +1,6 @@ | |||
[metadata] | |||
name = pymetis | |||
version = @PACKAGE_VERSION@ | |||
version = 0.0.1 |
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.
The ESO build system might expect @PACKAGE_VERSION@
here. I suppose everything would still work with a specific version though.
I think the idea is to have only one place where the version number is defined, which canonically is
METIS_Pipeline/metisp/configure.ac
Line 3 in d31dfd2
AC_INIT([METIS Instrument Pipeline], [0.0.1], [https://support.eso.org], |
Maybe it is easier for our development if we (also) define the version explicitly here, but it should be a conscious decision that means that we then have an extra location to update the version number.
I'm impartial in what we decide, so I'm not for or against this change; I'm just noting we should be aware of what it means.
(I personally think that the 'current version' should be derived from the git tag/branch/hash, like astropy, but I don't actually suggest doing that now.)
return re.sub(r"\?P<\w+>", "", cls.tags().pattern) |
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.
Two return statements in a row seems like a mistake.
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.
Forgot about this from some late night debugging session. Right now I'd prefer the unmodified version, since it explicitly shows what the name of the parameter is -- and how it is propagated to outputs.
class FluxstdCatalogInput(SinglePipelineInput): | ||
_title: str = "flux standard star catalogue table" |
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.
Just a note that we made a distinction between "tables" and "catalogs". A 'catalog' is a list of sources (e.g. stars) with their attributes, it is encoded as a FITS table extension. A 'table' contains something else, e.g. a list of offsets for each detector, and we have not decided how it should be encoded. For example, a table with just four numbers can perhaps be better encoded as four FITS headers, because that makes it queryable through the archive. The term "catalog[ue] table" is never used in the DRLD in order to prevent confusion.
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.
My bad. This was probably autogenerated by some PyCharm AI voodoo and I failed to notice.
Co-authored-by: Hugo Buddelmeijer <[email protected]>
cut_input = re.compile(r'Input$') | ||
|
||
# Now iterate over all refined Inputs, instantiate them and feed them the frameset to filter. | ||
for (name, input_type) in inspect.getmembers(self.__class__, |
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.
Usually, when I want to use inspect
, I'm doing something wrong. So this line triggers me, and there is not enough information here to take away my fear that we are doing something wrong here too. Maybe it is fine though.
Perhaps you can iterate over self.__class__.__dict__.items()
instead? But maybe that won't work for some reason? It would still be a bit hacky, but somewhat less, IMHO.
I think inspect
is also pretty heavy, and maybe implementation dependent (not sure)?
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 am not sure. There are many possible approaches, this felt cleanest to me. Also we can go fully explicit.
What I both like and dislike the most is that it happens fully automatically. It can lead to disgusting bugs (like failing to match the name of the overridden class, which results in extra inputs (but that can be caught by looking at the man page)). Also code collocation is horrendous -- all the magic happens way too high in the hierarchy.
for (name, input_type) in inspect.getmembers(self.__class__, | ||
lambda x: inspect.isclass(x) and issubclass(x, PipelineInput)): | ||
inp = input_type(frameset) | ||
# FixMe: very hacky for now: determine the name of the instance from the name of the class |
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.
Just run with it! I can understand it, I think:
(?<!^)(?=[A-Z])
means: look-back to determine we are not at the start, and then look-here/ahead but don't consume (?) and this is a capital. If so, insert an underscore. Before all that, remove "Input", and afterwards make lowercase. So this is debugable.
|
||
# Use this regex to verify that the product tag is correct. | ||
# This base version only verifies it is ALL_CAPS_WITH_UNDERSCORES | ||
_regex_tag: re.Pattern = re.compile(r"^[A-Z0-9]+[A-Z0-9_]+[A-Z0-9]+$") |
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 a tag starting with a number going to work? I can imagine it leading to problems, not sure.
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 guess it is (at least I don't see a reason why it should not work). But it might be better to just forbid that.
@@ -181,3 +183,21 @@ def _create_dummy_image() -> cpl.core.Image: | |||
@property | |||
def valid_frames(self) -> cpl.ui.FrameSet: | |||
return self.inputset.valid_frames | |||
|
|||
def _dispatch_child_class(self) -> type["MetisRecipeImpl"]: |
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.
Supersweet!
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 good!
Perhaps we should update the cached files? Or maybe wait till pyesorex 1.0.2 is released (which should be next week) |
No need to hurry now. I would like to fix the tests first anyway. |
OK, I can reproduce the same test failures with my local machine on |
Updating pyesorex version requirement to 1.0.2b0 in the feature branch
Sorry for the branch name, it got out of hand pretty quickly.
I tried to reimplement the loading part of the class hierarchy, so that it does not have to instantiate the
RecipeImpl
twice. As usual, the rabbithole went on and on... and we can now:pyesorex --man-page <recipe>
from the attributes of theRecipe
, and without a valid frameset. No more writing and formatting thedescription
yourself!as_dict
to compare with the DRLD, including OCA keywords, algorithm (my long-term goal is to to recreate all DRLD boxes from the code, even if we don't actually do it, it's good to be able to)inputs |= {...}
, as this is now done fully automatically withinspect
(everyPipelineInput
in theInputSet
gets instantiated and filled with data)Some downsides:
pyesorex
errors are more cryptic / nonexistent, because it catches many exceptions, so if you screw up, suddenly your recipe does not exist anymore (requires some minor tweaks to your workingpyesorex
, no problem if you ˙pip install -e` it)Input
s /Product
s are in fact the same (no shit Sherlock) and also keywords could probably be objects and not just strings, so I have to fix this tooRequires fixes to
pyesorex
(terminal size thing and better comparing forNone
) so it will not pass the tests right now.