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

PEP 604 Support #348

Closed
7 tasks done
AngellusMortis opened this issue Jan 4, 2022 · 18 comments · Fixed by #548
Closed
7 tasks done

PEP 604 Support #348

AngellusMortis opened this issue Jan 4, 2022 · 18 comments · Fixed by #548
Labels
feature New feature, enhancement or request investigate

Comments

@AngellusMortis
Copy link

First Check

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

Commit to Help

  • 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 AngellusMortis added the feature New feature, enhancement or request label Jan 4, 2022
@navhits
Copy link

navhits commented Jan 18, 2022

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.

@SRv6d
Copy link

SRv6d commented May 22, 2022

+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?

@navhits
Copy link

navhits commented May 22, 2022

Could this be more of a Pydantic issue?

@SRv6d
Copy link

SRv6d commented May 24, 2022

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

@navhits
Copy link

navhits commented May 25, 2022

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

@navhits
Copy link

navhits commented May 25, 2022

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

@SRv6d
Copy link

SRv6d commented May 25, 2022

I've been on that version since march.

@Sighery
Copy link

Sighery commented Nov 10, 2022

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)

@aberres
Copy link

aberres commented Dec 5, 2022

Yeps, running into this as well.

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

@AngellusMortis
Copy link
Author

AngellusMortis commented Dec 5, 2022

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}")

@Sighery
Copy link

Sighery commented Dec 5, 2022

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 |

@AngellusMortis
Copy link
Author

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.

@aberres
Copy link

aberres commented Dec 5, 2022

PathOrNone = Optional[Path]

Nice one, thanks!

@johnthagen
Copy link

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

@johnthagen
Copy link

For visibility, the current open PR for this issue is

@svlandeg
Copy link
Member

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

@Spenhouet
Copy link

Pydantic also has this issue and supports the union type as of pydantic 2.5. Not sure if this requires typer to support pydantic >=2.5?

@tiangolo
Copy link
Member

Thanks everyone for the feedback! ☕

This should have been fixed by #548

It is now available in Typer 0.12.4 🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment