1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
# imports
from collections import abc
import typing
# exports
__all__: typing.Sequence[str] = (
'normalize_args',
'typename',
)
## code ##
def typename(obj) -> str:
"""Return the type name of *obj*."""
return type(obj).__name__
# argument type in `normalize_args`.
ArgType = typing.TypeVar('ArgType') # pylint: disable=invalid-name # type vars don't follow the usual convention
def normalize_args(
*args: typing.Union[ArgType, typing.Iterable[ArgType], typing.Iterator[ArgType]]
) -> typing.Tuple[ArgType, ...]:
"""Arguments to a function can be passed as individual arguments, list-like
structures, or iterables. This function processes any of these styles and
returns a tuple of the respective items. Typically used within a function
provide a flexible interface but sill have parameters in a normalized form.
Examples:
>>> normalize_args(0,1,2)
(1,2,3)
>>> normalize_args([0,1,2])
(1,2,3)
>>> normalize_args(range(3))
(1,2,3)
"""
if len(args) == 0: # foo()
return tuple()
if len(args) > 1: # foo(0, 1, 2)
return tuple(args) # type: ignore [arg-type] # we assume that argument styles (arg vs. iterable) are not mixed.
if isinstance(args[0], abc.Iterator): # foo(iter([0,1,2]))
return tuple(args[0])
if isinstance(args[0], abc.Iterable) and not isinstance(args[0], str): # foo([0, 1, 2])
return tuple(args[0])
# foo(0)
return (args[0], ) # type: ignore [return-value] # if args[0] is a str, we assume that ArgType was str.
## EOF ##
|