Skip to content

Commit a1fe56f

Browse files
committed
🍻 @deprecated for v1
1 parent 60cdd95 commit a1fe56f

14 files changed

+93
-48
lines changed

src/arclet/alconna/__init__.py

+1-4
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,8 @@
3636
from .exceptions import NullMessage as NullMessage
3737
from .exceptions import ParamsUnmatched as ParamsUnmatched
3838
from .formatter import TextFormatter as TextFormatter
39-
from .manager import ShortcutArgs as ShortcutArgs
39+
from .shortcut import ShortcutArgs as ShortcutArgs
4040
from .manager import command_manager as command_manager
4141
from .typing import AllParam as AllParam
4242

4343
__version__ = "1.8.31"
44-
45-
# backward compatibility
46-
AnyOne = ANY

src/arclet/alconna/args.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -373,8 +373,10 @@ def __new__(
373373
if seps is not None:
374374
arg.field.seps = seps
375375
cls.__args_data__ = _Args(all_args, cls)
376-
377-
dcls = dc.make_dataclass(cls.__name__, [(arg.name, arg.type_, arg.field.to_dc_field()) for arg in cls.__args_data__.data], namespace=types_namespace, repr=True)
376+
try:
377+
dcls = dc.make_dataclass(cls.__name__, [(arg.name, arg.type_, arg.field.to_dc_field()) for arg in cls.__args_data__.data], namespace=types_namespace, repr=True)
378+
except TypeError as e:
379+
raise TypeError(f"cannot create Args Model: {e}") from None
378380
cls.__init__ = dcls.__init__ # type: ignore
379381
if "__repr__" not in cls.__dict__:
380382
cls.__repr__ = dcls.__repr__ # type: ignore

src/arclet/alconna/core.py

+2
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,8 @@ def _parse(self, message: TDC, ctx: dict[str, Any] | None = None) -> Arparma[TDC
433433
return res
434434
analyser = command_manager.require(self)
435435
argv = analyser.argv
436+
if message.__class__ is str:
437+
message = [message] # type: ignore
436438
argv.enter(ctx).build(message)
437439
if argv.message_cache and (res := command_manager.get_record(argv.token)):
438440
return res

src/arclet/alconna/ingedia/_argv.py

+9-8
Original file line numberDiff line numberDiff line change
@@ -120,15 +120,8 @@ def build(self, data: TDC) -> Self:
120120
"""
121121
self.reset()
122122
if self.checker and not self.checker(data):
123-
if not self.converter:
124-
raise TypeError(data)
125-
try:
126-
data = self.converter(data) # type: ignore
127-
except Exception as e:
128-
raise TypeError(data) from e
123+
raise TypeError(data)
129124
self.origin = data
130-
if data.__class__ is str:
131-
data = [data] # type: ignore
132125
i = 0
133126
raw_data = self.raw_data
134127
for unit in data:
@@ -320,3 +313,11 @@ def argv_config(
320313
Argv._cache.setdefault(target or __argv_type__.get(), {}).update(
321314
{k: v for k, v in locals().items() if v is not None}
322315
)
316+
317+
318+
def reset_argv_config(target: type[Argv] | None = None):
319+
"""重置命令行参数配置"""
320+
if target:
321+
Argv._cache.pop(target, None)
322+
else:
323+
Argv._cache.clear()

src/arclet/alconna/v1/__init__.py

+4
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,7 @@
5656
from .typing import StrMulti as StrMulti
5757
from .typing import UnpackVar as UnpackVar
5858
from .typing import Up as Up
59+
60+
61+
# backward compatibility
62+
AnyOne = ANY

src/arclet/alconna/v1/compat.py

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22

3+
import warnings
34
from typing import Literal, Any, Callable, ContextManager
45
from typing_extensions import deprecated
56
from arclet.alconna import Metadata, Config, global_config
@@ -93,6 +94,7 @@ def __setattr__(self, key, value):
9394
elif key in ("name", "prefixes", "formatter_type", "to_text", "converter"):
9495
setattr(self.origin, key, value)
9596
else:
97+
warnings.warn(f"Namespace.{key} is deprecated, use Namespace.config.{key} instead", DeprecationWarning, stacklevel=2)
9698
setattr(self.origin.config, key, value)
9799

98100

src/arclet/alconna/v1/duplication.py

+3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from inspect import isclass
44
from typing import cast
5+
from typing_extensions import deprecated
56

67
from tarina import Empty
78

@@ -12,6 +13,7 @@
1213
from .stub import ArgsStub, BaseStub, OptionStub, SubcommandStub
1314

1415

16+
@deprecated("Duplication is removed", category=DeprecationWarning, stacklevel=1)
1517
class Duplication:
1618
"""`副本`, 用以更方便的检查、调用解析结果的类。"""
1719

@@ -47,6 +49,7 @@ def subcommand(self, name: str) -> SubcommandStub | None:
4749
return cast(SubcommandStub, getattr(self, name, None))
4850

4951

52+
@deprecated("generate_duplication is removed", category=DeprecationWarning, stacklevel=1)
5053
def generate_duplication(alc: Alconna) -> type[Duplication]:
5154
"""依据给定的命令生成一个解析结果的检查类。"""
5255

src/arclet/alconna/v1/stub.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from dataclasses import dataclass, field
55
from inspect import isclass
66
from typing import Any, Generic, TypeVar
7-
from typing_extensions import Self
7+
from typing_extensions import Self, deprecated
88

99
from nepattern import ANY, BasePattern
1010

@@ -40,6 +40,7 @@ def __repr__(self):
4040
return f"{{{', '.join([f'{k}={v}' for k, v in vars(self).items() if v and not k.startswith('_')])}}}"
4141

4242

43+
@deprecated("ArgsStub is removed, use `ArgsBase` instead", category=DeprecationWarning, stacklevel=1)
4344
@dataclass(init=True)
4445
class ArgsStub(BaseStub[_Args]):
4546
"""参数存根"""
@@ -103,6 +104,7 @@ def __getitem__(self, item: int | str) -> Any:
103104
return self._value[item]
104105

105106

107+
@deprecated("OptionStub is removed", category=DeprecationWarning, stacklevel=1)
106108
@dataclass(init=True)
107109
class OptionStub(BaseStub[Option]):
108110
"""选项存根"""
@@ -130,6 +132,7 @@ def set_result(self, result: OptionResult | None):
130132
return self
131133

132134

135+
@deprecated("SubcommandStub is removed", category=DeprecationWarning, stacklevel=1)
133136
@dataclass(init=True)
134137
class SubcommandStub(BaseStub[Subcommand]):
135138
"""子命令存根"""

src/arclet/alconna/v1/typing.py

+5
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
Literal,
77
TypeVar,
88
)
9+
from typing_extensions import deprecated
910

1011
from nepattern import BasePattern, MatchMode, parser
1112

@@ -14,6 +15,7 @@
1415
T = TypeVar("T")
1516

1617

18+
@deprecated("KeyWordVar is deprecated, use `Field(kw_only=True)` instead", category=DeprecationWarning, stacklevel=1)
1719
class KeyWordVar(BasePattern[T, Any, Literal[MatchMode.KEEP]]):
1820
"""对具名参数的包装"""
1921

@@ -45,6 +47,7 @@ def __getitem__(self, item: BasePattern[T, Any, Any] | type[T] | Any):
4547
__rmatmul__ = __getitem__
4648

4749

50+
@deprecated("MultiVar is deprecated, use `Field(multiple=...)` instead", category=DeprecationWarning, stacklevel=1)
4851
class MultiVar(BasePattern[T, Any, Literal[MatchMode.KEEP]]):
4952
"""对可变参数的包装"""
5053

@@ -87,6 +90,7 @@ class KWBool(BasePattern):
8790
"""对布尔参数的包装"""
8891

8992

93+
@deprecated("UnpackVar is deprecated, use `ArgsBase` instead", category=DeprecationWarning, stacklevel=1)
9094
class UnpackVar(BasePattern):
9195
"""特殊参数,利用dataclass 的 field 生成 arg 信息,并返回dcls"""
9296

@@ -114,6 +118,7 @@ def __mul__(self, other):
114118
Up = _Up()
115119

116120

121+
@deprecated("StrMulti is deprecated, use `Field(multiple=str)` instead", stacklevel=1)
117122
class _StrMulti(MultiVar[str]):
118123
pass
119124

tests/analyser_test.py

+16-11
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
from dataclasses import dataclass, field
2-
from typing import Any, Union
2+
from typing import Union
3+
from collections import UserList
34

5+
import pytest
46
from nepattern import BasePattern, MatchMode
57

68
from arclet.alconna import Alconna, Args, Option
7-
from arclet.alconna.ingedia._argv import argv_config
9+
from arclet.alconna.ingedia._argv import argv_config, reset_argv_config
810

911

1012
@dataclass
@@ -49,7 +51,7 @@ def test_filter_out():
4951
ana = Alconna("ana", Args.foo(str))
5052
assert ana.parse(["ana", 123, "bar"]).matched is True
5153
assert ana.parse("ana bar").matched is True
52-
argv_config(filter_out=[])
54+
reset_argv_config()
5355
ana_1 = Alconna("ana", Args.foo(str))
5456
assert ana_1.parse(["ana", 123, "bar"]).matched is False
5557

@@ -59,7 +61,7 @@ def test_preprocessor():
5961
ana1 = Alconna("ana1", Args.bar(int))
6062
assert ana1.parse(["ana1", [1, 2, 3]]).matched is True
6163
assert ana1.parse(["ana1", [1, 2, 3]]).bar == 3
62-
argv_config(preprocessors={})
64+
reset_argv_config()
6365
ana1_1 = Alconna("ana1", Args.bar(int))
6466
assert ana1_1.parse(["ana1", [1, 2, 3]]).matched is False
6567

@@ -72,7 +74,7 @@ def test_with_set_unit():
7274
assert res.matched is True
7375
assert res.foo.data["qq"] == "123456"
7476
assert not ana2.parse([Segment.text("ana2"), Segment.face(103), Segment.at(123456)]).matched
75-
argv_config()
77+
reset_argv_config()
7678

7779

7880
def test_unhashable_unit():
@@ -88,15 +90,18 @@ def test_unhashable_unit():
8890
print(ana3_1.parse(["ana3_1", "--foo", "--comp", Segment.at(123)]))
8991
print(ana3_1.parse(["ana3_1", "--comp", Segment.at(123)]))
9092

93+
reset_argv_config()
94+
9195

9296
def test_checker():
93-
argv_config(checker=lambda x: isinstance(x, list))
97+
argv_config(checker=lambda x: isinstance(x, UserList))
9498
ana4 = Alconna("ana4", Args.foo(int))
95-
print(ana4.parse(["ana4", "123"]))
96-
try:
97-
print(ana4.parse("ana4 123"))
98-
except TypeError as e:
99-
print(e)
99+
assert ana4.parse(UserList(["ana4", "123"]))
100+
101+
with pytest.raises(TypeError):
102+
ana4.parse("ana4 123")
103+
104+
reset_argv_config()
100105

101106

102107
if __name__ == "__main__":

tests/args_test.py

+24-16
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
import pytest
2+
13
from typing import Union
24

35
from nepattern import INTEGER, BasePattern, MatchMode, combine
46

5-
from arclet.alconna import Args, Arg
7+
from arclet.alconna import Args, Arg, ArgsBase, arg_field
68
from devtool import analyse_args
79

810

@@ -201,21 +203,27 @@ def test_annotated():
201203
assert analyse_args(arg18, ["0 0"], raise_exception=False) != {"foo": 0, "bar": 0}
202204

203205

204-
# def test_unpack():
205-
# from dataclasses import dataclass, field
206-
#
207-
# from arclet.alconna.typing import UnpackVar
208-
#
209-
# @dataclass
210-
# class People:
211-
# name: str
212-
# age: int = field(default=16)
213-
#
214-
# arg19 = Args["people", UnpackVar(People)]
215-
# assert analyse_args(arg19, ["alice", 16]) == {"people": People("alice", 16)}
216-
# assert analyse_args(arg19, ["bob"]) == {"people": People("bob", 16)}
217-
# arg19_1 = Args["people", UnpackVar(People, kw_only=True)].separate("&")
218-
# assert analyse_args(arg19_1, ["name=alice&age=16"]) == {"people": People("alice", 16)}
206+
def test_args_model():
207+
class People(ArgsBase):
208+
name: str
209+
age: int = arg_field(default=16)
210+
211+
assert analyse_args(People, ["abc"]) == {"name": "abc", "age": 16}
212+
213+
class Foo(ArgsBase):
214+
foo: str
215+
216+
class Bar(ArgsBase):
217+
bar: int = arg_field(42)
218+
219+
class Baz(Bar, Foo):
220+
baz: bool = arg_field(True)
221+
222+
assert analyse_args(Baz, ["abc 123"]) == {"foo": "abc", "bar": 123, "baz": True}
223+
224+
with pytest.raises(TypeError, match="cannot create Args Model: non-default argument 'foo' follows default argument"):
225+
class Baz1(Foo, Bar):
226+
baz: bool = arg_field(True)
219227

220228

221229
def test_multi_multi():

tests/base_test.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,20 @@ def test_option_aliases():
2121

2222
def test_separator():
2323
opt2 = Option("foo", Args.bar(int), separators="|")
24-
assert analyse_option(opt2, "foo|123") == OptionResult(None, {"bar": 123})
24+
assert analyse_option(opt2, ["foo|123"]) == OptionResult(None, {"bar": 123})
2525
opt2_1 = Option("foo", Args.bar(int)).separate("|")
2626
assert opt2 == opt2_1
2727

2828

2929
def test_subcommand():
3030
sub = Subcommand("test", Option("foo"), Option("bar"))
3131
assert len(sub.options) == 2
32-
assert analyse_subcommand(sub, "test foo") == SubcommandResult(None, {}, {"foo": OptionResult()})
32+
assert analyse_subcommand(sub, ["test foo"]) == SubcommandResult(None, {}, {"foo": OptionResult()})
3333

3434

3535
def test_compact():
3636
opt3 = Option("-Foo", Args.bar(int), compact=True)
37-
assert analyse_option(opt3, "-Foo123") == OptionResult(None, {"bar": 123})
37+
assert analyse_option(opt3, ["-Foo123"]) == OptionResult(None, {"bar": 123})
3838

3939

4040
def test_add():

tests/core_test.py

+13
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,7 @@ def test_completion_interface():
723723

724724
def test_call():
725725
from dataclasses import dataclass
726+
from arclet.alconna import ArgsBase
726727

727728
alc22 = Alconna("core22", Args.foo(int), Args.bar(str))
728729
alc22("core22 123 abc")
@@ -748,6 +749,18 @@ class A:
748749
alc22_1.parse("core22_1 abc")
749750
assert alc22_1.exec_result["A"] == A("abc")
750751

752+
class B(ArgsBase):
753+
name: str
754+
755+
alc22_2 = Alconna("core22_2", B)
756+
757+
@alc22_2.bind(False)
758+
def cb1(args: B):
759+
return args.name
760+
761+
alc22_2.parse("core22_2 abc")
762+
assert cb1.result == "abc"
763+
751764

752765
def test_nest_subcommand():
753766
class A:

tests/devtool.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ def analyse_args(
6161
def analyse_header(
6262
headers: list[str | Any] | list[tuple[Any, str]],
6363
command_name: str,
64-
command: DataCollection[str | Any],
64+
command: list[str | Any],
6565
sep: str = " ",
6666
compact: bool = False,
6767
raise_exception: bool = True,
@@ -83,7 +83,7 @@ def analyse_header(
8383

8484
def analyse_option(
8585
option: Option,
86-
command: DataCollection[str | Any],
86+
command: list[str | Any],
8787
raise_exception: bool = True,
8888
context_style: Literal["bracket", "parentheses"] | None = None,
8989
**kwargs,
@@ -111,7 +111,7 @@ def analyse_option(
111111

112112
def analyse_subcommand(
113113
subcommand: Subcommand,
114-
command: DataCollection[str | Any],
114+
command: list[str | Any],
115115
raise_exception: bool = True,
116116
context_style: Literal["bracket", "parentheses"] | None = None,
117117
**kwargs,

0 commit comments

Comments
 (0)