Skip to content

When iterating, make all iteropts except builddependencies lists #4848

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

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from

Conversation

bartoldeman
Copy link
Contributor

Since some easyblocks, e.g. CMakeMake modify self.cfg['configopts'] it's safer to start afresh for every iteration. This PR implements this by turning options like these, if not already lists, into lists with identical element copies, e.g.
[self.cfg['configopts']] * <number_of_iterations>

This modification does not affect the logic of iterative builddependencies itself since it is used in some other places in the code.

Since some easyblocks, e.g. `CMakeMake` modify `self.cfg['configopts']`
it's safer to start afresh for every iteration. This PR implements
this by turning options like these, if not already lists,
into lists with identical element copies, e.g.
`[self.cfg['configopts']] * <number_of_iterations>`

This modification does not affect the logic of iterative `builddependencies`
itself since it is used in some other places in the code.
@bartoldeman bartoldeman marked this pull request as draft April 9, 2025 14:57
@bartoldeman
Copy link
Contributor Author

Framework alternative to easybuilders/easybuild-easyblocks#3693

Still needs a test.

self.iter_opts[opt] = self.cfg[opt] # copy
elif iter_cnt > 1:
# make iter_cnt copies for every opt since easyblocks can modify them
self.iter_opts[opt] = [self.cfg[opt]] * iter_cnt
Copy link
Member

Choose a reason for hiding this comment

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

Although this will help, it's not a perfect solution since for some easyconfig parameters (which have a list or tuple value but are not iterated over), we won't be doing a proper reset...

Can we come up with a more robust way or resetting all easyconfig parameters before we start a new iteration?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it's only a few easyconfig parameters that are affected by this logic:

ITERATE_OPTIONS = ['builddependencies',
                   'preconfigopts', 'configopts', 'prebuildopts', 'buildopts', 'preinstallopts', 'installopts']

which are normally always strings right?

The exception being builddependencies; I will have to special case that one here I think.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I simplified this PR by only touching one file, and it passes the test suite now, so I'll undraft.

It'd be more complicated to add a test that fails without the PR and passes with it. Is that needed @boegel even if the actual behaviour of the function is tested (and yes self.iter_opts now includes all iterable options from ITERATE_OPTIONS including those that stay constant, so it changes how the function affects self).

If the above are a problem one quick fix for 5.0.1 would be to use $EBROOTPYTHON in the easyblock instead of get_software_root("python") in what is passed to cmake.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Adding a test that mimics the buggy behaviour was quite easy in the end. So that addresses the above "more complicated" bit :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

oh I may have misunderstood the all easyconfig parameters, it's more a wish list.

IMHO that would be a much bigger change, not for a bugfix release. You could also argue that a reset is only really needed for all easyconfig parameters that are affected by iteration; there really is no point doing it for checksums and sources, though one could reasonably make things like pretestopts and testopts iterable and saved (they aren't now).

I'd then much rather than go for a way of making most easyconfig parameters read-only, i.e. __setitem__ can complain when an easyblock changes something it shouldn't.

@boegel boegel added the bug fix label Apr 9, 2025
@boegel boegel added this to the release after 5.0.0 milestone Apr 9, 2025
This way each iteration will start from the original copy of
configopts etc, as it's in the iter_opts dict.
This deals with easyconfigs that have lists with just one element
so they will be iterated: `toy.eb` in tests has
`prebuildopts = "echo \"int main() { return 0; }\" > exts-git.c && ",`
the trailing comma makes that a tuple with one element.
@bartoldeman bartoldeman marked this pull request as ready for review April 10, 2025 02:25
# keep track of list, supply first element as first option to handle
for opt in self.cfg.iterate_options:
for opt in ITERATE_OPTIONS:
self.iter_opts[opt] = self.cfg[opt] # copy
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we do a deepcopy here just to be safe? IIRC it doesn't change anything for strings but if we were to use e.g. lists now or in the future it would still work.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

once upon a time, it was a deeper copy, then commit 56e2fc4 changed it from

-                self.iter_opts[opt + suffix] = self.cfg[opt][::-1]  # reversed copy
+                self.iter_opts[opt + suffix] = self.cfg[opt]  # copy

which changed the by-reference semantics. I doubt @boegel remembers though since that change is 12 years old :)

In general, and that applies to the below comment too, for a bugfix release I'd favour the absolute minimal change that fixes the bug, any other nice-to-have should wait.

@Flamefire
Copy link
Contributor

Looks good to me, I expect this works. Instead of using ITERATE_OPTIONS we could use another constant which for now has the same values but could be extended if the need arises. It should basically contain all relevant keys we want to save/restore.

We could also use ec.asdict() and ec.set_keys instead to save all values but a) the latter is very verbose, so better add a "quiet" param and b) e.g.the "parallel" property would need to be updated too. That could be added to set_keys though: Set properties if they were set according to new keys. But then: Do we want that? I don't see an issue though, we could just reset or ignore the properties as they can't be set pre-iteration so easyblocks should not expect that they are and set them in prepare_step or similar.
But maybe that is too much anticipation of cases not coming up ever.

Apply this patch directly to the code without easybuilders#4848 makes it fail
with
AssertionError: 'FOO=bar ' != ''
- FOO=bar
+
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants