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

Support custom parameter types #443

Closed
wants to merge 1 commit into from

Conversation

paulo-raca
Copy link
Contributor

While most CLI parameters are strings, ints, etc, we sometimes need custom
types.

Currently typer has no support for it (See #77), and while there are a few hacks, the
likely solution is to add a 'str' argument and parse it inside the main function.

This PR adds support for custom types in 3 different ways:

  • Manually specifying a click_type
  • Manually specifying a parse function
  • Using a Callable type annotation (It is very common for types to have a string constructor, like int("1"))

@@ -38,7 +38,7 @@ Documentation = "https://typer.tiangolo.com/"
[tool.flit.metadata.requires-extra]
test = [
"shellingham >=1.3.0,<2.0.0",
"pytest >=4.4.0,<5.4.0",
"pytest >=6.2.5",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not sure if I should bump it on this PR, but it was necessary to test it under Python 3.10

@codecov
Copy link

codecov bot commented Aug 15, 2022

Codecov Report

Merging #443 (847d207) into master (83bf2fc) will decrease coverage by 0.01%.
The diff coverage is 97.56%.

❗ Current head 847d207 differs from pull request most recent head 24466a3. Consider uploading reports for the commit 24466a3 to get more accurate results

@@             Coverage Diff             @@
##            master     #443      +/-   ##
===========================================
- Coverage   100.00%   99.98%   -0.02%     
===========================================
  Files          285      285              
  Lines         6467     6506      +39     
===========================================
+ Hits          6467     6505      +38     
- Misses           0        1       +1     
Impacted Files Coverage Δ
typer/params.py 100.00% <ø> (ø)
tests/test_type_conversion.py 98.82% <96.87%> (-1.18%) ⬇️
typer/main.py 100.00% <100.00%> (ø)
typer/models.py 100.00% <100.00%> (ø)

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

@github-actions
Copy link

📝 Docs preview for commit 847d207 at: https://62faaa2b7f883f06b9e3e56a--typertiangolo.netlify.app

While most CLI parameters are strings, ints, etc, we sometimes need custom
types.

Currently typer has no support for it (See fastapi#77), and while there are a few hacks, the
likely solution is to add a 'str' argument and parse it inside the main function.

This PR adds support for custom types in 3 different ways:
- Manually specifying a `click_type`
- Manually specifying a `parse` function
- Using a Callable type annotation (It is very common for types to have a string constructor, like `int("1")`)
@rafales
Copy link

rafales commented Aug 29, 2022

@tiangolo any reason this has not been merged? I'm constantly missing Decimal type. Is there anything I can do to help / speed this up?

@jpurviance
Copy link
Contributor

jpurviance commented Apr 24, 2023

I've been able to verify that this PR supports parsing of custom parameter types:

import click
import typer
from typing import Optional

class CustomClass:
    def __init__(self, value):
        self.value = value

    def __str__(self):
        return f"<{self.__class__.__name__}: {self.value=}>"

    def __repr__(self):
        return str(self)

class CustomClassParser(click.ParamType):
    name = "CustomClass"

    def convert(self, value, param, ctx):
        return CustomClass(value*3)

def parse_custom_class(value):
    return CustomClass(value*2)

def main(
        arg_1: str = typer.Argument("arg_1", click_type=CustomClassParser()),
        arg_2: str = typer.Argument("arg_2", parser=parse_custom_class),
        opt_1: str = typer.Option("opt_1", click_type=CustomClassParser()),
        opt_2: str = typer.Option("opt_2", parser=parse_custom_class)
    ):
    print(
        (
            arg_1,
            arg_2,
            opt_1,
            opt_2,
        )
    )


if __name__ == "__main__":
    typer.run(main)

invocation:

python test-cli.py 1 2 --opt-1 a --opt-2 b
(<CustomClass: self.value='111'>, <CustomClass: self.value='22'>, <CustomClass: self.value='aaa'>, <CustomClass: self.value='bb'>)

And the corresponding help message

python test-cli.py --help
Usage: test-cli.py [OPTIONS] [ARG_1] [ARG_2]

Arguments:
  [ARG_1]  [default: arg_1]
  [ARG_2]  [default: arg_2]

Options:
  --opt-1 CUSTOMCLASS         [default: opt_1]
  --opt-2 PARSE_CUSTOM_CLASS  [default: opt_2]
  --help                      Show this message and exit.

@jpurviance
Copy link
Contributor

Since I'm not able to update this PR, I have created #583. @paulo-raca , I've kept your contribution in the git commit history. Thank you for getting this started 🎉

@paulo-raca
Copy link
Contributor Author

I'm happy to see this moving on, thank you!

Closing this PR in favour of yours

@paulo-raca paulo-raca closed this Apr 25, 2023
tiangolo added a commit that referenced this pull request May 1, 2023
…) (#583)

* Support custom parameter types

While most CLI parameters are strings, ints, etc, we sometimes need custom
types.

Currently typer has no support for it (See #77), and while there are a few hacks, the
likely solution is to add a 'str' argument and parse it inside the main function.

This PR adds support for custom types in 3 different ways:
- Manually specifying a `click_type`
- Manually specifying a `parse` function
- Using a Callable type annotation (It is very common for types to have a string constructor, like `int("1")`)

* Document how to parse custom objects with Typer.

Typer supports parsing of cutom types with:
- A user provided parser class
- A click custom type parser

* 🎨 [pre-commit.ci] Auto format from pre-commit.com hooks

* 📝 Tweak and simplify docs

* ✅ Tweak tests to run scripts and remove pragma: nocover in examples

* 📝 Tweak examples for docs, add types and remove # pragma: nocover

* ♻️ Tweak implementation checking for parser and Click type

---------

Co-authored-by: Paulo Costa <me@paulo.costa.nom.br>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
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.

3 participants