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

[BUG] callback with type Enum passes None back to the app command #223

Open
larsclaussen opened this issue Jan 18, 2021 · 2 comments
Open
Labels
bug Something isn't working investigate

Comments

@larsclaussen
Copy link

Describe the bug

When adding a callback to a typer.Option of type Enum the value is not passed back to the app command.

To Reproduce

Fairly easy to reproduce

  • Create a file main.py with:
import typer
from enum import Enum

app = typer.Typer()


class EndpointChoices(str, Enum):
    localhost = "localhost"
    staging = "staging"
    production = "production"


def models_callback(value: EndpointChoices):
    typer.echo(f"Validating param: {value}, {type(value)}")
    return value


@app.command()
def models(endpoint: EndpointChoices = typer.Option(
            ..., case_sensitive=False, callback=models_callback
        )
):
    """List available models"""
    raise Exception(endpoint)

if __name__ == "__main__":
    app()
  • Call it with:
python main.py --endpoint localhost
  • It outputs:
raise Exception(endpoint)
Exception: None

  • But I expected it to output:
localhost, <enum 'EndpointChoices'>

Expected behavior

I would expect the option argument to be present in the scope of the app command.

Screenshots

Environment

  • OS: Ubuntu 20.04
  • Python 3.8.5
  • Typer Version 0.3.2
@larsclaussen larsclaussen added the bug Something isn't working label Jan 18, 2021
@larsclaussen
Copy link
Author

Just had the idea to return the value of the EndpointChoices instance from the models_callback like so

def models_callback(value: EndpointChoices):
    typer.echo(f"Validating param: {value}, {type(value)}")
    return value.value

Which gives me the result I was expecting

    raise Exception(type(endpoint))
Exception: <enum 'EndpointChoices'>

I'm not sure if this is the expected behavior, though.

@daddycocoaman
Copy link
Contributor

daddycocoaman commented Jan 18, 2021

Looks like what's happening is that at some point during the callback return, the Enum convertor is being called but it passes in the entire Enum object instead of just the value. In this case, it's passing in the EndpointChoices object instead of localhost.

Here is the Enum being passed in the @app.command and returning the expected value:
image

Here is the Enum being returned from the callback into the @app.command. Notice the difference in that it's no longer "localhost" being passed, but "EndpointChoices.localhost" as a string, therefore failing the rest of the function and returning None. This is why returning value.value worked instead...because instead of returning the value of the Enum that @app.command already checked, the callback is returning the entire object.

image

The docs here indicated this is expected behavior, since your callback should receive the same annotation of the main function! However, I think it's counter-intuitive to not handle that case and return None....even as an error it should return the Enum object or raise an error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working investigate
Projects
None yet
Development

No branches or pull requests

3 participants