typer icon indicating copy to clipboard operation
typer copied to clipboard

PEP 604 Support

Open AngellusMortis opened this issue 3 years ago • 17 comments

First Check

  • [X] I added a very descriptive title to this issue.
  • [X] I used the GitHub search to find a similar issue and didn't find it.
  • [X] I searched the Typer documentation, with the integrated search.
  • [X] I already searched in Google "How to X in Typer" and didn't find any information.
  • [X] I already read and followed all the tutorial in the docs and didn't find an answer.
  • [X] I already checked if it is not related to Typer but to Click.

Commit to Help

  • [X] I commit to help with one of those options 👆

Example Code

from pathlib import Path
import typer


def main(output: Path | None):
    typer.guess_name(f"Hello {name}")


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

Description

Using an argument with the type of pathlib.Path | None (as per PEP 604) raise the error:

Type not yet supported: pathlib.Path | None

Wanted Solution

| None types should work instead of having to need to use Optional[].

Wanted Code

from pathlib import Path
import typer


def main(output: Path | None):
    typer.echo(output)


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

Alternatives

No response

Operating System

Linux

Operating System Details

No response

Typer Version

0.4.0

Python Version

3.10.1

Additional Context

No response

AngellusMortis avatar Jan 04 '22 21:01 AngellusMortis

I'm thinking if you can do this output: Path = None? When you have Path | None, the function expects either Path or None to be passed. This is the case even if you use Optional[] without setting a default value type. Plus I believe Typer is tested for up to Python 3.9. This means most of the features from Python 3.10 might not work as expected. Let's just say certain recursive dependencies used by Typer also might have similar troubles.

navhits avatar Jan 18 '22 07:01 navhits

+1 Even using Python 3.10 without the __future__ imports PEP 604 isn't supported. @tiangolo Are there any plans to support this in the near future?

SRv6d avatar May 22 '22 14:05 SRv6d

Could this be more of a Pydantic issue?

navhits avatar May 22 '22 16:05 navhits

@navhits I'm not exactly sure what you mean. Pydantic supports PEP 604 type hints.

SRv6d avatar May 24 '22 21:05 SRv6d

If that's the case, then try building from python3.10 branch. In my understanding 604 is a 3.10 focussed enhancement.

navhits avatar May 25 '22 01:05 navhits

Ok. There's a 0.4.1 release already. Try this version @SRv6d

navhits avatar May 25 '22 01:05 navhits

I've been on that version since march.

SRv6d avatar May 25 '22 20:05 SRv6d

Seems this is still broken as of 0.7.0, even though that release is supposed to support Python 3.11 (and therefore I assumed these new type annotations included with Python3.10)

Sighery avatar Nov 10 '22 10:11 Sighery

Yeps, running into this as well.

As we have pyupgrade in place enforcing PEP 604, I am in an awkward situation 🤔

aberres avatar Dec 05 '22 14:12 aberres

As we have pyupgrade in place

Make them standalone types and pyupgrade will not change it. Or exclude the file from pyupgrade (your CLI interface is separated from the rest of your app, right?).

PathOrNone = Path | None

def main(output: PathOrNone):
    typer.guess_name(f"Hello {name}")

AngellusMortis avatar Dec 05 '22 14:12 AngellusMortis

As we have pyupgrade in place

Make them standalone types and pyupgrade will not change it. Or exclude the file from pyupgrade (your CLI interface is separated from the rest of your app, right?).

PathOrNone = Path | None

def main(output: PathOrNone):
    typer.guess_name(f"Hello {name}")

Last I tried, making them standalone types would still give errors in typer, as it just doesn't support the new union notation at all. If you pass it a standalone type, it'll just go through an extra hop to get the types that are in an union in the standalone type, and then fail again because it doesn't understand |

Sighery avatar Dec 05 '22 14:12 Sighery

Sorry, bad example, I just woke up. 😂

PathOrNone = Optional[Path]

def main(output: PathOrNone):
    typer.guess_name(f"Hello {name}")

pyupgrade should not change Optional[] type aliases.

AngellusMortis avatar Dec 05 '22 14:12 AngellusMortis

PathOrNone = Optional[Path]

Nice one, thanks!

aberres avatar Dec 05 '22 14:12 aberres

Since the PR doesn't link to this issue, I'll link it here. This PR appears to be trying to fix this issue:

  • https://github.com/tiangolo/typer/pull/522

johnthagen avatar Jan 03 '23 13:01 johnthagen

For visibility, the current open PR for this issue is

  • #676

johnthagen avatar Jan 16 '24 13:01 johnthagen

Confirmed that either #676 or #548 will fix this issue!

svlandeg avatar Apr 11 '24 12:04 svlandeg