命令参数
Args
是一个特殊的类,用来包装command
中的args
, 即命令参数, 如
from arclet.alconna import Args, Option
opt = Option("test", Args(foo=str, num=int).default(foo="bar"))
或
from arclet.alconna import Args, Option
opt = Option("test", Args["foo", str, "bar"]["num", int])
Args
推荐的构造方式如下:
Args.default()
用来设置 Args(**kwargs)
时的默认值, 但是不会覆盖 Args["key", type, default]
的默认值
Arg
Args
是由多个Arg
组成的, 一个Arg
代表一个参数, 如
from arclet.alconna import Args, Arg
arg1 = Args["foo", str, "bar"]["num", int]
arg2 = Args[Arg("foo", str, "bar")][Arg("num", int)]
arg3 = Args(Arg("foo", str, "bar"), Arg("num", int))
assert arg1 == arg2 == arg3
Arg
的构造方式如下:
Arg(
name: str,
value: TAValue | None = None,
field: Field[_T] | _T | None = None,
seps: str | Iterable[str] = " ",
notice: str | None = None,
flags: list[ArgFlag] | None = None,
)
name
为参数名, 用于在Args
与解析结果中标识该参数value
为参数值, 用于在Args
中标识该参数的类型或者匹配值field
为参数的Field
, 用于在Args
中标识该参数的默认值,默认值生成器等; 也可以直接传入默认值seps
为参数的分隔符, 用于在Args
中标识该参数的分隔符, 默认为' '
(空格)notice
为参数的提示, 用于在Args
中标识该参数的提示, 默认为None
flags
为参数的标识符, 用于在Args
中标识该参数的标识符, 默认为None
flag
目前有 3 种, 分别为 ?: ArgFlag.OPTIONAL
、!: ArgFlag.ANTI
和 /: ArgFlag.HIDDEN
其中 name
保留了一些特殊形式, 用于便捷传入 notice
和 flags
其形式为 name(;?)flags#notice
, ;
或 名字之后为 flags
, #
之后为 notice
:
from arclet.alconna import Arg, ArgFlag
arg1 = Arg("foo;/?#bar")
arg2 = Arg("foo", notice="bar", flags=[ArgFlag.OPTIONAL, ArgFlag.HIDDEN])
assert arg1 == arg2
value
value
可以是以下类型:
- 存在于
nepattern.all_patterns
中的类型/字符串,用以替换为预制好的 BasePattern - 字符串,会转换为正则表达式
- 列表,其中可存放 BasePattern、类型或者任意参数值,如字符串或者数字
Union
、Optional
、Literal
等会尝试转换为List[Type]
Dict[type1,type2]
、List[type]
、Set[type]
- 一般的类型,其会尝试比较传入参数的类型是否与其相关
- AnyOne、AllParam.
- 预制好的字典, 表示传入值依据该字典的键决定匹配结果
Annotated[type, Callable[..., bool], ...]
,表示为某一类型添加校验器Callable[[P], T]
,表示会将传入的参数 P 经过该调用对象并将返回值 T 作为匹配结果- ...
内置的类型检查包括 int
、str
、float
、bool
、'url'
、'ip'
、'email'
、list
、dict
、tuple
、set
、Any
、bytes
、hex
、datetime
等。
Field
Field
是如下定义的:
class Field(Generic[_T]):
"""标识参数单元字段"""
default: _T = dc_field(default=None)
alias: str | None = dc_field(default=None)
completion: Callable[[], str | list[str]] | None = dc_field(default=None)
其中 default
用于给出默认值
需要注意的是, default 为 None
相当于没有默认值
如果你需要使自己的默认值为 None
, 你应该使用 arclet.aclonna.Empty
, 其会在解析之后自动替换
separator
在命令解析过程中, Args
会根据每个 Arg
的 seps
来进行分隔:
Command(
...,
Separator("main_sep"),
Segment(
Name("opt1"),
Separator("opt1_sep"),
Segment(
Arg("value1"),
Separator("arg1_sep"),
Arg("value2"),
Separator("arg2_sep"),
...,
Arg("valueN")
)
),
Separator("main_sep"),
Segment(
Name("opt2"),
Separator("opt2_sep"),
...
)
)
AnyOne 与 AllParam
AnyOne
与AllParam
是特殊的两种参数类型, 作用分别为单参泛匹配与全参泛匹配
对于同个命令, /test foo bar 123
来讲
from arclet.alconna import AnyOne, AllParam, Alconna, Args
test1 = Alconna(
"/test",
Args["wild", AnyOne],
)
test2 = Alconna(
"/test",
Args["wild", AllParam],
)
test1
只能将foo
匹配给wild
而 test2
能够将foo bar 123
匹配给wild
AllParam
会直接截断后续的命令解析操作, 请谨慎使用
Keyword args
Alconna
提供了一个特殊的 KeyWordVar
, 用于标识一个参数为关键字参数:
from arclet.alconna import Args, Alconna, KeyWordVar
alc = Alconna("test", Args["foo", KeyWordVar(int)])
这会使得该参数只能通过关键字参数的形式传入, 例如:
KeyWordVar
可以传入一个 sep
参数, 用于标识该关键字参数的分隔符, 默认为'='
:
from arclet.alconna import Args, Alconna, KeyWordVar
alc = Alconna("test", Args["foo", KeyWordVar(int, sep=":")])
这样该参数就可以通过 foo:123
的形式传入了
Multi args
Alconna
提供了另一个特殊的 MultiVar
, 用于标识一个参数为不定参数:
from arclet.alconna import Args, Alconna, MultiVar
alc = Alconna("test", Args["foo", MultiVar(int)])
这会使得该参数可以接受多个相同类型的参数, 例如:
MultiVar
可以传入一个 flag
参数, 用于标识该可变参数的类型, 目前支持的类型有:
*
: 传入0个或多个参数+
: 传入1个或多个参数- 任意大于0的整数: 传入指定数量的参数
MultiVar
与 KeyWordVar
可以结合使用, 例如:
from arclet.alconna import Args, Alconna, MultiVar, KeyWordVar
alc = Alconna("test", Args["foo", MultiVar(KeyWordVar(int))])
这会使得该参数可以接受多个关键字参数, 例如:
Optional args
通过 flag
参数, 我们可以将参数标记为可选参数:
from arclet.alconna import Args, Alconna, Arg, ArgFlag
alc = Alconna("test", Args["foo", int]["bar;?", str])
# or
alc = Alconna("test", Args["foo", int][Arg("bar", str, flags=[ArgFlag.Optional])])
这会使得该参数可以不传入, 例如:
该情形下也可以使用 typing.Optional
来标记参数参数:
from arclet.alconna import Args, Alconna
from typing import Optional
alc = Alconna("test", Args["foo", int]["bar", Optional[str]])
这等同于:
alc = Alconna("test", Args["foo", int]["bar", str, Empty]) # 意思为 bar 的默认值是 None
optional 参数必须在 multi 参数之前,并且 optional flag 不能与 MultiVar
同时使用
Anti args
通过 flag
参数, 我们可以将参数标记为反向参数:
from arclet.alconna import Args, Alconna, Arg, ArgFlag
alc = Alconna("test", Args["foo", int]["bar;!", int])
# or
alc = Alconna("test", Args["foo", int][Arg("bar", int, flags=[ArgFlag.Anti])])
这使得该参数可以传入任何不符合该参数类型的参数, 例如:
Const args
在 value
参数中传入一个 const
值, 可以将该参数标记为常量参数:
from arclet.alconna import Args, Alconna
alc = Alconna("test", Args["foo", int]["bar", 123])
# or
from typing import Literal
alc = Alconna("test", Args["foo", int]["bar", Literal[123]])
这会使得该参数只能传入指定的值, 例如:
Union args
在 value
参数中传入一个 typing.Union
值, 可以将该参数标记为联合参数:
from arclet.alconna import Args, Alconna
from typing import Union
alc = Alconna("test", Args["foo", Union[int, bool]])
这会使得该参数可以传入多种类型的参数, 例如:
此处可以直接使用 [int, bool]
作为 value
参数
不仅如此,直接使用 [...]
可以传入常量参数作为 "choice" 参数:
alc = Alconna("test", Args["foo", [1, 2, 3]])
这使得该参数只能传入 1
, 2
, 3
中的一个, 例如:
[...]
中可以同时传入类型和常量:
alc = Alconna("test", Args["foo", [bool, 1, 2, 3]])
更特别的是,此处还可以传入 "foo|bar"
这样的字符串:
alc = Alconna("test", Args["foo", ["abc|def"]]) # 会尝试在 patterns 里寻找 abc 或 def
# or
alc = Alconna("test", Args["foo", ["re:abc|def"]]) # 转为正则表达式
Switch args
在 value
参数中传入一个字典, 可以将该参数标记为开关参数:
from arclet.alconna import Args, Alconna
alc = Alconna("test", Args["foo", {"bar": 123, "baz": 456}])
这就类似于:
switch (foo) {
case "bar": return 123;
case "baz": return 456;
default: throw new Error("参数不正确");
}
使得该参数只能传入指定的值, 例如:
特别的,如果字典中有一个 ...
键,那么该参数可以传入任何值:
alc = Alconna("test", Args["foo", {"bar": 123, "baz": 456, ...: 789}])
这就类似于:
switch (foo) {
case "bar": return 123;
case "baz": return 456;
default: return 789;
}
Callable args
在 value
参数中传入一个可调用对象, 可以将该参数标记为可调用参数:
from arclet.alconna import Args, Alconna
def func(value) -> int | None:
if isinstance(value, int):
return value * 2
elif isinstance(value, str):
if value == "abc":
return 123
elif value == "def":
return 456
alc = Alconna("test", Args["foo", func])
这会使得该参数只能传入可以通过 func
处理的值, 例如: