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

Remove default values used as expressions in generate.py. #2345

Merged

Conversation

h-mayorquin
Copy link
Collaborator

@h-mayorquin h-mayorquin commented Dec 18, 2023

This should only be missing durations as @JoeZiminski volunteer himself to do that. See:
#2342

@alejoe91
Copy link
Member

Thansk @h-mayorquin

Can you check why tests are failing? It seems related to the change!

@alejoe91 alejoe91 added generators Related to generator tools enhancement New feature or request labels Dec 18, 2023
""" """
assert len(split_ids) > 0, "you need to provide some ids to split"

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@alejoe91
The error was caused by the fact that np.array(0) behaves as False. I should know better to not play with the truthiness of containers.

However, as in this case, you actually ask the split_ids to be non-empty I Just made the argument a required one.

@h-mayorquin h-mayorquin marked this pull request as ready for review December 18, 2023 13:19
@samuelgarcia
Copy link
Member

I am not sure to like this kind of changes.
I do not think we have the cases given by @JoeZiminski which is a inplace modification of the input variable.

@h-mayorquin
Copy link
Collaborator Author

@samuelgarcia
I think that the error is unlikely to show up here but setting expressions as default values is a well known footgun in python and a in consequence a practice. What's the gain of keeping a bad practice? You don't like how it looks?

@JoeZiminski
Copy link
Collaborator

JoeZiminski commented Apr 1, 2024

Hey @h-mayorquin @samuelgarcia sorry for the delay on this! I will open a PR in the second half of next week. I think it is important to remove any mutable default variables due to the unintuitive behaviour of mutable defaults in python.

I had a quick look through and it is true that the function does not do any in-place modification of the default arguments, and would probably not cause an bug in this instance at the present time. Nonetheless I think it is important to remove the pattern here and anywhere else it is found in the codebase for the following reasons:

  1. The most important, in future someone might change the code such that an in-place modification of the variable takes place. This will instantly cause horrible bugs if not caught in code review. So for future proof / maintainability reasons it makes sense to change it now.
  2. It exemplifies an antipattern in the codebase which contributors may see and copy when inappropriate. It signals that this pattern is okay / safe when in fact it is only safe in very specific circumstances. Using the robust pattern turns this into a teachable moment (Q: 'why do you bother assigning None just to change it to dict? 'A: Oh, because of the crazy way python handles mutable default arguments', 'Q: Thanks I did not know about that, I am learning so much working on the SI codebase 😍!'.)
  3. For code-consistency reasons, this pattern will have to be changed in some signatures (where the function makes an inplace modification to the default argument). So we end up with two patterns for mutable defaults across the codebase which is confusing.
  4. I can't think of any tangible benefits of keeping mutable defaults but definitely happy to hear!

@alejoe91
Copy link
Member

alejoe91 commented Apr 4, 2024

Let's go forward with this guys. I think that the majority of us agree that we should follow good practice ;) @h-mayorquin could you solve conflicts?

@h-mayorquin
Copy link
Collaborator Author

Let's try.

@h-mayorquin
Copy link
Collaborator Author

@alejoe91 OK, I fixed them Let's merge because I got conflicts twice already.

@alejoe91 alejoe91 merged commit 49ae822 into SpikeInterface:main Apr 12, 2024
11 checks passed
@samuelgarcia
Copy link
Member

What ??
Did we reach concensus on this ?

Here it is little, I do not care so much but I really do not want to this to be the unique rule for all other the place/
The code would be looks very very ungly.

For instance here:

@h-mayorquin h-mayorquin deleted the remove_wrong_expressions_in_generate branch April 12, 2024 15:11
@JoeZiminski
Copy link
Collaborator

JoeZiminski commented Apr 16, 2024

I agree it is less neat but in this I think it is worth the protection it affords, also the alternative pattern gives opportunity for some extra documentation and isolation of kwargs. For example currently generate_probe_kwargs here elements are currently undocumented but moving these to a function allows them to have their own docstring.

def get_default_generate_probe_kwargs():
    """ docs"""
    return dict(...)

and in the function itself the dict is replaced by None and if generate_probe_kwargs is None: generate_probe_kwargs = get_get_default_generate_probe_kwargs(). It is a typical pattern to see so should not confuse people too much.

I do agree that the existing code is neater than the solution but in this case would advocate the change nonetheless - this really is a very dangerous pattern. Mutable default arguments are a python antipattern and there are many sources warning (a small selection below) against their use:

including this interesting case where the pattern caused failure of a company website launch and 1+ month of heavy bug-fixing!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request generators Related to generator tools
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants