Skip to content

Commit

Permalink
Add sigparse.utils.unwrap (#8)
Browse files Browse the repository at this point in the history
* add the utils function

* add tests

* fix tests

* add tests

* add tests

* support 3.7

* args 3.7

* mypy
  • Loading branch information
zunda-arrow authored Oct 16, 2022
1 parent 3f09f6d commit 25386dd
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 0 deletions.
2 changes: 2 additions & 0 deletions sigparse/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,13 @@
from sigparse._sigparse import sigparse, Parameter
from sigparse._classparse import classparse, ClassVar
from sigparse._pep604 import global_PEP604
from sigparse import utils

__all__: typing.Sequence[str] = (
"classparse",
"sigparse",
"Parameter",
"ClassVar",
"global_PEP604",
"utils",
)
54 changes: 54 additions & 0 deletions sigparse/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import types
import typing

__all__: typing.Sequence[str] = ("unwrap",)

try:
UnionType = types.UnionType # type: ignore
except AttributeError:
UnionType = ...

NoneType = type(None)


def _get_origin(typehint: typing.Any) -> typing.Any:
if hasattr(typehint, "__origin__"):
return typehint.__origin__

return None


def _get_args(typehint: typing.Any) -> typing.Any:
if hasattr(typehint, "__args__"):
return typehint.__args__

return None


def unwrap(typehint: typing.Any) -> typing.Any:
"""
Remove the `None` values from a `Union[T, U]` or `Optional[T]`.
If one of `T` or `U` is `None`, return the non-none value.
If `T` and `U` are `None`, return `None`.
If neither `T` or `U` are `None`, return `Union[T, U]`.
If `typehint` is not a `Union` or `Option` return `typehint`.
"""

if typehint is NoneType:
return None

if _get_origin(typehint) not in {typing.Union, UnionType}:
return typehint

args = _get_args(typehint)

if not args:
return None

hints = list(filter(lambda x: x not in {NoneType, None}, args))

if len(hints) == 1:
return hints[0]

return typing.Union[hints[0], hints[1]]
13 changes: 13 additions & 0 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import typing
import sigparse

def test_unwrap():
assert sigparse.utils.unwrap(typing.Union[int, None]) == int
assert sigparse.utils.unwrap(typing.Union[None, None]) == None
assert sigparse.utils.unwrap(typing.Union[int, str]) == typing.Union[int, str]

assert sigparse.utils.unwrap(typing.Optional[int]) == int
assert sigparse.utils.unwrap(typing.Optional[None]) == None

assert sigparse.utils.unwrap(int) == int
assert sigparse.utils.unwrap(None) == None

0 comments on commit 25386dd

Please sign in to comment.