🐛 fix(playbook): import Optional for cli compatibility

restore the missing typing.Optional import in scripts/playbook.py
so older python runtimes can import the CLI module successfully.

add a regression test for typing annotation imports and register it
in the tests README.
This commit is contained in:
csh 2026-05-19 10:08:02 +08:00
parent 63e24bfe54
commit c0729c7933
3 changed files with 34 additions and 0 deletions

View File

@ -6,6 +6,7 @@ from pathlib import Path
from shutil import copy2, copytree, rmtree, which from shutil import copy2, copytree, rmtree, which
import subprocess import subprocess
import importlib.util import importlib.util
from typing import Optional
try: try:
import tomllib import tomllib

View File

@ -14,6 +14,7 @@ tests/
├── test_firstparty_skills_quality.py # first-party skills 元数据与结构质量测试 ├── test_firstparty_skills_quality.py # first-party skills 元数据与结构质量测试
├── test_gitattributes_modes.py # gitattr_mode 行为测试 ├── test_gitattributes_modes.py # gitattr_mode 行为测试
├── test_no_backup_flags.py # no_backup 行为测试 ├── test_no_backup_flags.py # no_backup 行为测试
├── test_playbook_typing_imports.py # playbook.py typing 导入兼容性测试
├── test_sync_directory_actions.py # sync_memory_bank/sync_prompts 行为测试 ├── test_sync_directory_actions.py # sync_memory_bank/sync_prompts 行为测试
├── test_vendor_snapshot_templates.py # vendor 快照模板完整性测试 ├── test_vendor_snapshot_templates.py # vendor 快照模板完整性测试
├── test_main_loop_cli.py # main_loop CLI 测试 ├── test_main_loop_cli.py # main_loop CLI 测试

View File

@ -0,0 +1,32 @@
import ast
import unittest
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
PLAYBOOK_SCRIPT = ROOT / "scripts" / "playbook.py"
class PlaybookTypingImportTests(unittest.TestCase):
def test_optional_annotation_names_are_imported(self):
tree = ast.parse(PLAYBOOK_SCRIPT.read_text(encoding="utf-8"))
imported_names: set[str] = set()
referenced_names: set[str] = set()
for node in ast.walk(tree):
if isinstance(node, ast.Import):
for alias in node.names:
imported_names.add(alias.asname or alias.name.split(".")[0])
elif isinstance(node, ast.ImportFrom):
for alias in node.names:
imported_names.add(alias.asname or alias.name)
elif isinstance(node, ast.Name):
referenced_names.add(node.id)
if "Optional" in referenced_names:
self.assertIn("Optional", imported_names)
if __name__ == "__main__":
unittest.main()