mirror of
https://github.com/nonebot/nonebot2.git
synced 2025-02-23 02:55:35 +08:00
🐛 Fix: shell command 词法解析错误未捕获 (#3290)
This commit is contained in:
parent
cf30dc6264
commit
950461b556
@ -557,12 +557,22 @@ class ShellCommandRule:
|
|||||||
if cmd not in self.cmds or msg is None:
|
if cmd not in self.cmds or msg is None:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
state[SHELL_ARGV] = list(
|
try:
|
||||||
chain.from_iterable(
|
state[SHELL_ARGV] = list(
|
||||||
shlex.split(str(seg)) if cast(MessageSegment, seg).is_text() else (seg,)
|
chain.from_iterable(
|
||||||
for seg in msg
|
shlex.split(str(seg))
|
||||||
|
if cast(MessageSegment, seg).is_text()
|
||||||
|
else (seg,)
|
||||||
|
for seg in msg
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
except Exception as e:
|
||||||
|
# set SHELL_ARGV to none indicating shlex error
|
||||||
|
state[SHELL_ARGV] = None
|
||||||
|
# ensure SHELL_ARGS is set to ParserExit if parser is provided
|
||||||
|
if self.parser:
|
||||||
|
state[SHELL_ARGS] = ParserExit(status=2, message=str(e))
|
||||||
|
return True
|
||||||
|
|
||||||
if self.parser:
|
if self.parser:
|
||||||
t = parser_message.set("")
|
t = parser_message.set("")
|
||||||
|
@ -371,9 +371,31 @@ async def test_shell_command():
|
|||||||
assert state[SHELL_ARGV] == []
|
assert state[SHELL_ARGV] == []
|
||||||
assert SHELL_ARGS not in state
|
assert SHELL_ARGS not in state
|
||||||
|
|
||||||
|
test_lexical_error = shell_command(CMD)
|
||||||
|
dependent = next(iter(test_lexical_error.checkers))
|
||||||
|
checker = dependent.call
|
||||||
|
assert isinstance(checker, ShellCommandRule)
|
||||||
|
message = Message("-a '1")
|
||||||
|
event = make_fake_event(_message=message)()
|
||||||
|
state = {PREFIX_KEY: {CMD_KEY: CMD, CMD_ARG_KEY: message}}
|
||||||
|
assert await dependent(event=event, state=state)
|
||||||
|
assert state[SHELL_ARGV] is None
|
||||||
|
|
||||||
parser = ArgumentParser("test")
|
parser = ArgumentParser("test")
|
||||||
parser.add_argument("-a", required=True)
|
parser.add_argument("-a", required=True)
|
||||||
|
|
||||||
|
test_lexical_error_with_parser = shell_command(CMD, parser=ArgumentParser("test"))
|
||||||
|
dependent = next(iter(test_lexical_error_with_parser.checkers))
|
||||||
|
checker = dependent.call
|
||||||
|
assert isinstance(checker, ShellCommandRule)
|
||||||
|
message = Message("-a '1")
|
||||||
|
event = make_fake_event(_message=message)()
|
||||||
|
state = {PREFIX_KEY: {CMD_KEY: CMD, CMD_ARG_KEY: message}}
|
||||||
|
assert await dependent(event=event, state=state)
|
||||||
|
assert state[SHELL_ARGV] is None
|
||||||
|
assert isinstance(state[SHELL_ARGS], ParserExit)
|
||||||
|
assert state[SHELL_ARGS].status != 0
|
||||||
|
|
||||||
test_simple_parser = shell_command(CMD, parser=parser)
|
test_simple_parser = shell_command(CMD, parser=parser)
|
||||||
dependent = next(iter(test_simple_parser.checkers))
|
dependent = next(iter(test_simple_parser.checkers))
|
||||||
checker = dependent.call
|
checker = dependent.call
|
||||||
|
@ -843,21 +843,39 @@ async def _(foo: str = CommandWhitespace()): ...
|
|||||||
|
|
||||||
### ShellCommandArgv
|
### ShellCommandArgv
|
||||||
|
|
||||||
获取 shell 命令解析前的参数列表,列表中可能包含文本字符串和富文本消息段(如:图片)。
|
获取 shell 命令解析前的参数列表,列表中可能包含文本字符串和富文本消息段(如:图片)。当词法解析出错的时候,返回值将为 `None`。通过重载机制即可处理两种不同的情况。
|
||||||
|
|
||||||
<Tabs groupId="python">
|
<Tabs groupId="python">
|
||||||
<TabItem value="3.10" label="Python 3.10+" default>
|
<TabItem value="3.10" label="Python 3.10+" default>
|
||||||
|
|
||||||
```python {4}
|
```python {4}
|
||||||
from typing import Annotated
|
from typing import Annotated
|
||||||
from nonebot.params import ShellCommandArgs
|
from nonebot import on_shell_command
|
||||||
|
from nonebot.params import ShellCommandArgv
|
||||||
|
|
||||||
|
matcher = on_shell_command("cmd")
|
||||||
|
|
||||||
|
# 解析失败
|
||||||
|
@matcher.handle()
|
||||||
|
async def _(foo: Annotated[None, ShellCommandArgv()]): ...
|
||||||
|
|
||||||
|
# 解析成功
|
||||||
|
@matcher.handle()
|
||||||
async def _(foo: Annotated[list[str | MessageSegment], ShellCommandArgv()]): ...
|
async def _(foo: Annotated[list[str | MessageSegment], ShellCommandArgv()]): ...
|
||||||
```
|
```
|
||||||
|
|
||||||
```python {4}
|
```python {4}
|
||||||
from nonebot.params import ShellCommandArgs
|
from nonebot import on_shell_command
|
||||||
|
from nonebot.params import ShellCommandArgv
|
||||||
|
|
||||||
|
matcher = on_shell_command("cmd")
|
||||||
|
|
||||||
|
# 解析失败
|
||||||
|
@matcher.handle()
|
||||||
|
async def _(foo: None = ShellCommandArgv()): ...
|
||||||
|
|
||||||
|
# 解析成功
|
||||||
|
@matcher.handle()
|
||||||
async def _(foo: list[str | MessageSegment] = ShellCommandArgv()): ...
|
async def _(foo: list[str | MessageSegment] = ShellCommandArgv()): ...
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -866,15 +884,33 @@ async def _(foo: list[str | MessageSegment] = ShellCommandArgv()): ...
|
|||||||
|
|
||||||
```python {4}
|
```python {4}
|
||||||
from typing import Union, Annotated
|
from typing import Union, Annotated
|
||||||
from nonebot.params import ShellCommandArgs
|
from nonebot import on_shell_command
|
||||||
|
from nonebot.params import ShellCommandArgv
|
||||||
|
|
||||||
|
matcher = on_shell_command("cmd")
|
||||||
|
|
||||||
|
# 解析失败
|
||||||
|
@matcher.handle()
|
||||||
|
async def _(foo: Annotated[None, ShellCommandArgv()]): ...
|
||||||
|
|
||||||
|
# 解析成功
|
||||||
|
@matcher.handle()
|
||||||
async def _(foo: Annotated[list[Union[str, MessageSegment]], ShellCommandArgv()]): ...
|
async def _(foo: Annotated[list[Union[str, MessageSegment]], ShellCommandArgv()]): ...
|
||||||
```
|
```
|
||||||
|
|
||||||
```python {4}
|
```python {4}
|
||||||
from typing import Union
|
from typing import Union
|
||||||
from nonebot.params import ShellCommandArgs
|
from nonebot import on_shell_command
|
||||||
|
from nonebot.params import ShellCommandArgv
|
||||||
|
|
||||||
|
matcher = on_shell_command("cmd")
|
||||||
|
|
||||||
|
# 解析失败
|
||||||
|
@matcher.handle()
|
||||||
|
async def _(foo: None = ShellCommandArgv()): ...
|
||||||
|
|
||||||
|
# 解析成功
|
||||||
|
@matcher.handle()
|
||||||
async def _(foo: list[Union[str, MessageSegment]] = ShellCommandArgv()): ...
|
async def _(foo: list[Union[str, MessageSegment]] = ShellCommandArgv()): ...
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -886,7 +922,7 @@ async def _(foo: list[Union[str, MessageSegment]] = ShellCommandArgv()): ...
|
|||||||
获取 shell 命令解析后的参数 Namespace,支持 MessageSegment 富文本(如:图片)。
|
获取 shell 命令解析后的参数 Namespace,支持 MessageSegment 富文本(如:图片)。
|
||||||
|
|
||||||
:::tip 提示
|
:::tip 提示
|
||||||
如果参数解析成功,则为 parser 返回的 Namespace;如果参数解析失败,则为 [`ParserExit`](../api/exception.md#ParserExit) 异常,并携带错误码与错误信息。通过重载机制即可处理两种不同的情况。
|
如果参数解析成功,则为 parser 返回的 Namespace;如果参数解析失败,则为 [`ParserExit`](../api/exception.md#ParserExit) 异常,并携带错误码与错误信息。在前置词法解析失败时,返回值也为 [`ParserExit`](../api/exception.md#ParserExit) 异常。通过重载机制即可处理两种不同的情况。
|
||||||
|
|
||||||
由于 `ArgumentParser` 在解析到 `--help` 参数时也会抛出异常,这种情况下错误码为 `0` 且错误信息即为帮助信息。
|
由于 `ArgumentParser` 在解析到 `--help` 参数时也会抛出异常,这种情况下错误码为 `0` 且错误信息即为帮助信息。
|
||||||
:::
|
:::
|
||||||
|
Loading…
x
Reference in New Issue
Block a user