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

Add ChoiceParameter to restrict parameter options to those specified. #1800

Merged
merged 11 commits into from
Aug 9, 2016

Conversation

brcopeland
Copy link
Contributor

Description

As in description.

Motivation and Context

This allows the user to define the permissible values for a parameter and the value type, and reject any parameter that does not meet these criteria.

Have you tested this? If so, how?

I've been using the class for several weeks without issue.

@mention-bot
Copy link

@brcopeland, thanks for your PR! By analyzing the annotation information on this pull request, we identified @dlstadther, @Tarrasch and @mikekap to be potential reviewers

@erikbern
Copy link
Contributor

erikbern commented Aug 1, 2016

lgtm although would be cool if this works with --help

@brcopeland
Copy link
Contributor Author

@erikbern, can you give me an example of what you mean? I'd be happy to make the change(s). When I create a Task using a ChoiceParameter, the parameter and its description show up when I run luigi --module <module> <Task> --help.

@erikbern
Copy link
Contributor

erikbern commented Aug 1, 2016

would be cool if the --help also shows what options are available. but no biggie :)

if var in self.choices:
return var
else:
raise ValueError("{s} is not a valid choice from {choices}".format(
Copy link
Contributor

Choose a reason for hiding this comment

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

this line is broken – can you fix

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, fixed. Don't know how I didn't copy that last line.

@brcopeland
Copy link
Contributor Author

brcopeland commented Aug 1, 2016

Ah, yeah. I'm trying to figure out a way to do that - updating self.description in init does not appear to be sufficient.

@brcopeland
Copy link
Contributor Author

Ok, got it working. My system has a luigi install I was importing instead of the one I was editing.

@erikbern
Copy link
Contributor

erikbern commented Aug 2, 2016

awesome! flake8 is complaining: https://travis-ci.org/spotify/luigi/jobs/149050059

@Tarrasch
Copy link
Contributor

Tarrasch commented Aug 2, 2016

Can you also add test cases please?

"""
def __init__(self, choices, var_type=str, *args, **kwargs):
super(ChoiceParameter, self).__init__(*args, **kwargs)
self.choices = set(var_type(choice) for choice in choices)
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you make this into an assertion? I imagine people creating new Parameters know enough luigi+python that they would rather be explicit in types over than luigi magically converting stuff behind their back.

@Tarrasch
Copy link
Contributor

Tarrasch commented Aug 2, 2016

This class is somewhat similar to EnumParameter. Would you mind interlinking those two in the docs? Maybe add something like "If you want a more typed and structured version of a ChoiceParameter, you should consider using an EnumParameter instead." could guide our users to pick the right choice?

@brcopeland
Copy link
Contributor Author

You could be entirely right here. I am a pretty new user of luigi and may have overlooked this class before coming up with my own version. I will clean it up if requested, but maybe at this point it just makes more sense to not include this.

@Tarrasch
Copy link
Contributor

Tarrasch commented Aug 3, 2016

I still think this makes sense. Not everyone likes to create a new Enum type for every input-restriction and add all the conversion overhead if they want to eventually go back to a string type. I would be happy to include this, as long as the docs comes with recommended good practices. Like we've previously done here for example. :)

@brcopeland
Copy link
Contributor Author

I changed the docstring to I believe the proper format and added a test suite to the test/ directory. Please let me know if any further changes would be welcome.

def __init__(self, var_type=str, *args, **kwargs):
if "choices" not in kwargs:
raise ParameterException("A choices iterable must be specified")
self._choices = set(var_type(choice) for choice in kwargs.pop("choices"))
Copy link
Contributor

Choose a reason for hiding this comment

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

As I pointed out earlier, I probably would prefer if we could somehow would assert instead of convert. But I'm not sure really what's best :)

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, ok sure I think that's perfectly reasonable.

@Tarrasch
Copy link
Contributor

Tarrasch commented Aug 4, 2016

Apart from the small comment about assert/convert. This looks very good. I must say I'm very impressed how you managed to fix all the shortcomings in a single review turnaround! :)

@brcopeland
Copy link
Contributor Author

Made a couple changes to assert the choices are the proper type as you suggest. And sure, glad it's helpful.

@brcopeland
Copy link
Contributor Author

I rebased, updated docstrings, and added unit tests for the class.

@Tarrasch Tarrasch merged commit aa2224c into spotify:master Aug 9, 2016
@Tarrasch
Copy link
Contributor

Tarrasch commented Aug 9, 2016

Awesomeness! :)

@Tarrasch
Copy link
Contributor

A post-merge note. Some users might want to use the "Functional API" of enums. Instead of

ChoiceParameter(choices=['a', 'b', 'c'])

Some users might prefer

EnumParameter(enum=Enum('Character', 'a b c'))

This was referenced Jun 29, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants