Skip to content

Commit

Permalink
🍻 sync
Browse files Browse the repository at this point in the history
  • Loading branch information
RF-Tar-Railt committed Mar 7, 2024
1 parent 4b9d475 commit d8d1fc5
Show file tree
Hide file tree
Showing 35 changed files with 904 additions and 441 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -127,4 +127,5 @@ dmypy.json

# Pyre type checker
.pyre/
.pdm-python
.pdm-python
.idea/
130 changes: 129 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,133 @@
# 更新日志

## Alconna 1.8.4

### 新增

- `command_manager.update` 上下文方法,用于修改 Alconna 对象后更新与其绑定的其他组件

```python
from arclet.alconna import Args, Alconna, Option, command_manager

alc = Alconna("test")

with command_manager.update(alc):
alc.prefixes = ["!"]
alc.add(Option("foo", Args["bar", int]))
```


## Alconna 1.8.3

### 修复

- 修复 `shortcut.wrapper` 的处理逻辑

## Alconna 1.8.2

### 修复

- 修复 `manager.get_shortcuts` 的错误

## Alconna 1.8.1

### 破坏性改动

- 删除 `ContextVal` 表达式

### 新增

- `Namespace``CommandMeta` 新增 `context_style` 属性,用于指定命令插值的格式,不填入则默认不启用插值:
```python
from dataclasses import dataclass
from arclet.alconna import Alconna, Args, CommandMeta

alc = Alconna("test", Args["foo", str], meta=CommandMeta(context_style="bracket"))

@dataclass
class User:
id: str

@dataclass
class Session:
user: User

arp = alc.parse(
"test {session.user.id}",
{"session": Session(user=User(id="123"))}
)
assert arp.query[str]("foo") == "123"
```

### 改进

- 命令插值的结果现在受类型约束

## Alconna 1.8.0

**此版本为长期支持版本 (LTS),同时为 v1.x 与 v2.0 之间的过渡版本**

### 破坏性改动

> 用户侧

- `Args.__init__` 不再接受 `**kwargs` 参数
- `Alconna.parse` 不再接受 `duplication` 参数;请直接使用 `Duplication(Arparma)`
- `fuzzy_threshold` 参数移至 `Namespace`

> 开发侧

- `NEPattern` 依赖升级至 0.6.x
- 移除兼容名称 `Arpamar``DataCollectionContainer`

### 新增

- `Alconna.parse` 新增 `ctx: dict[str, Any]` 参数,用于传入上下文.
1. 用户可以通过 `$argv.overrides` 参数来覆盖 Argv 的属性
- `Arparma` 新增 `context` 参数,与 `Alconna.parse``ctx` 参数对应
1. 当触发快捷指令后,用户可以通过 `$shortcut.trigger`, `$shortcut.args`, `$shortcut.rest` 来获取快捷指令的信息
- 新增 `ContextVal` 表达式,可以依据用户传入的指定键从 `ctx` 中获取值
1. `ContextVal` 默认格式为 `$(KEY)`, 其中 `KEY``ctx` 中的键
2. 使用 `ContextVal(style="bracket")` 可以将 `ContextVal` 的格式改为 `{KEY}`
3. 指定键支持 eval 表达式,如 `$(session.user.id)`, `$(session.user.name[1:])`
4. `ContextVal` 支持只允许指定的键,如 `ContextVal("session", "event")`

```python
from dataclasses import dataclass
from arclet.alconna import Alconna, Args, ContextVal

alc = Alconna("test", Args["foo", ContextVal(style="bracket")])

@dataclass
class User:
id: str

@dataclass
class Session:
user: User

arp = alc.parse(
"test {session.user.id}",
{"session": Session(user=User(id="123"))}
)
assert arp.query[str]("foo") == "123"
```

### 改进

- `Subcommand` 可以设置别名了
- `Alconna` 的前缀可以在最尾端塞分隔符

### 修复

- 修复类型提示错误

## Alconna 1.7.44

### 修复

- 修复 `shortcut list` 的错误

## Alconna 1.7.43

### 改进
Expand Down Expand Up @@ -353,7 +481,7 @@

## Alconna 1.7.0

**此版本为长期支持版本 (LTS), 也是 2.0 版本前的最后一个主要版本**
**此版本为长期支持版本 (LTS)**

### 破坏性改动

Expand Down
2 changes: 1 addition & 1 deletion commander/__main__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from arclet.alconna import Alconna, command_manager, Args
from arclet.alconna import Alconna, Args, command_manager
from commander import Commands

command = Commands()
Expand Down
10 changes: 6 additions & 4 deletions commander/commander.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
from arclet.alconna import Alconna, Arparma
from arclet.alconna.core import ArparmaExecutor
from tarina import is_awaitable
from dataclasses import dataclass, field
from typing import TypeVar, Tuple, Callable, Any, Optional
from typing import Any, Callable, Optional, Tuple, TypeVar
from weakref import WeakKeyDictionary

from tarina import is_awaitable

from arclet.alconna import Alconna, Arparma
from arclet.alconna.core import ArparmaExecutor

TCall = TypeVar("TCall", bound=Callable)


Expand Down
72 changes: 50 additions & 22 deletions devtool.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,35 @@
from __future__ import annotations

from collections import namedtuple
from typing import Any
import traceback
from collections import namedtuple
from typing import Any, Literal

from arclet.alconna._internal._analyser import Analyser, default_compiler
from arclet.alconna.argv import Argv
from arclet.alconna._internal._handlers import analyse_args as ala, analyse_header as alh, analyse_option as alo
from arclet.alconna._internal._handlers import analyse_args as ala
from arclet.alconna._internal._handlers import analyse_header as alh
from arclet.alconna._internal._handlers import analyse_option as alo
from arclet.alconna._internal._header import Header
from arclet.alconna.typing import DataCollection
from arclet.alconna.base import Option, Subcommand
from arclet.alconna.args import Args
from arclet.alconna.config import config
from arclet.alconna.argv import Argv
from arclet.alconna.base import Option, Subcommand
from arclet.alconna.config import Namespace
from arclet.alconna.typing import DataCollection, CommandMeta


class AnalyseError(Exception):
"""分析时发生错误"""


dev_space = Namespace("devtool")


class _DummyAnalyser(Analyser):
filter_out = []

class _DummyALC:
options = []
meta = namedtuple("Meta", ["keep_crlf", "fuzzy_match", "raise_exception"])(False, False, True)
namespace_config = config.default_namespace
namespace_config = dev_space

def __new__(cls, *args, **kwargs):
cls.command = cls._DummyALC() # type: ignore
Expand All @@ -33,9 +38,17 @@ def __new__(cls, *args, **kwargs):
return super().__new__(cls)


def analyse_args(args: Args, command: list[str | Any], raise_exception: bool = True):
argv = Argv(config.default_namespace, message_cache=False, filter_crlf=True)
def analyse_args(
args: Args,
command: list[str | Any],
raise_exception: bool = True,
context_style: Literal["bracket", "parentheses"] | None = None,
**kwargs
):
meta = CommandMeta(keep_crlf=False, fuzzy_match=False, raise_exception=raise_exception, context_style=context_style)
argv = Argv(meta, dev_space)
try:
argv.enter(kwargs)
argv.build(["test"] + command)
argv.next()
return ala(argv, args)
Expand All @@ -51,16 +64,15 @@ def analyse_header(
command: DataCollection[str | Any],
sep: str = " ",
compact: bool = False,
raise_exception: bool = True
raise_exception: bool = True,
context_style: Literal["bracket", "parentheses"] | None = None,
**kwargs
):
argv = Argv(
config.default_namespace,
message_cache=False,
filter_crlf=True,
separators=(sep, )
)
meta = CommandMeta(keep_crlf=False, fuzzy_match=False, raise_exception=raise_exception, context_style=context_style)
argv = Argv(meta, dev_space, separators=(sep,))
command_header = Header.generate(command_name, headers, compact=compact)
try:
argv.enter(kwargs)
argv.build(command)
return alh(command_header, argv)
except Exception as e:
Expand All @@ -69,8 +81,15 @@ def analyse_header(
return


def analyse_option(option: Option, command: DataCollection[str | Any], raise_exception: bool = True):
argv = Argv(config.default_namespace, message_cache=False, filter_crlf=True)
def analyse_option(
option: Option,
command: DataCollection[str | Any],
raise_exception: bool = True,
context_style: Literal["bracket", "parentheses"] | None = None,
**kwargs
):
meta = CommandMeta(keep_crlf=False, fuzzy_match=False, raise_exception=raise_exception, context_style=context_style)
argv = Argv(meta, dev_space)
_analyser = _DummyAnalyser.__new__(_DummyAnalyser)
_analyser.reset()
_analyser.command.separators = (" ",)
Expand All @@ -79,6 +98,7 @@ def analyse_option(option: Option, command: DataCollection[str | Any], raise_exc
default_compiler(_analyser, argv.param_ids)
_analyser.command.options.clear()
try:
argv.enter(kwargs)
argv.build(command)
alo(_analyser, argv, option)
return _analyser.options_result[option.dest]
Expand All @@ -88,16 +108,24 @@ def analyse_option(option: Option, command: DataCollection[str | Any], raise_exc
return


def analyse_subcommand(subcommand: Subcommand, command: DataCollection[str | Any], raise_exception: bool = True):
argv = Argv(config.default_namespace, message_cache=False, filter_crlf=True)
def analyse_subcommand(
subcommand: Subcommand,
command: DataCollection[str | Any],
raise_exception: bool = True,
context_style: Literal["bracket", "parentheses"] | None = None,
**kwargs
):
meta = CommandMeta(keep_crlf=False, fuzzy_match=False, raise_exception=raise_exception, context_style=context_style)
argv = Argv(meta, dev_space)
_analyser = _DummyAnalyser.__new__(_DummyAnalyser)
_analyser.reset()
_analyser.command.separators = (" ", )
_analyser.command.separators = (" ",)
_analyser.need_main_args = False
_analyser.command.options.append(subcommand)
default_compiler(_analyser, argv.param_ids)
_analyser.command.options.clear()
try:
argv.enter(kwargs)
argv.build(command)
return _analyser.compile_params[subcommand.name].process(argv).result() # type: ignore
except Exception as e:
Expand Down
6 changes: 3 additions & 3 deletions entry_test.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from tests.analyser_test import *
from tests.args_test import *
from tests.base_test import *
from tests.util_test import *
from tests.core_test import *
from tests.components_test import *
from tests.config_test import *
from tests.analyser_test import *
from tests.core_test import *
from tests.util_test import *

if __name__ == '__main__':
import pytest
Expand Down
3 changes: 2 additions & 1 deletion exam1.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from arclet.alconna import Alconna, Option, CommandMeta, Args, CompSession, Arg, OptionResult
from tarina import lang

from arclet.alconna import Alconna, Arg, Args, CommandMeta, CompSession, Option, OptionResult

lang.set("completion", "node", "")
lang.set("completion", "prompt_select", "")

Expand Down
28 changes: 22 additions & 6 deletions exam3.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,31 @@
from typing_extensions import ParamSpec, Self
from typing import Callable, TypeVar, Any
from __future__ import annotations

from typing import Any, Callable, Literal, TypeVar, overload
from typing_extensions import Concatenate, ParamSpec, Self

T = TypeVar("T")
R = TypeVar("R")
P = ParamSpec("P")


def deco(fn: Callable[P, T]) -> Callable[[Callable[[Any, T], R]], Callable[P, R]]:
def wrapper(func: Callable[[Any, T], R]) -> Callable[P, R]:
@overload
def deco(fn: Callable[P, T]) -> Callable[[Callable[[T], R]], Callable[P, R]]: ...


@overload
def deco(
fn: Callable[P, T], is_method: Literal[True]
) -> Callable[[Callable[[Any, T], R]], Callable[Concatenate[Any, P], R]]: ...


def deco( # type: ignore
fn: Callable[P, T], is_method: bool = False
) -> Callable[[Callable[[T], R] | Callable[[Any, T], R]], Callable[P, R] | Callable[Concatenate[Any, P], R]]:
def wrapper(func: Callable[[T], R] | Callable[[Any, T], R]) -> Callable[P, R] | Callable[Concatenate[Any, P], R]:
def inner(*args: P.args, **kwargs: P.kwargs):
return func(args[0], fn(*args[1:], **kwargs)) # type: ignore
if is_method:
return func(args[0], fn(*args[1:], **kwargs)) # type: ignore
return func(fn(*args, **kwargs)) # type: ignore

return inner

Expand All @@ -25,7 +41,7 @@ class B:
def foo(self, num: int):
...

@deco(A)
@deco(A, is_method=True)
def add(self, args: A) -> Self:
print(args.num)
return self
Expand Down
Loading

0 comments on commit d8d1fc5

Please sign in to comment.