Note: This is a Jupyter notebook. You can explore this notebook interactively by clicking the "download" button in the top-right corner.
Sequence Parameters¶
A sequence parameter is one annotated with any of: Sequence
, List
, Tuple
, Set
, or Dict
When a parameter is provided multiple times, the values are appended to the final result.
The type of the values within the data structure must be homogenous.
For example:
List¶
Parameters annotated with List
or Sequence
are treated the same.
import yapx
from typing import List, Sequence, Tuple, Set, Dict
def demo(value: List[str]):
print(value, type(value))
yapx.run(demo, args=["--value", "one", "--value", "two", "--value", "three"])
['one', 'two', 'three'] <class 'list'>
Tuple¶
Yapx offers limited support for the Tuple type. The type must be homogenous, and the length unbounded. It's effectively treated the same as a List/Sequence.
import yapx
def demo(value: Tuple[str, ...]):
print(value, type(value))
yapx.run(demo, args=["--value", "one", "--value", "two", "--value", "three"])
('one', 'two', 'three') <class 'tuple'>
Set¶
Set
behaves as you would expect:
import yapx
def demo(value: Set[str]):
print(value, type(value))
yapx.run(
demo,
args=[
"--value",
"one",
"--value",
"one",
"--value",
"two",
"--value",
"three",
"--value",
"two",
],
)
{'two', 'three', 'one'} <class 'set'>
Dict¶
Parameters annotated as Dict
are handled similar to other sequences, but the values are expected to be key-value pairs, separated by an equal sign =
.
import yapx
from typing import Dict, Optional
def demo(value: Dict[str, int]):
print(value, type(value))
yapx.run(
demo,
args=[
"--value",
"one=1",
"--value",
"two=2",
"--value",
"three=3",
],
)
{'one': 1, 'two': 2, 'three': 3} <class 'dict'>
If a value does not contain an equal sign, it's resulting value is None
. This is actually a clever way to obtain an ordered set.
import yapx
from typing import Dict, Optional
def demo(value: Dict[str, Optional[int]]):
print(value, type(value))
yapx.run(
demo,
args=[
"--value",
"one",
"--value",
"one",
"--value",
"two",
"--value",
"three",
"--value",
"two",
],
)
{'one': None, 'two': None, 'three': None} <class 'dict'>
Sequences from Strings¶
It is sometimes useful to specify the list values in a string, and necessary when loading sequence values from an environment variable.
The string must contain space-separated values contained within square brackets, e.g.: [hello world]
is parsed to ["hello", "world"]
import os
os.environ["MY_VALUES"] = "[a b c ez as 1 2 3]"
Works for dictionaries too.
import os
os.environ["MY_VALUES"] = "[a='aye aye' b=bae c=see ez=easy as=af one=1 two=2 three=3]"
import yapx
from yapx.types import Annotated
from typing import Dict
def demo(value: Annotated[Dict[str, str], yapx.arg(env="MY_VALUES")]):
return value
yapx.run(demo, args=[])
{'a': 'aye aye', 'b': 'bae', 'c': 'see', 'ez': 'easy', 'as': 'af', 'one': '1', 'two': '2', 'three': '3'}
Multi-Value Parameters¶
The default method of providing sequence values is by providing the argument multiple times, e.g.:
--value one --value two --value three
Leveraging yapx.arg(nargs=...)
, a parameter can accept multiple values by separating them with a space, like this:
--value one two three
nargs accepts any of:
- an integer, specifying a finite number of accepted argument values
?
meaning0
or1
*
meaning0
or more (unbounded)+
meaning1
or more (unbounded)
import yapx
from yapx.types import Annotated
from typing import List
def demo(value: Annotated[List[bool], yapx.arg(nargs="+")]):
print(value, type(value))
yapx.run(demo, args=["--value", "0", "1", "true", "false", "t", "f", "y", "n"])
[False, True, True, False, True, False, True, False] <class 'list'>
I prefer this style, but it introduces one issue to be aware of.
If the multi-valued parameter precedes a positional argument or subcommand -- like shown below -- the parser will not behave.
--value one two three do-work
When an parameter is positional and is type-hinted with a sequence-type, it will be inherently multi-value because there is no flag to provide multiple times.
import yapx
from yapx.types import Annotated
from typing import List
def demo(value: Annotated[List[bool], yapx.arg(pos=True)]):
print(value, type(value))
yapx.run(demo, args=["0", "1", "true", "false", "t", "f", "y", "n"])
[False, True, True, False, True, False, True, False] <class 'list'>