drinkzen-admin-cli 0.3.0__tar.gz → 0.3.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {drinkzen_admin_cli-0.3.0 → drinkzen_admin_cli-0.3.3}/PKG-INFO +4 -1
- {drinkzen_admin_cli-0.3.0 → drinkzen_admin_cli-0.3.3}/README.md +3 -0
- {drinkzen_admin_cli-0.3.0 → drinkzen_admin_cli-0.3.3}/drinkzen_admin/cli.py +18 -0
- {drinkzen_admin_cli-0.3.0 → drinkzen_admin_cli-0.3.3}/drinkzen_admin/skill.py +4 -2
- {drinkzen_admin_cli-0.3.0 → drinkzen_admin_cli-0.3.3}/drinkzen_admin_cli.egg-info/PKG-INFO +4 -1
- {drinkzen_admin_cli-0.3.0 → drinkzen_admin_cli-0.3.3}/drinkzen_admin_cli.egg-info/SOURCES.txt +1 -0
- {drinkzen_admin_cli-0.3.0 → drinkzen_admin_cli-0.3.3}/pyproject.toml +1 -1
- drinkzen_admin_cli-0.3.3/tests/test_skill.py +26 -0
- {drinkzen_admin_cli-0.3.0 → drinkzen_admin_cli-0.3.3}/tests/test_standalone_cli.py +28 -0
- {drinkzen_admin_cli-0.3.0 → drinkzen_admin_cli-0.3.3}/drinkzen_admin/__init__.py +0 -0
- {drinkzen_admin_cli-0.3.0 → drinkzen_admin_cli-0.3.3}/drinkzen_admin/client.py +0 -0
- {drinkzen_admin_cli-0.3.0 → drinkzen_admin_cli-0.3.3}/drinkzen_admin/config.py +0 -0
- {drinkzen_admin_cli-0.3.0 → drinkzen_admin_cli-0.3.3}/drinkzen_admin/formatting.py +0 -0
- {drinkzen_admin_cli-0.3.0 → drinkzen_admin_cli-0.3.3}/drinkzen_admin/menu_options.py +0 -0
- {drinkzen_admin_cli-0.3.0 → drinkzen_admin_cli-0.3.3}/drinkzen_admin_cli.egg-info/dependency_links.txt +0 -0
- {drinkzen_admin_cli-0.3.0 → drinkzen_admin_cli-0.3.3}/drinkzen_admin_cli.egg-info/entry_points.txt +0 -0
- {drinkzen_admin_cli-0.3.0 → drinkzen_admin_cli-0.3.3}/drinkzen_admin_cli.egg-info/top_level.txt +0 -0
- {drinkzen_admin_cli-0.3.0 → drinkzen_admin_cli-0.3.3}/setup.cfg +0 -0
- {drinkzen_admin_cli-0.3.0 → drinkzen_admin_cli-0.3.3}/tests/test_config.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: drinkzen-admin-cli
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.3
|
|
4
4
|
Summary: Standalone CLI client for DrinkZen Admin operations
|
|
5
5
|
Author: DrinkZen Team
|
|
6
6
|
License: MIT
|
|
@@ -156,6 +156,9 @@ drinkzen-admin brand update 霸王茶姬 --name "霸王茶姬 CHAGEE" --alias "C
|
|
|
156
156
|
|
|
157
157
|
# 上传品牌 Logo 并标注数据置信度
|
|
158
158
|
drinkzen-admin brand set-logo 霸王茶姬 ./logo.png --confidence verified --source-name "官方小程序"
|
|
159
|
+
|
|
160
|
+
# 只读核对数据库 Logo 引用与 COS 文件,识别缺失引用与孤儿对象
|
|
161
|
+
drinkzen-admin brand audit-logos --json
|
|
159
162
|
```
|
|
160
163
|
|
|
161
164
|
### 2. 菜单模板管理 (`menu-template`)
|
|
@@ -134,6 +134,9 @@ drinkzen-admin brand update 霸王茶姬 --name "霸王茶姬 CHAGEE" --alias "C
|
|
|
134
134
|
|
|
135
135
|
# 上传品牌 Logo 并标注数据置信度
|
|
136
136
|
drinkzen-admin brand set-logo 霸王茶姬 ./logo.png --confidence verified --source-name "官方小程序"
|
|
137
|
+
|
|
138
|
+
# 只读核对数据库 Logo 引用与 COS 文件,识别缺失引用与孤儿对象
|
|
139
|
+
drinkzen-admin brand audit-logos --json
|
|
137
140
|
```
|
|
138
141
|
|
|
139
142
|
### 2. 菜单模板管理 (`menu-template`)
|
|
@@ -63,6 +63,16 @@ def cmd_brand_show(
|
|
|
63
63
|
return 0
|
|
64
64
|
|
|
65
65
|
|
|
66
|
+
def cmd_brand_audit_logos(client: AdminCLIClient, is_json: bool = False) -> int:
|
|
67
|
+
"""Print the API's read-only COS/database logo consistency audit."""
|
|
68
|
+
status, data = client.request("GET", "/api/admin/brands/logo-audit")
|
|
69
|
+
if status != 200:
|
|
70
|
+
print(format_cli_output({"error": data}, is_json))
|
|
71
|
+
return 1
|
|
72
|
+
print(format_cli_output(data, is_json))
|
|
73
|
+
return 0
|
|
74
|
+
|
|
75
|
+
|
|
66
76
|
def cmd_brand_update(
|
|
67
77
|
client: AdminCLIClient,
|
|
68
78
|
brand_id_or_name: str,
|
|
@@ -429,6 +439,12 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
429
439
|
b_show = brand_sub.add_parser("show", help="Show brand details", parents=[common_parser])
|
|
430
440
|
b_show.add_argument("brand", help="Brand ID or name")
|
|
431
441
|
|
|
442
|
+
brand_sub.add_parser(
|
|
443
|
+
"audit-logos",
|
|
444
|
+
help="Read-only audit of brand Logo references against object storage",
|
|
445
|
+
parents=[common_parser],
|
|
446
|
+
)
|
|
447
|
+
|
|
432
448
|
b_update = brand_sub.add_parser("update", help="Update brand information", parents=[common_parser])
|
|
433
449
|
b_update.add_argument("brand", help="Brand ID or name")
|
|
434
450
|
b_update.add_argument("--name", default=None, help="New brand name")
|
|
@@ -515,6 +531,8 @@ def main(args: list[str] | None = None) -> int:
|
|
|
515
531
|
return cmd_brand_list(client, search=parsed.search, active_only=parsed.active_only, is_json=is_json)
|
|
516
532
|
if parsed.brand_action == "show":
|
|
517
533
|
return cmd_brand_show(client, brand_id_or_name=parsed.brand, is_json=is_json)
|
|
534
|
+
if parsed.brand_action == "audit-logos":
|
|
535
|
+
return cmd_brand_audit_logos(client, is_json=is_json)
|
|
518
536
|
if parsed.brand_action == "update":
|
|
519
537
|
return cmd_brand_update(
|
|
520
538
|
client,
|
|
@@ -6,7 +6,8 @@ import urllib.request
|
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
|
|
8
8
|
SKILL_NAME = "drinkzen-admin"
|
|
9
|
-
SKILL_URL = "https://
|
|
9
|
+
SKILL_URL = "https://drinkzen.cn/skills/drinkzen-admin/SKILL.md"
|
|
10
|
+
SKILL_USER_AGENT = "DrinkZenAdminCLI/1.0 (+https://drinkzen.cn)"
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
def skill_path(scope: str = "project", project_dir: str | None = None) -> Path:
|
|
@@ -27,7 +28,8 @@ def install_skill(
|
|
|
27
28
|
if destination.exists() and not force:
|
|
28
29
|
raise FileExistsError(f"Skill already exists: {destination}. Use --force to replace it.")
|
|
29
30
|
destination.parent.mkdir(parents=True, exist_ok=True)
|
|
30
|
-
|
|
31
|
+
request = urllib.request.Request(url, headers={"User-Agent": SKILL_USER_AGENT})
|
|
32
|
+
with urllib.request.urlopen(request, timeout=20) as response:
|
|
31
33
|
content = response.read()
|
|
32
34
|
if not content:
|
|
33
35
|
raise RuntimeError("Downloaded Skill is empty")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: drinkzen-admin-cli
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.3
|
|
4
4
|
Summary: Standalone CLI client for DrinkZen Admin operations
|
|
5
5
|
Author: DrinkZen Team
|
|
6
6
|
License: MIT
|
|
@@ -156,6 +156,9 @@ drinkzen-admin brand update 霸王茶姬 --name "霸王茶姬 CHAGEE" --alias "C
|
|
|
156
156
|
|
|
157
157
|
# 上传品牌 Logo 并标注数据置信度
|
|
158
158
|
drinkzen-admin brand set-logo 霸王茶姬 ./logo.png --confidence verified --source-name "官方小程序"
|
|
159
|
+
|
|
160
|
+
# 只读核对数据库 Logo 引用与 COS 文件,识别缺失引用与孤儿对象
|
|
161
|
+
drinkzen-admin brand audit-logos --json
|
|
159
162
|
```
|
|
160
163
|
|
|
161
164
|
### 2. 菜单模板管理 (`menu-template`)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from tempfile import TemporaryDirectory
|
|
3
|
+
from unittest.mock import patch
|
|
4
|
+
|
|
5
|
+
from drinkzen_admin.skill import SKILL_USER_AGENT, install_skill
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class SkillResponse:
|
|
9
|
+
def __enter__(self) -> "SkillResponse":
|
|
10
|
+
return self
|
|
11
|
+
|
|
12
|
+
def __exit__(self, exc_type: object, exc_value: object, traceback: object) -> None:
|
|
13
|
+
return None
|
|
14
|
+
|
|
15
|
+
def read(self) -> bytes:
|
|
16
|
+
return b"---\nname: drinkzen-admin\n---\n"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def test_install_skill_identifies_the_cli_request() -> None:
|
|
20
|
+
with TemporaryDirectory() as temp_dir:
|
|
21
|
+
with patch("urllib.request.urlopen", return_value=SkillResponse()) as urlopen:
|
|
22
|
+
destination = install_skill(project_dir=temp_dir)
|
|
23
|
+
|
|
24
|
+
request = urlopen.call_args.args[0]
|
|
25
|
+
assert request.get_header("User-agent") == SKILL_USER_AGENT
|
|
26
|
+
assert Path(destination).read_text(encoding="utf-8").startswith("---")
|
|
@@ -71,6 +71,34 @@ class TestStandaloneCLI(unittest.TestCase):
|
|
|
71
71
|
self.assertTrue(output.get("dry_run"))
|
|
72
72
|
self.assertEqual(output["proposed"]["name"], "新名称")
|
|
73
73
|
|
|
74
|
+
@patch("drinkzen_admin.cli.AdminCLIClient")
|
|
75
|
+
def test_brand_audit_logos_command(self, mock_client_cls):
|
|
76
|
+
mock_client = MagicMock()
|
|
77
|
+
mock_client.request.return_value = (
|
|
78
|
+
200,
|
|
79
|
+
{
|
|
80
|
+
"backend": "CosObjectStorage",
|
|
81
|
+
"total_brands": 14,
|
|
82
|
+
"referenced_logo_count": 9,
|
|
83
|
+
"missing_referenced_objects": [],
|
|
84
|
+
"recoverable_unlinked_objects": [],
|
|
85
|
+
"orphan_object_keys": ["brands/old/logo.png"],
|
|
86
|
+
},
|
|
87
|
+
)
|
|
88
|
+
mock_client_cls.return_value = mock_client
|
|
89
|
+
|
|
90
|
+
buf = io.StringIO()
|
|
91
|
+
with patch("sys.argv", ["drinkzen-admin", "brand", "audit-logos", "--json"]):
|
|
92
|
+
with redirect_stdout(buf):
|
|
93
|
+
exit_code = main()
|
|
94
|
+
|
|
95
|
+
self.assertEqual(exit_code, 0)
|
|
96
|
+
output = json.loads(buf.getvalue())
|
|
97
|
+
self.assertEqual(output["referenced_logo_count"], 9)
|
|
98
|
+
mock_client.request.assert_called_once_with(
|
|
99
|
+
"GET", "/api/admin/brands/logo-audit"
|
|
100
|
+
)
|
|
101
|
+
|
|
74
102
|
def test_menu_template_validate_command(self):
|
|
75
103
|
valid_template = json.dumps({
|
|
76
104
|
"optionGroups": [
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{drinkzen_admin_cli-0.3.0 → drinkzen_admin_cli-0.3.3}/drinkzen_admin_cli.egg-info/entry_points.txt
RENAMED
|
File without changes
|
{drinkzen_admin_cli-0.3.0 → drinkzen_admin_cli-0.3.3}/drinkzen_admin_cli.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|