Skip to content

Commit

Permalink
Support types from PEP 585, 604
Browse files Browse the repository at this point in the history
  • Loading branch information
brentyi committed Oct 4, 2022
1 parent 913155a commit 515dd00
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 24 deletions.
23 changes: 22 additions & 1 deletion dcargs/_resolver.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
"""Utilities for resolving types and forward references."""

import collections.abc
import copy
import dataclasses
import sys
from typing import (
Any,
Callable,
Dict,
FrozenSet,
List,
Optional,
Set,
Tuple,
Type,
TypeVar,
Expand Down Expand Up @@ -171,6 +173,25 @@ def apply_type_from_typevar(
if get_origin(typ) is collections.abc.Callable:
assert isinstance(args[0], list)
args = tuple(args[0]) + args[1:]

# Convert Python 3.10-style types to their typing library equivalents, which
# support `.copy_with()`.
if sys.version_info[:2] >= (3, 10):
import types

for new, old in {
# PEP 585
tuple: Tuple,
list: List,
dict: Dict,
set: Set,
frozenset: FrozenSet,
# PEP 604
types.UnionType: Union,
}.items():
if isinstance(typ, new) or get_origin(typ) is new: # type: ignore
typ = old.__getitem__(args) # type: ignore

return typ.copy_with(tuple(apply_type_from_typevar(x, type_from_typevar) for x in args)) # type: ignore

return typ
23 changes: 0 additions & 23 deletions tests/test_kw_only_only_py310.py

This file was deleted.

60 changes: 60 additions & 0 deletions tests/test_new_style_annotations_only_py310.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import dataclasses
from typing import Any, Literal

import pytest

import dcargs


def test_union_basic():
def main(x: int | str) -> int | str:
return x

assert dcargs.cli(main, args=["--x", "5"]) == 5
assert dcargs.cli(main, args=["--x", "6"]) == 6
assert dcargs.cli(main, args=["--x", "five"]) == "five"


def test_union_with_list():
def main(x: int | str | list[bool]) -> Any:
return x

assert dcargs.cli(main, args=["--x", "5"]) == 5
assert dcargs.cli(main, args=["--x", "6"]) == 6
assert dcargs.cli(main, args=["--x", "five"]) == "five"
assert dcargs.cli(main, args=["--x", "True"]) == "True"
assert dcargs.cli(main, args=["--x", "True", "False"]) == [True, False]


def test_union_literal():
def main(x: Literal[1, 2] | Literal[3, 4, 5] | str) -> int | str:
return x

assert dcargs.cli(main, args=["--x", "5"]) == 5
assert dcargs.cli(main, args=["--x", "6"]) == "6"
assert dcargs.cli(main, args=["--x", "five"]) == "five"


def test_super_nested():
def main(
x: None
| list[
tuple[
None | int,
Literal[3, 4],
tuple[int, int] | tuple[str, str],
]
] = None
) -> Any:
return x

assert dcargs.cli(main, args=[]) is None
assert dcargs.cli(main, args="--x None".split(" ")) is None
assert dcargs.cli(main, args="--x None 3 2 2".split(" ")) == [(None, 3, (2, 2))]
assert dcargs.cli(main, args="--x 2 3 x 2".split(" ")) == [(2, 3, ("x", "2"))]
assert dcargs.cli(main, args="--x 2 3 x 2 2 3 1 2".split(" ")) == [
(2, 3, ("x", "2")),
(2, 3, (1, 2)),
]
with pytest.raises(SystemExit):
dcargs.cli(main, args=["--help"])

0 comments on commit 515dd00

Please sign in to comment.