pyquipu-cli 0.3.2__tar.gz → 0.4.0__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.
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/PKG-INFO +5 -5
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/pyproject.toml +4 -4
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/src/quipu/cli/commands/axon.py +2 -4
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/src/quipu/cli/commands/cache.py +1 -1
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/src/quipu/cli/commands/export.py +11 -11
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/src/quipu/cli/commands/helpers.py +6 -8
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/src/quipu/cli/commands/navigation.py +2 -2
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/src/quipu/cli/commands/query.py +7 -9
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/src/quipu/cli/commands/remote.py +6 -6
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/src/quipu/cli/commands/run.py +7 -10
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/src/quipu/cli/commands/show.py +3 -3
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/src/quipu/cli/commands/workspace.py +2 -2
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/src/quipu/cli/main.py +2 -5
- pyquipu_cli-0.4.0/src/quipu/cli/main.stitcher.yaml +2 -0
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/src/quipu/cli/tui.py +10 -10
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/src/quipu/cli/ui_utils.py +2 -4
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/src/quipu/cli/view_model.py +11 -12
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/stitcher.lock +61 -52
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/tests/integration/test_navigation_commands.py +2 -2
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/tests/integration/test_workspace_commands.py +3 -2
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/tests/unit/test_view_model.py +13 -14
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/.gitignore +0 -0
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/src/quipu/__init__.py +0 -0
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/src/quipu/cli/commands/__init__.py +0 -0
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/src/quipu/cli/commands/cache.stitcher.yaml +0 -0
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/src/quipu/cli/commands/export.stitcher.yaml +0 -0
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/src/quipu/cli/commands/helpers.stitcher.yaml +0 -0
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/src/quipu/cli/commands/query.stitcher.yaml +0 -0
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/src/quipu/cli/commands/show.stitcher.yaml +0 -0
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/src/quipu/cli/commands/ui.py +1 -1
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/src/quipu/cli/config.py +0 -0
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/src/quipu/cli/config.stitcher.yaml +0 -0
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/src/quipu/cli/logger_config.py +0 -0
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/src/quipu/cli/logger_config.stitcher.yaml +0 -0
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/src/quipu/cli/rendering.py +0 -0
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/src/quipu/cli/rendering.stitcher.yaml +0 -0
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/src/quipu/cli/tui.css +0 -0
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/src/quipu/cli/tui.stitcher.yaml +0 -0
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/src/quipu/cli/ui_utils.stitcher.yaml +0 -0
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/src/quipu/cli/view_model.stitcher.yaml +0 -0
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/tests/integration/conftest.py +0 -0
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/tests/integration/test_cache_commands.py +0 -0
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/tests/integration/test_cache_commands.stitcher.yaml +0 -0
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/tests/integration/test_cli_interaction.py +1 -1
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/tests/integration/test_cli_interaction.stitcher.yaml +0 -0
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/tests/integration/test_export_command.py +0 -0
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/tests/integration/test_export_command.stitcher.yaml +0 -0
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/tests/integration/test_query_commands.py +1 -1
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/tests/integration/test_query_commands.stitcher.yaml +0 -0
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/tests/integration/test_unfriendly_paths.py +0 -0
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/tests/integration/test_unfriendly_paths.stitcher.yaml +0 -0
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/tests/unit/test_tui_logic.py +0 -0
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/tests/unit/test_tui_logic.stitcher.yaml +0 -0
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/tests/unit/test_tui_reachability.py +0 -0
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/tests/unit/test_tui_reachability.stitcher.yaml +0 -0
- {pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/tests/unit/test_view_model.stitcher.yaml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: pyquipu-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: The command-line interface for Quipu.
|
|
5
5
|
Project-URL: Homepage, https://github.com/quipu-dev/Quipu
|
|
6
6
|
Project-URL: Repository, https://github.com/quipu-dev/Quipu
|
|
@@ -21,10 +21,10 @@ Classifier: Topic :: Text Processing
|
|
|
21
21
|
Classifier: Typing :: Typed
|
|
22
22
|
Requires-Python: >=3.10
|
|
23
23
|
Requires-Dist: click>=8.1.0
|
|
24
|
-
Requires-Dist: pyquipu-application~=0.
|
|
24
|
+
Requires-Dist: pyquipu-application~=0.4.0
|
|
25
25
|
Requires-Dist: pyquipu-common~=0.2.0
|
|
26
|
-
Requires-Dist: pyquipu-engine~=0.
|
|
26
|
+
Requires-Dist: pyquipu-engine~=0.4.0
|
|
27
27
|
Requires-Dist: pyquipu-runtime~=0.3.0
|
|
28
|
-
Requires-Dist: pyquipu-spec~=0.
|
|
28
|
+
Requires-Dist: pyquipu-spec~=0.2.0
|
|
29
29
|
Requires-Dist: textual>=0.58.0
|
|
30
30
|
Requires-Dist: typer>=0.9.0
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pyquipu-cli"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.4.0"
|
|
8
8
|
authors = [{ name="doucx", email="doucxldh@gmail.com" }]
|
|
9
9
|
description = "The command-line interface for Quipu."
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -25,11 +25,11 @@ classifiers = [
|
|
|
25
25
|
keywords = ["quipu", "devops", "cli", "tui", "git", "history"]
|
|
26
26
|
|
|
27
27
|
dependencies = [
|
|
28
|
-
"pyquipu-spec ~= 0.
|
|
29
|
-
"pyquipu-engine ~= 0.
|
|
28
|
+
"pyquipu-spec ~= 0.2.0",
|
|
29
|
+
"pyquipu-engine ~= 0.4.0",
|
|
30
30
|
"pyquipu-runtime ~= 0.3.0",
|
|
31
31
|
"pyquipu-common ~= 0.2.0",
|
|
32
|
-
"pyquipu-application ~= 0.
|
|
32
|
+
"pyquipu-application ~= 0.4.0",
|
|
33
33
|
"typer >= 0.9.0",
|
|
34
34
|
"textual >= 0.58.0",
|
|
35
35
|
"click >= 8.1.0",
|
|
@@ -2,7 +2,7 @@ import inspect
|
|
|
2
2
|
import logging
|
|
3
3
|
import sys
|
|
4
4
|
from pathlib import Path
|
|
5
|
-
from typing import Annotated
|
|
5
|
+
from typing import Annotated
|
|
6
6
|
|
|
7
7
|
import typer
|
|
8
8
|
from needle.pointer import L
|
|
@@ -19,9 +19,7 @@ def register(app: typer.Typer):
|
|
|
19
19
|
@app.command(name="axon", help="无状态执行 Plan 文件,绕过 Quipu 引擎。")
|
|
20
20
|
def axon_command(
|
|
21
21
|
ctx: typer.Context,
|
|
22
|
-
file: Annotated[
|
|
23
|
-
Optional[Path], typer.Argument(help="包含 Markdown 指令的文件路径。", resolve_path=True)
|
|
24
|
-
] = None,
|
|
22
|
+
file: Annotated[Path | None, typer.Argument(help="包含 Markdown 指令的文件路径。", resolve_path=True)] = None,
|
|
25
23
|
work_dir: Annotated[
|
|
26
24
|
Path,
|
|
27
25
|
typer.Option(
|
|
@@ -2,7 +2,7 @@ import logging
|
|
|
2
2
|
import re
|
|
3
3
|
import shutil
|
|
4
4
|
from pathlib import Path
|
|
5
|
-
from typing import Annotated
|
|
5
|
+
from typing import Annotated
|
|
6
6
|
|
|
7
7
|
import typer
|
|
8
8
|
import yaml
|
|
@@ -49,9 +49,9 @@ def _format_frontmatter(node: QuipuNode) -> str:
|
|
|
49
49
|
|
|
50
50
|
def _generate_navbar(
|
|
51
51
|
current_node: QuipuNode,
|
|
52
|
-
exported_hashes_set:
|
|
53
|
-
filename_map:
|
|
54
|
-
hidden_link_types:
|
|
52
|
+
exported_hashes_set: set[str],
|
|
53
|
+
filename_map: dict[str, str],
|
|
54
|
+
hidden_link_types: set[str],
|
|
55
55
|
) -> str:
|
|
56
56
|
nav_links = []
|
|
57
57
|
|
|
@@ -102,9 +102,9 @@ def _generate_file_content(
|
|
|
102
102
|
engine: Engine,
|
|
103
103
|
no_frontmatter: bool,
|
|
104
104
|
no_nav: bool,
|
|
105
|
-
exported_hashes_set:
|
|
106
|
-
filename_map:
|
|
107
|
-
hidden_link_types:
|
|
105
|
+
exported_hashes_set: set[str],
|
|
106
|
+
filename_map: dict[str, str],
|
|
107
|
+
hidden_link_types: set[str],
|
|
108
108
|
) -> str:
|
|
109
109
|
parts = []
|
|
110
110
|
if not no_frontmatter:
|
|
@@ -138,14 +138,14 @@ def register(app: typer.Typer):
|
|
|
138
138
|
output_dir: Annotated[Path, typer.Option("--output-dir", "-o", help="导出目录", resolve_path=True)] = Path(
|
|
139
139
|
"./.quipu/export"
|
|
140
140
|
),
|
|
141
|
-
limit: Annotated[
|
|
142
|
-
since: Annotated[
|
|
143
|
-
until: Annotated[
|
|
141
|
+
limit: Annotated[int | None, typer.Option("--limit", "-n", help="限制最新节点数量")] = None,
|
|
142
|
+
since: Annotated[str | None, typer.Option("--since", help="起始时间戳 (YYYY-MM-DD HH:MM)")] = None,
|
|
143
|
+
until: Annotated[str | None, typer.Option("--until", help="截止时间戳 (YYYY-MM-DD HH:MM)")] = None,
|
|
144
144
|
zip_output: Annotated[bool, typer.Option("--zip", help="压缩导出目录")] = False,
|
|
145
145
|
no_nav: Annotated[bool, typer.Option("--no-nav", help="禁用导航栏")] = False,
|
|
146
146
|
no_frontmatter: Annotated[bool, typer.Option("--no-frontmatter", help="禁用 Frontmatter")] = False,
|
|
147
147
|
hide_link_type: Annotated[
|
|
148
|
-
|
|
148
|
+
list[str] | None,
|
|
149
149
|
typer.Option(
|
|
150
150
|
"--hide-link-type", help="禁用特定类型的导航链接 (可多次使用: summary, branch, parent, child)"
|
|
151
151
|
),
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import logging
|
|
2
|
+
from collections.abc import Generator
|
|
2
3
|
from contextlib import contextmanager
|
|
3
4
|
from datetime import datetime
|
|
4
5
|
from pathlib import Path
|
|
5
|
-
from typing import Dict, Generator, List, Optional
|
|
6
6
|
|
|
7
7
|
import typer
|
|
8
|
-
from quipu.application.factory import create_engine
|
|
9
8
|
from needle.pointer import L
|
|
9
|
+
from quipu.application.factory import create_engine
|
|
10
10
|
from quipu.common.bus import bus
|
|
11
11
|
from quipu.engine.state_machine import Engine
|
|
12
12
|
from quipu.spec.models.graph import QuipuNode
|
|
@@ -28,7 +28,7 @@ def engine_context(work_dir: Path) -> Generator[Engine, None, None]:
|
|
|
28
28
|
engine.close()
|
|
29
29
|
|
|
30
30
|
|
|
31
|
-
def _find_current_node(engine: Engine, graph:
|
|
31
|
+
def _find_current_node(engine: Engine, graph: dict[str, QuipuNode]) -> QuipuNode | None:
|
|
32
32
|
current_hash = engine.git_db.get_tree_hash()
|
|
33
33
|
# 修复:直接从 graph 中通过 output_tree hash 查找
|
|
34
34
|
for node in graph.values():
|
|
@@ -46,14 +46,12 @@ def _execute_visit(ctx: typer.Context, engine: Engine, target_hash: str, msg_id:
|
|
|
46
46
|
engine.visit(target_hash)
|
|
47
47
|
bus.success(L.navigation.success.visit, short_hash=target_hash[:7])
|
|
48
48
|
except Exception as e:
|
|
49
|
-
logger.
|
|
49
|
+
logger.exception(f"导航操作失败 (目标哈希: {target_hash[:12]})")
|
|
50
50
|
bus.error(L.navigation.error.generic, error=str(e))
|
|
51
51
|
ctx.exit(1)
|
|
52
52
|
|
|
53
53
|
|
|
54
|
-
def filter_nodes(
|
|
55
|
-
nodes: List[QuipuNode], limit: Optional[int], since: Optional[str], until: Optional[str]
|
|
56
|
-
) -> List[QuipuNode]:
|
|
54
|
+
def filter_nodes(nodes: list[QuipuNode], limit: int | None, since: str | None, until: str | None) -> list[QuipuNode]:
|
|
57
55
|
filtered = nodes
|
|
58
56
|
if since:
|
|
59
57
|
try:
|
|
@@ -72,7 +70,7 @@ def filter_nodes(
|
|
|
72
70
|
return filtered
|
|
73
71
|
|
|
74
72
|
|
|
75
|
-
def filter_reachable_nodes(engine: Engine, nodes:
|
|
73
|
+
def filter_reachable_nodes(engine: Engine, nodes: list[QuipuNode]) -> list[QuipuNode]:
|
|
76
74
|
current_node = _find_current_node(engine, engine.history_graph)
|
|
77
75
|
if not current_node:
|
|
78
76
|
# 如果工作区是脏的,无法确定起点,返回所有节点
|
|
@@ -218,7 +218,7 @@ def register(app: typer.Typer):
|
|
|
218
218
|
else:
|
|
219
219
|
bus.warning(L.navigation.back.atStart)
|
|
220
220
|
except Exception as e:
|
|
221
|
-
logger.
|
|
221
|
+
logger.exception("后退操作失败")
|
|
222
222
|
bus.error(L.navigation.back.error, error=str(e))
|
|
223
223
|
ctx.exit(1)
|
|
224
224
|
|
|
@@ -235,6 +235,6 @@ def register(app: typer.Typer):
|
|
|
235
235
|
else:
|
|
236
236
|
bus.warning(L.navigation.forward.atEnd)
|
|
237
237
|
except Exception as e:
|
|
238
|
-
logger.
|
|
238
|
+
logger.exception("前进操作失败")
|
|
239
239
|
bus.error(L.navigation.forward.error, error=str(e))
|
|
240
240
|
ctx.exit(1)
|
|
@@ -2,7 +2,7 @@ import dataclasses
|
|
|
2
2
|
import json
|
|
3
3
|
from datetime import datetime
|
|
4
4
|
from pathlib import Path
|
|
5
|
-
from typing import Annotated
|
|
5
|
+
from typing import Annotated
|
|
6
6
|
|
|
7
7
|
import typer
|
|
8
8
|
from needle.pointer import L
|
|
@@ -13,7 +13,7 @@ from ..config import DEFAULT_WORK_DIR
|
|
|
13
13
|
from .helpers import engine_context, filter_nodes, filter_reachable_nodes
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
def _nodes_to_json_str(nodes:
|
|
16
|
+
def _nodes_to_json_str(nodes: list[QuipuNode]) -> str:
|
|
17
17
|
EXCLUDED_FIELDS = {"parent", "children", "content", "filename"}
|
|
18
18
|
node_list = []
|
|
19
19
|
for node in nodes:
|
|
@@ -44,9 +44,9 @@ def register(app: typer.Typer):
|
|
|
44
44
|
"--work-dir", "-w", help="操作执行的根目录(工作区)", file_okay=False, dir_okay=True, resolve_path=True
|
|
45
45
|
),
|
|
46
46
|
] = DEFAULT_WORK_DIR,
|
|
47
|
-
limit: Annotated[
|
|
48
|
-
since: Annotated[
|
|
49
|
-
until: Annotated[
|
|
47
|
+
limit: Annotated[int | None, typer.Option("--limit", "-n", help="限制显示的节点数量。")] = None,
|
|
48
|
+
since: Annotated[str | None, typer.Option("--since", help="起始时间戳 (YYYY-MM-DD HH:MM)。")] = None,
|
|
49
|
+
until: Annotated[str | None, typer.Option("--until", help="截止时间戳 (YYYY-MM-DD HH:MM)。")] = None,
|
|
50
50
|
reachable_only: Annotated[
|
|
51
51
|
bool, typer.Option("--reachable-only", help="仅显示与当前工作区状态直接相关的节点。")
|
|
52
52
|
] = False,
|
|
@@ -98,11 +98,9 @@ def register(app: typer.Typer):
|
|
|
98
98
|
def find_command(
|
|
99
99
|
ctx: typer.Context,
|
|
100
100
|
summary_regex: Annotated[
|
|
101
|
-
|
|
102
|
-
] = None,
|
|
103
|
-
node_type: Annotated[
|
|
104
|
-
Optional[str], typer.Option("--type", "-t", help="节点类型 ('plan' 或 'capture')。")
|
|
101
|
+
str | None, typer.Option("--summary", "-s", help="用于匹配节点摘要的正则表达式 (不区分大小写)。")
|
|
105
102
|
] = None,
|
|
103
|
+
node_type: Annotated[str | None, typer.Option("--type", "-t", help="节点类型 ('plan' 或 'capture')。")] = None,
|
|
106
104
|
limit: Annotated[int, typer.Option("--limit", "-n", help="返回的最大结果数量。")] = 10,
|
|
107
105
|
work_dir: Annotated[Path, typer.Option("--work-dir", "-w", help="工作区根目录。")] = DEFAULT_WORK_DIR,
|
|
108
106
|
json_output: Annotated[bool, typer.Option("--json", help="以 JSON 格式输出结果。")] = False,
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import subprocess
|
|
2
2
|
from enum import Enum
|
|
3
3
|
from pathlib import Path
|
|
4
|
-
from typing import Annotated
|
|
4
|
+
from typing import Annotated
|
|
5
5
|
|
|
6
6
|
import typer
|
|
7
|
-
from quipu.application.utils import find_git_repository_root
|
|
8
7
|
from needle.pointer import L
|
|
8
|
+
from quipu.application.utils import find_git_repository_root
|
|
9
9
|
from quipu.common.bus import bus
|
|
10
10
|
from quipu.common.identity import get_user_id_from_email
|
|
11
11
|
from quipu.engine.config import ConfigManager
|
|
@@ -35,7 +35,7 @@ def register(app: typer.Typer):
|
|
|
35
35
|
),
|
|
36
36
|
] = DEFAULT_WORK_DIR,
|
|
37
37
|
remote_option: Annotated[
|
|
38
|
-
|
|
38
|
+
str | None, typer.Option("--remote", "-r", help="Git 远程仓库的名称 (覆盖配置文件)。")
|
|
39
39
|
] = None,
|
|
40
40
|
mode: Annotated[
|
|
41
41
|
SyncMode,
|
|
@@ -85,7 +85,7 @@ def register(app: typer.Typer):
|
|
|
85
85
|
match mode:
|
|
86
86
|
case SyncMode.BIDIRECTIONAL:
|
|
87
87
|
bus.info(L.sync.run.info.pulling)
|
|
88
|
-
for target_id in sorted(
|
|
88
|
+
for target_id in sorted(target_ids_to_fetch):
|
|
89
89
|
git_db.fetch_quipu_refs(remote, target_id)
|
|
90
90
|
bus.info(L.sync.run.info.reconciling)
|
|
91
91
|
git_db.reconcile_local_with_remote(remote, final_user_id)
|
|
@@ -95,7 +95,7 @@ def register(app: typer.Typer):
|
|
|
95
95
|
|
|
96
96
|
case SyncMode.PULL_ONLY:
|
|
97
97
|
bus.info(L.sync.run.info.pulling)
|
|
98
|
-
for target_id in sorted(
|
|
98
|
+
for target_id in sorted(target_ids_to_fetch):
|
|
99
99
|
git_db.fetch_quipu_refs(remote, target_id)
|
|
100
100
|
bus.info(L.sync.run.info.reconciling)
|
|
101
101
|
git_db.reconcile_local_with_remote(remote, final_user_id)
|
|
@@ -103,7 +103,7 @@ def register(app: typer.Typer):
|
|
|
103
103
|
|
|
104
104
|
case SyncMode.PULL_PRUNE:
|
|
105
105
|
bus.info(L.sync.run.info.pullingPrune)
|
|
106
|
-
for target_id in sorted(
|
|
106
|
+
for target_id in sorted(target_ids_to_fetch):
|
|
107
107
|
git_db.fetch_quipu_refs(remote, target_id)
|
|
108
108
|
bus.info(L.sync.run.info.reconciling)
|
|
109
109
|
git_db.reconcile_local_with_remote(remote, final_user_id)
|
|
@@ -2,11 +2,11 @@ import inspect
|
|
|
2
2
|
import logging
|
|
3
3
|
import sys
|
|
4
4
|
from pathlib import Path
|
|
5
|
-
from typing import Annotated
|
|
5
|
+
from typing import Annotated
|
|
6
6
|
|
|
7
7
|
import typer
|
|
8
|
-
from quipu.application.controller import run_quipu
|
|
9
8
|
from needle.pointer import L
|
|
9
|
+
from quipu.application.controller import run_quipu
|
|
10
10
|
from quipu.common.bus import bus
|
|
11
11
|
|
|
12
12
|
from ..config import DEFAULT_ENTRY_FILE, DEFAULT_WORK_DIR
|
|
@@ -20,9 +20,7 @@ def register(app: typer.Typer):
|
|
|
20
20
|
@app.command(name="run", help="执行 Plan 文件并记录到 Quipu 历史。")
|
|
21
21
|
def run_command(
|
|
22
22
|
ctx: typer.Context,
|
|
23
|
-
file: Annotated[
|
|
24
|
-
Optional[Path], typer.Argument(help="包含 Markdown 指令的文件路径。", resolve_path=True)
|
|
25
|
-
] = None,
|
|
23
|
+
file: Annotated[Path | None, typer.Argument(help="包含 Markdown 指令的文件路径。", resolve_path=True)] = None,
|
|
26
24
|
work_dir: Annotated[
|
|
27
25
|
Path,
|
|
28
26
|
typer.Option(
|
|
@@ -75,11 +73,10 @@ def register(app: typer.Typer):
|
|
|
75
73
|
bus.error(L.common.error.fileNotFound, path=file)
|
|
76
74
|
bus.warning(L.run.error.ambiguousCommand, command=file.name)
|
|
77
75
|
ctx.exit(1)
|
|
78
|
-
if not content.strip():
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
ctx.exit(0)
|
|
76
|
+
if not content.strip() and not file:
|
|
77
|
+
bus.warning(L.run.warning.noInput, filename=DEFAULT_ENTRY_FILE.name)
|
|
78
|
+
bus.info(L.run.info.usageHint)
|
|
79
|
+
ctx.exit(0)
|
|
83
80
|
|
|
84
81
|
logger.info(f"已加载指令源: {source_desc}")
|
|
85
82
|
logger.info(f"工作区根目录: {work_dir}")
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import logging
|
|
3
3
|
from pathlib import Path
|
|
4
|
-
from typing import Annotated
|
|
4
|
+
from typing import Annotated
|
|
5
5
|
|
|
6
6
|
import typer
|
|
7
7
|
from needle.pointer import L
|
|
@@ -15,7 +15,7 @@ from .helpers import engine_context
|
|
|
15
15
|
logger = logging.getLogger(__name__)
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
def _find_target_node(graph:
|
|
18
|
+
def _find_target_node(graph: dict, hash_prefix: str):
|
|
19
19
|
matches = [
|
|
20
20
|
node
|
|
21
21
|
for node in graph.values()
|
|
@@ -48,7 +48,7 @@ def register(app: typer.Typer):
|
|
|
48
48
|
] = DEFAULT_WORK_DIR,
|
|
49
49
|
json_output: Annotated[bool, typer.Option("--json", help="以 JSON 格式将结果输出到 stdout。")] = False,
|
|
50
50
|
extract: Annotated[
|
|
51
|
-
|
|
51
|
+
list[str] | None, typer.Option("--extract", "-e", help="仅提取并显示指定文件的内容 (可多次使用)。")
|
|
52
52
|
] = None,
|
|
53
53
|
):
|
|
54
54
|
with engine_context(work_dir) as engine:
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
|
-
from typing import Annotated
|
|
2
|
+
from typing import Annotated
|
|
3
3
|
|
|
4
4
|
import typer
|
|
5
5
|
from needle.pointer import L
|
|
@@ -15,7 +15,7 @@ def register(app: typer.Typer):
|
|
|
15
15
|
@app.command(help="将当前工作区的变更创建为一个新的快照节点。")
|
|
16
16
|
def save(
|
|
17
17
|
ctx: typer.Context,
|
|
18
|
-
message: Annotated[
|
|
18
|
+
message: Annotated[str | None, typer.Argument(help="本次快照的简短描述。")] = None,
|
|
19
19
|
work_dir: Annotated[
|
|
20
20
|
Path,
|
|
21
21
|
typer.Option(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import importlib.metadata
|
|
2
2
|
import logging
|
|
3
|
-
from typing import Annotated
|
|
3
|
+
from typing import Annotated
|
|
4
4
|
|
|
5
5
|
import typer
|
|
6
6
|
from quipu.common.bus import bus
|
|
@@ -54,13 +54,10 @@ app.add_typer(cache.cache_app)
|
|
|
54
54
|
@app.callback()
|
|
55
55
|
def main(
|
|
56
56
|
version: Annotated[
|
|
57
|
-
|
|
57
|
+
bool | None,
|
|
58
58
|
typer.Option("--version", "-V", callback=version_callback, is_eager=True, help="显示版本信息并退出。"),
|
|
59
59
|
] = None,
|
|
60
60
|
):
|
|
61
|
-
"""
|
|
62
|
-
Quipu: 一个基于 Git 的、用于文件系统状态溯源与文学化操作的工具。
|
|
63
|
-
"""
|
|
64
61
|
pass
|
|
65
62
|
|
|
66
63
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from enum import Enum, auto
|
|
3
3
|
from pathlib import Path
|
|
4
|
-
from typing import
|
|
4
|
+
from typing import ClassVar
|
|
5
5
|
|
|
6
6
|
from quipu.application.factory import create_engine
|
|
7
7
|
from quipu.engine.state_machine import Engine
|
|
@@ -29,11 +29,11 @@ class ContentViewSate(Enum):
|
|
|
29
29
|
SHOWING_CONTENT = auto()
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
class QuipuUiApp(App[
|
|
32
|
+
class QuipuUiApp(App[UiResult | None]):
|
|
33
33
|
CSS_PATH = "tui.css"
|
|
34
34
|
TITLE = "Quipu History Explorer"
|
|
35
35
|
|
|
36
|
-
BINDINGS = [
|
|
36
|
+
BINDINGS: ClassVar[list[Binding]] = [
|
|
37
37
|
Binding("q", "quit", "退出"),
|
|
38
38
|
Binding("space", "checkout_node", "检出节点"),
|
|
39
39
|
Binding("enter", "checkout_node", "检出节点"),
|
|
@@ -54,12 +54,12 @@ class QuipuUiApp(App[Optional[UiResult]]):
|
|
|
54
54
|
def __init__(self, work_dir: Path, initial_raw_mode: bool = False):
|
|
55
55
|
super().__init__()
|
|
56
56
|
self.work_dir = work_dir
|
|
57
|
-
self.engine:
|
|
58
|
-
self.view_model:
|
|
57
|
+
self.engine: Engine | None = None
|
|
58
|
+
self.view_model: GraphViewModel | None = None
|
|
59
59
|
|
|
60
60
|
# --- State Machine ---
|
|
61
61
|
self.content_view_state = ContentViewSate.HIDDEN
|
|
62
|
-
self.update_timer:
|
|
62
|
+
self.update_timer: Timer | None = None
|
|
63
63
|
self.debounce_delay_seconds: float = 0.50
|
|
64
64
|
self.markdown_enabled = not initial_raw_mode
|
|
65
65
|
|
|
@@ -177,10 +177,10 @@ class QuipuUiApp(App[Optional[UiResult]]):
|
|
|
177
177
|
self._focus_current_node(table)
|
|
178
178
|
self._update_header()
|
|
179
179
|
|
|
180
|
-
def _populate_table(self, table: DataTable, nodes:
|
|
180
|
+
def _populate_table(self, table: DataTable, nodes: list[QuipuNode]):
|
|
181
181
|
assert self.view_model is not None
|
|
182
182
|
# 移除了过滤逻辑,因为 ViewModel 已经处理
|
|
183
|
-
tracks: list[
|
|
183
|
+
tracks: list[str | None] = []
|
|
184
184
|
|
|
185
185
|
for node in nodes:
|
|
186
186
|
is_reachable = self.view_model.is_reachable(node.output_tree)
|
|
@@ -279,8 +279,8 @@ class QuipuUiApp(App[Optional[UiResult]]):
|
|
|
279
279
|
# LookupError 捕获 RowKeyError 等
|
|
280
280
|
logger.warning(f"DEBUG: Row key {row_key} not found in DataTable.")
|
|
281
281
|
|
|
282
|
-
except Exception
|
|
283
|
-
logger.
|
|
282
|
+
except Exception:
|
|
283
|
+
logger.exception("DEBUG: Failed to focus current node")
|
|
284
284
|
|
|
285
285
|
def _update_loading_preview(self):
|
|
286
286
|
assert self.view_model is not None
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
from typing import List, Optional
|
|
2
|
-
|
|
3
1
|
import click
|
|
4
2
|
import typer
|
|
5
3
|
from needle.pointer import L
|
|
@@ -7,7 +5,7 @@ from quipu.common.bus import bus
|
|
|
7
5
|
from quipu.spec.exceptions import OperationCancelledError
|
|
8
6
|
|
|
9
7
|
|
|
10
|
-
def confirmation_handler_for_executor(diff_lines:
|
|
8
|
+
def confirmation_handler_for_executor(diff_lines: list[str], prompt: str) -> bool:
|
|
11
9
|
# 原始逻辑是 `char.lower() != "n"`,这相当于默认为 True
|
|
12
10
|
confirmed = prompt_for_confirmation(prompt=prompt, diff_lines=diff_lines, default=True)
|
|
13
11
|
if not confirmed:
|
|
@@ -17,7 +15,7 @@ def confirmation_handler_for_executor(diff_lines: List[str], prompt: str) -> boo
|
|
|
17
15
|
return True
|
|
18
16
|
|
|
19
17
|
|
|
20
|
-
def prompt_for_confirmation(prompt: str, diff_lines:
|
|
18
|
+
def prompt_for_confirmation(prompt: str, diff_lines: list[str] | None = None, default: bool = False) -> bool:
|
|
21
19
|
if diff_lines:
|
|
22
20
|
bus.info(L.prompt.ui.diffHeader)
|
|
23
21
|
for line in diff_lines:
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import math
|
|
2
|
-
from typing import Dict, List, Optional, Set
|
|
3
2
|
|
|
4
3
|
from quipu.spec.models.graph import QuipuNode
|
|
5
4
|
from quipu.spec.protocols.storage import HistoryReader
|
|
6
5
|
|
|
7
6
|
|
|
8
7
|
class GraphViewModel:
|
|
9
|
-
def __init__(self, reader: HistoryReader, current_output_tree_hash:
|
|
8
|
+
def __init__(self, reader: HistoryReader, current_output_tree_hash: str | None, page_size: int = 50):
|
|
10
9
|
self.reader = reader
|
|
11
10
|
self.current_output_tree_hash = current_output_tree_hash
|
|
12
11
|
self.page_size = page_size
|
|
@@ -18,10 +17,10 @@ class GraphViewModel:
|
|
|
18
17
|
|
|
19
18
|
# --- TUI 交互状态 ---
|
|
20
19
|
self.show_unreachable: bool = True
|
|
21
|
-
self.current_page_nodes:
|
|
22
|
-
self.current_selected_node:
|
|
23
|
-
self._node_by_key:
|
|
24
|
-
self.reachable_set:
|
|
20
|
+
self.current_page_nodes: list[QuipuNode] = []
|
|
21
|
+
self.current_selected_node: QuipuNode | None = None
|
|
22
|
+
self._node_by_key: dict[str, QuipuNode] = {}
|
|
23
|
+
self.reachable_set: set[str] = set()
|
|
25
24
|
|
|
26
25
|
def initialize(self):
|
|
27
26
|
self.total_nodes = self.reader.get_node_count()
|
|
@@ -58,7 +57,7 @@ class GraphViewModel:
|
|
|
58
57
|
# e.g. pos 0 -> page 1; pos 49 -> page 1; pos 50 -> page 2
|
|
59
58
|
return (position // self.page_size) + 1
|
|
60
59
|
|
|
61
|
-
def load_page(self, page_number: int) ->
|
|
60
|
+
def load_page(self, page_number: int) -> list[QuipuNode]:
|
|
62
61
|
if not (1 <= page_number <= self.total_pages):
|
|
63
62
|
self.current_page_nodes = []
|
|
64
63
|
self._node_by_key = {}
|
|
@@ -74,26 +73,26 @@ class GraphViewModel:
|
|
|
74
73
|
def toggle_unreachable(self):
|
|
75
74
|
self.show_unreachable = not self.show_unreachable
|
|
76
75
|
|
|
77
|
-
def get_nodes_to_render(self) ->
|
|
76
|
+
def get_nodes_to_render(self) -> list[QuipuNode]:
|
|
78
77
|
if self.show_unreachable:
|
|
79
78
|
return self.current_page_nodes
|
|
80
79
|
return [node for node in self.current_page_nodes if self.is_reachable(node.output_tree)]
|
|
81
80
|
|
|
82
|
-
def select_node_by_key(self, key: str) ->
|
|
81
|
+
def select_node_by_key(self, key: str) -> QuipuNode | None:
|
|
83
82
|
node = self._node_by_key.get(key)
|
|
84
83
|
self.current_selected_node = node
|
|
85
84
|
return node
|
|
86
85
|
|
|
87
|
-
def get_selected_node(self) ->
|
|
86
|
+
def get_selected_node(self) -> QuipuNode | None:
|
|
88
87
|
return self.current_selected_node
|
|
89
88
|
|
|
90
89
|
def get_public_content(self, node: QuipuNode) -> str:
|
|
91
90
|
return self.reader.get_node_content(node) or ""
|
|
92
91
|
|
|
93
|
-
def previous_page(self) ->
|
|
92
|
+
def previous_page(self) -> list[QuipuNode]:
|
|
94
93
|
return self.load_page(self.current_page - 1)
|
|
95
94
|
|
|
96
|
-
def next_page(self) ->
|
|
95
|
+
def next_page(self) -> list[QuipuNode]:
|
|
97
96
|
return self.load_page(self.current_page + 1)
|
|
98
97
|
|
|
99
98
|
def get_content_bundle(self, node: QuipuNode) -> str:
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"baseline_yaml_content_hash": "072213b865fe7346f0d15fb5dac39d87008c64d4c265f765d49a7e0a561a2b76"
|
|
26
26
|
},
|
|
27
27
|
"py://packages/pyquipu-cli/src/quipu/cli/commands/export.py#_generate_file_content": {
|
|
28
|
-
"baseline_code_signature_text": "def _generate_file_content(node: QuipuNode, engine: Engine, no_frontmatter: bool, no_nav: bool, exported_hashes_set:
|
|
29
|
-
"baseline_code_structure_hash": "
|
|
28
|
+
"baseline_code_signature_text": "def _generate_file_content(node: QuipuNode, engine: Engine, no_frontmatter: bool, no_nav: bool, exported_hashes_set: set[str], filename_map: dict[str, str], hidden_link_types: set[str]) -> str:",
|
|
29
|
+
"baseline_code_structure_hash": "c2c5c7689c763390ce6b2ee51ab34e4de40c4322e1431e541c6af738d1bce182",
|
|
30
30
|
"baseline_yaml_content_hash": "11e8b1b55093a75571b2f6321e13bd409eaf706cc11d05d7bc6f5ded73130d7b"
|
|
31
31
|
},
|
|
32
32
|
"py://packages/pyquipu-cli/src/quipu/cli/commands/export.py#_generate_filename": {
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
"baseline_yaml_content_hash": "92ba975530e3f064b4e863a873c946fd95e94b147efc977b7a7b8056b7cd54ba"
|
|
36
36
|
},
|
|
37
37
|
"py://packages/pyquipu-cli/src/quipu/cli/commands/export.py#_generate_navbar": {
|
|
38
|
-
"baseline_code_signature_text": "def _generate_navbar(current_node: QuipuNode, exported_hashes_set:
|
|
39
|
-
"baseline_code_structure_hash": "
|
|
38
|
+
"baseline_code_signature_text": "def _generate_navbar(current_node: QuipuNode, exported_hashes_set: set[str], filename_map: dict[str, str], hidden_link_types: set[str]) -> str:",
|
|
39
|
+
"baseline_code_structure_hash": "13f89fc77fd05d7a31e5732fa5a7603170ce584cfaf8800199400a68de86323c",
|
|
40
40
|
"baseline_yaml_content_hash": "12f6b2229709ef9b30084a487dbce1e73f1dc18f9104a615883b25787bca2820"
|
|
41
41
|
},
|
|
42
42
|
"py://packages/pyquipu-cli/src/quipu/cli/commands/export.py#_sanitize_summary": {
|
|
@@ -54,8 +54,8 @@
|
|
|
54
54
|
"baseline_yaml_content_hash": "ae1ff41ba75c522fa2e42291e621ada5e1b02efe729959a460edc34a4a6f1c8a"
|
|
55
55
|
},
|
|
56
56
|
"py://packages/pyquipu-cli/src/quipu/cli/commands/helpers.py#_find_current_node": {
|
|
57
|
-
"baseline_code_signature_text": "def _find_current_node(engine: Engine, graph:
|
|
58
|
-
"baseline_code_structure_hash": "
|
|
57
|
+
"baseline_code_signature_text": "def _find_current_node(engine: Engine, graph: dict[str, QuipuNode]) -> QuipuNode | None:",
|
|
58
|
+
"baseline_code_structure_hash": "f5b529ac7d1b8129b8ff1023fab9b47cca14a3bca0dfa4f7087622e6c30e325b",
|
|
59
59
|
"baseline_yaml_content_hash": "0f66d45f4d99892cd3236244bdefbfaab2652961fb15ef3b74c735aada7f4eda"
|
|
60
60
|
},
|
|
61
61
|
"py://packages/pyquipu-cli/src/quipu/cli/commands/helpers.py#engine_context": {
|
|
@@ -64,13 +64,13 @@
|
|
|
64
64
|
"baseline_yaml_content_hash": "a95bdec257bf9536a0f2b01704c7c08fdf356e43c0aec646290b1cbf0d6991aa"
|
|
65
65
|
},
|
|
66
66
|
"py://packages/pyquipu-cli/src/quipu/cli/commands/helpers.py#filter_nodes": {
|
|
67
|
-
"baseline_code_signature_text": "def filter_nodes(nodes:
|
|
68
|
-
"baseline_code_structure_hash": "
|
|
67
|
+
"baseline_code_signature_text": "def filter_nodes(nodes: list[QuipuNode], limit: int | None, since: str | None, until: str | None) -> list[QuipuNode]:",
|
|
68
|
+
"baseline_code_structure_hash": "145a7aa3efae785494476511439819a7c2bbabfa2cad8ce35515803a853b2fa6",
|
|
69
69
|
"baseline_yaml_content_hash": "79ea525d26ab251901c03f43b61d5ad30cd35953a00202e75e81456000417054"
|
|
70
70
|
},
|
|
71
71
|
"py://packages/pyquipu-cli/src/quipu/cli/commands/helpers.py#filter_reachable_nodes": {
|
|
72
|
-
"baseline_code_signature_text": "def filter_reachable_nodes(engine: Engine, nodes:
|
|
73
|
-
"baseline_code_structure_hash": "
|
|
72
|
+
"baseline_code_signature_text": "def filter_reachable_nodes(engine: Engine, nodes: list[QuipuNode]) -> list[QuipuNode]:",
|
|
73
|
+
"baseline_code_structure_hash": "7de6be7af2e8f0be6104f222dd827eeb85e99ebd51452c70ef9122f778d8ae0f",
|
|
74
74
|
"baseline_yaml_content_hash": "1ef180ac9d0dc5c26fcd9531e469fcba9f07183977b6ddde67ef4b54b3afaac9"
|
|
75
75
|
},
|
|
76
76
|
"py://packages/pyquipu-cli/src/quipu/cli/commands/navigation.py#register": {
|
|
@@ -78,8 +78,8 @@
|
|
|
78
78
|
"baseline_code_structure_hash": "32475c50cf36afaf2fb100127ea888c4b2eda4d547ed04ef114d35119f2a5d4b"
|
|
79
79
|
},
|
|
80
80
|
"py://packages/pyquipu-cli/src/quipu/cli/commands/query.py#_nodes_to_json_str": {
|
|
81
|
-
"baseline_code_signature_text": "def _nodes_to_json_str(nodes:
|
|
82
|
-
"baseline_code_structure_hash": "
|
|
81
|
+
"baseline_code_signature_text": "def _nodes_to_json_str(nodes: list[QuipuNode]) -> str:",
|
|
82
|
+
"baseline_code_structure_hash": "1afb8c1e8d73ed71d1237ff99fef1ddb976087d2647b99e3562c0294a18d8339",
|
|
83
83
|
"baseline_yaml_content_hash": "e8fd6bcc24b3c636e78d61a66c4aeb44f31548851d618950ed80afaf75d0eef3"
|
|
84
84
|
},
|
|
85
85
|
"py://packages/pyquipu-cli/src/quipu/cli/commands/query.py#register": {
|
|
@@ -99,8 +99,8 @@
|
|
|
99
99
|
"baseline_code_structure_hash": "32475c50cf36afaf2fb100127ea888c4b2eda4d547ed04ef114d35119f2a5d4b"
|
|
100
100
|
},
|
|
101
101
|
"py://packages/pyquipu-cli/src/quipu/cli/commands/show.py#_find_target_node": {
|
|
102
|
-
"baseline_code_signature_text": "def _find_target_node(graph:
|
|
103
|
-
"baseline_code_structure_hash": "
|
|
102
|
+
"baseline_code_signature_text": "def _find_target_node(graph: dict, hash_prefix: str):",
|
|
103
|
+
"baseline_code_structure_hash": "b95f1b757c251a926b96be651aa0fa712870028e7e525e57cc9d8ae7200636ae",
|
|
104
104
|
"baseline_yaml_content_hash": "807e9066a944912816641ed1d209223dde8f450e116617142a0c032a9b55360e"
|
|
105
105
|
},
|
|
106
106
|
"py://packages/pyquipu-cli/src/quipu/cli/commands/show.py#register": {
|
|
@@ -130,6 +130,15 @@
|
|
|
130
130
|
"baseline_code_structure_hash": "9f8fe4f78b0a37cb1fdcb7a71340369231210c17cf8aabd7932364e85e49558f",
|
|
131
131
|
"baseline_yaml_content_hash": "661102cbe0d8b99976a010fa18584a63efc961471bd041664f794e0c03e75c4c"
|
|
132
132
|
},
|
|
133
|
+
"py://packages/pyquipu-cli/src/quipu/cli/main.py#main": {
|
|
134
|
+
"baseline_code_signature_text": "def main(version: Annotated[bool | None, typer.Option(--version, -V, callback=version_callback, is_eager=True, help='\u663e\u793a\u7248\u672c\u4fe1\u606f\u5e76\u9000\u51fa\u3002')] = None):",
|
|
135
|
+
"baseline_code_structure_hash": "32e7711e68310146999ecb80f8efca45170cd1c73dccb108d7002b57e2e38842",
|
|
136
|
+
"baseline_yaml_content_hash": "8d9317ae2b400f1f47bf287cfbbb004adf475f941e27413c5e04b9d072d22c98"
|
|
137
|
+
},
|
|
138
|
+
"py://packages/pyquipu-cli/src/quipu/cli/main.py#version_callback": {
|
|
139
|
+
"baseline_code_signature_text": "def version_callback(value: bool):",
|
|
140
|
+
"baseline_code_structure_hash": "cddfc7cd3b2fe49aab452780ba4ab96c9c2aa7acbe75d5b89b7a7575fe8df41c"
|
|
141
|
+
},
|
|
133
142
|
"py://packages/pyquipu-cli/src/quipu/cli/rendering.py#Renderer.data": {
|
|
134
143
|
"baseline_code_signature_text": "def data(self, data_string: str) -> None:",
|
|
135
144
|
"baseline_code_structure_hash": "e24670692edbaa5b2b5efeb813dbb1f8c58794e5f10e72f7b92f5ee5d18f505c"
|
|
@@ -186,8 +195,8 @@
|
|
|
186
195
|
"baseline_code_structure_hash": "b42ae08d89173d6c36f958bd504fdbe34d778e321cf0e748835e2c6efa55cb94"
|
|
187
196
|
},
|
|
188
197
|
"py://packages/pyquipu-cli/src/quipu/cli/tui.py#QuipuUiApp": {
|
|
189
|
-
"baseline_code_signature_text": "class QuipuUiApp(App[
|
|
190
|
-
"baseline_code_structure_hash": "
|
|
198
|
+
"baseline_code_signature_text": "class QuipuUiApp(App[UiResult | None]):",
|
|
199
|
+
"baseline_code_structure_hash": "06d592e4c0dd98b4925a676eff12e395f6be75d7f84579b9ab0a757004b239ab"
|
|
191
200
|
},
|
|
192
201
|
"py://packages/pyquipu-cli/src/quipu/cli/tui.py#QuipuUiApp.__init__": {
|
|
193
202
|
"baseline_code_signature_text": "def __init__(self, work_dir: Path, initial_raw_mode: bool = False):",
|
|
@@ -216,8 +225,8 @@
|
|
|
216
225
|
"baseline_yaml_content_hash": "32815db7c566b485e41dc7ea4d9d40e0d8924eca6e948f58ce4e55b439712a86"
|
|
217
226
|
},
|
|
218
227
|
"py://packages/pyquipu-cli/src/quipu/cli/tui.py#QuipuUiApp._populate_table": {
|
|
219
|
-
"baseline_code_signature_text": "def _populate_table(self, table: DataTable, nodes:
|
|
220
|
-
"baseline_code_structure_hash": "
|
|
228
|
+
"baseline_code_signature_text": "def _populate_table(self, table: DataTable, nodes: list[QuipuNode]):",
|
|
229
|
+
"baseline_code_structure_hash": "9b34306b3cc2df3739564a1c4737aa0badebf1f5b0f400d237ef9b131eff989a"
|
|
221
230
|
},
|
|
222
231
|
"py://packages/pyquipu-cli/src/quipu/cli/tui.py#QuipuUiApp._refresh_table": {
|
|
223
232
|
"baseline_code_signature_text": "def _refresh_table(self):",
|
|
@@ -293,13 +302,13 @@
|
|
|
293
302
|
"baseline_code_structure_hash": "3f8bce49d7664245df81a63bb5a291ccf0c3cd96c45f83e04d75aebf1d2d5e3d"
|
|
294
303
|
},
|
|
295
304
|
"py://packages/pyquipu-cli/src/quipu/cli/ui_utils.py#confirmation_handler_for_executor": {
|
|
296
|
-
"baseline_code_signature_text": "def confirmation_handler_for_executor(diff_lines:
|
|
297
|
-
"baseline_code_structure_hash": "
|
|
305
|
+
"baseline_code_signature_text": "def confirmation_handler_for_executor(diff_lines: list[str], prompt: str) -> bool:",
|
|
306
|
+
"baseline_code_structure_hash": "8839407c0755c23f75f457786bae946a90b42b7cedf79063e69426a80ca23aa6",
|
|
298
307
|
"baseline_yaml_content_hash": "4eb68f7550569e0298c63e8d43e90f5b8434b8f6f4d6636f6f93978d74b08f84"
|
|
299
308
|
},
|
|
300
309
|
"py://packages/pyquipu-cli/src/quipu/cli/ui_utils.py#prompt_for_confirmation": {
|
|
301
|
-
"baseline_code_signature_text": "def prompt_for_confirmation(prompt: str, diff_lines:
|
|
302
|
-
"baseline_code_structure_hash": "
|
|
310
|
+
"baseline_code_signature_text": "def prompt_for_confirmation(prompt: str, diff_lines: list[str] | None = None, default: bool = False) -> bool:",
|
|
311
|
+
"baseline_code_structure_hash": "4683c55a61670e31e1df91326540848fe46b1447f94bf29ad10ed42c82dc0aa2",
|
|
303
312
|
"baseline_yaml_content_hash": "3dc83b0a19984f5b60144f71d8978ac23b4c0daa4cde38b1926347f412644bfe"
|
|
304
313
|
},
|
|
305
314
|
"py://packages/pyquipu-cli/src/quipu/cli/view_model.py#GraphViewModel": {
|
|
@@ -308,8 +317,8 @@
|
|
|
308
317
|
"baseline_yaml_content_hash": "96759d61f739ca4964b341e970bfc7441bf01351bc836fa766e4e6b1cb55e69c"
|
|
309
318
|
},
|
|
310
319
|
"py://packages/pyquipu-cli/src/quipu/cli/view_model.py#GraphViewModel.__init__": {
|
|
311
|
-
"baseline_code_signature_text": "def __init__(self, reader: HistoryReader, current_output_tree_hash:
|
|
312
|
-
"baseline_code_structure_hash": "
|
|
320
|
+
"baseline_code_signature_text": "def __init__(self, reader: HistoryReader, current_output_tree_hash: str | None, page_size: int = 50):",
|
|
321
|
+
"baseline_code_structure_hash": "5ae4d4f819ce2ba63f6f06105a2bdcf1bac50fa3c9c7942bc3a363e22a76de45"
|
|
313
322
|
},
|
|
314
323
|
"py://packages/pyquipu-cli/src/quipu/cli/view_model.py#GraphViewModel.calculate_initial_page": {
|
|
315
324
|
"baseline_code_signature_text": "def calculate_initial_page(self) -> int:",
|
|
@@ -322,8 +331,8 @@
|
|
|
322
331
|
"baseline_yaml_content_hash": "a4ed01837de13f83a2e09fe379954c2b3943c52c2c6fbc12ebe2763d49f99ba3"
|
|
323
332
|
},
|
|
324
333
|
"py://packages/pyquipu-cli/src/quipu/cli/view_model.py#GraphViewModel.get_nodes_to_render": {
|
|
325
|
-
"baseline_code_signature_text": "def get_nodes_to_render(self) ->
|
|
326
|
-
"baseline_code_structure_hash": "
|
|
334
|
+
"baseline_code_signature_text": "def get_nodes_to_render(self) -> list[QuipuNode]:",
|
|
335
|
+
"baseline_code_structure_hash": "765e1a9704f17737ce518b862c52463538b0c777ae3cf251c9770ef57b05da7c",
|
|
327
336
|
"baseline_yaml_content_hash": "0c4b0ab6fca1e2564718863cbb3e770ffbc94bb7cb9ce43e00e6a7758cb3a543"
|
|
328
337
|
},
|
|
329
338
|
"py://packages/pyquipu-cli/src/quipu/cli/view_model.py#GraphViewModel.get_public_content": {
|
|
@@ -332,8 +341,8 @@
|
|
|
332
341
|
"baseline_yaml_content_hash": "c82cd6689891833f5df596acf5cc349d3dc989ae032d448a218521060efc01e1"
|
|
333
342
|
},
|
|
334
343
|
"py://packages/pyquipu-cli/src/quipu/cli/view_model.py#GraphViewModel.get_selected_node": {
|
|
335
|
-
"baseline_code_signature_text": "def get_selected_node(self) ->
|
|
336
|
-
"baseline_code_structure_hash": "
|
|
344
|
+
"baseline_code_signature_text": "def get_selected_node(self) -> QuipuNode | None:",
|
|
345
|
+
"baseline_code_structure_hash": "6e3ce0781035f9c7b116b29e108e47f425001b4b388b9741beea84dfbc6ed6e9"
|
|
337
346
|
},
|
|
338
347
|
"py://packages/pyquipu-cli/src/quipu/cli/view_model.py#GraphViewModel.initialize": {
|
|
339
348
|
"baseline_code_signature_text": "def initialize(self):",
|
|
@@ -346,23 +355,23 @@
|
|
|
346
355
|
"baseline_yaml_content_hash": "e76a7af9c807fb82b1397daacd8942c36ffc31eb26d9e05732fb5b2077949ab0"
|
|
347
356
|
},
|
|
348
357
|
"py://packages/pyquipu-cli/src/quipu/cli/view_model.py#GraphViewModel.load_page": {
|
|
349
|
-
"baseline_code_signature_text": "def load_page(self, page_number: int) ->
|
|
350
|
-
"baseline_code_structure_hash": "
|
|
358
|
+
"baseline_code_signature_text": "def load_page(self, page_number: int) -> list[QuipuNode]:",
|
|
359
|
+
"baseline_code_structure_hash": "20f07fca5cc53aa8ada42eacec3b73b6ab9d9082b0246a95204df426712fb025",
|
|
351
360
|
"baseline_yaml_content_hash": "fe82bcfdadf90d6a216cf5cf3b49caf1049a42ed83d34f8cfcd8a389dab699f9"
|
|
352
361
|
},
|
|
353
362
|
"py://packages/pyquipu-cli/src/quipu/cli/view_model.py#GraphViewModel.next_page": {
|
|
354
|
-
"baseline_code_signature_text": "def next_page(self) ->
|
|
355
|
-
"baseline_code_structure_hash": "
|
|
363
|
+
"baseline_code_signature_text": "def next_page(self) -> list[QuipuNode]:",
|
|
364
|
+
"baseline_code_structure_hash": "1bac01aa154cb7eec042a34d7297ed3f4189267c9c2d75afdc9781d804181e7b",
|
|
356
365
|
"baseline_yaml_content_hash": "1bcf43d112b504b11793b21ed9fe9206f3f75d852f9b3d23a71075f48becc845"
|
|
357
366
|
},
|
|
358
367
|
"py://packages/pyquipu-cli/src/quipu/cli/view_model.py#GraphViewModel.previous_page": {
|
|
359
|
-
"baseline_code_signature_text": "def previous_page(self) ->
|
|
360
|
-
"baseline_code_structure_hash": "
|
|
368
|
+
"baseline_code_signature_text": "def previous_page(self) -> list[QuipuNode]:",
|
|
369
|
+
"baseline_code_structure_hash": "56ddbcea75ee3c17eae1fcd6a94d87c6257d1c2b81cc18c2b442ac3184321f55",
|
|
361
370
|
"baseline_yaml_content_hash": "42d56fe3ac79b9852ab639aa371b31ff732169536a50162c0c47c481a9ddf2e0"
|
|
362
371
|
},
|
|
363
372
|
"py://packages/pyquipu-cli/src/quipu/cli/view_model.py#GraphViewModel.select_node_by_key": {
|
|
364
|
-
"baseline_code_signature_text": "def select_node_by_key(self, key: str) ->
|
|
365
|
-
"baseline_code_structure_hash": "
|
|
373
|
+
"baseline_code_signature_text": "def select_node_by_key(self, key: str) -> QuipuNode | None:",
|
|
374
|
+
"baseline_code_structure_hash": "3d513ffd7ee7dc220da062f5401be29ec559cbe4d31dec2c9c3226ae49df2db7",
|
|
366
375
|
"baseline_yaml_content_hash": "e1578b6156c3311a4e524f7c899158b2badde72f9fab1562a3eda6cf4dde79ac"
|
|
367
376
|
},
|
|
368
377
|
"py://packages/pyquipu-cli/src/quipu/cli/view_model.py#GraphViewModel.toggle_unreachable": {
|
|
@@ -609,24 +618,24 @@
|
|
|
609
618
|
"baseline_yaml_content_hash": "2581c4597d154e14157a1ca4f1e6689818bc75cac6c6c982154246996a68ba66"
|
|
610
619
|
},
|
|
611
620
|
"py://packages/pyquipu-cli/tests/unit/test_view_model.py#MockHistoryReader.__init__": {
|
|
612
|
-
"baseline_code_signature_text": "def __init__(self, nodes:
|
|
613
|
-
"baseline_code_structure_hash": "
|
|
621
|
+
"baseline_code_signature_text": "def __init__(self, nodes: list[QuipuNode], ancestors: set[str] | None = None, descendants: set[str] | None = None, private_data: dict[str, str] | None = None):",
|
|
622
|
+
"baseline_code_structure_hash": "c15adb4b9faeca3e22de5b84c4d7dcd05ea584b089d584de2305cb7da5b17915"
|
|
614
623
|
},
|
|
615
624
|
"py://packages/pyquipu-cli/tests/unit/test_view_model.py#MockHistoryReader.find_nodes": {
|
|
616
|
-
"baseline_code_signature_text": "def find_nodes(self, summary_regex:
|
|
617
|
-
"baseline_code_structure_hash": "
|
|
625
|
+
"baseline_code_signature_text": "def find_nodes(self, summary_regex: str | None = None, node_type: str | None = None, limit: int = 10) -> list[QuipuNode]:",
|
|
626
|
+
"baseline_code_structure_hash": "b103f594dbae22354bdb513e871e3b9cdbbeb2e41d2db5a818abb6a7f3b0c311"
|
|
618
627
|
},
|
|
619
628
|
"py://packages/pyquipu-cli/tests/unit/test_view_model.py#MockHistoryReader.get_ancestor_output_trees": {
|
|
620
|
-
"baseline_code_signature_text": "def get_ancestor_output_trees(self, start_output_tree_hash: str) ->
|
|
621
|
-
"baseline_code_structure_hash": "
|
|
629
|
+
"baseline_code_signature_text": "def get_ancestor_output_trees(self, start_output_tree_hash: str) -> set[str]:",
|
|
630
|
+
"baseline_code_structure_hash": "3137f354f85dc31acbd0088f5ef7e1fe4cf485b61f6be7e135f65436068e515c"
|
|
622
631
|
},
|
|
623
632
|
"py://packages/pyquipu-cli/tests/unit/test_view_model.py#MockHistoryReader.get_descendant_output_trees": {
|
|
624
|
-
"baseline_code_signature_text": "def get_descendant_output_trees(self, start_output_tree_hash: str) ->
|
|
625
|
-
"baseline_code_structure_hash": "
|
|
633
|
+
"baseline_code_signature_text": "def get_descendant_output_trees(self, start_output_tree_hash: str) -> set[str]:",
|
|
634
|
+
"baseline_code_structure_hash": "526a17b5e1ffa47471d993f9b748dac6ea0351fbcfe21dd8af229f06468c8eb4"
|
|
626
635
|
},
|
|
627
636
|
"py://packages/pyquipu-cli/tests/unit/test_view_model.py#MockHistoryReader.get_node_blobs": {
|
|
628
|
-
"baseline_code_signature_text": "def get_node_blobs(self, commit_hash: str) ->
|
|
629
|
-
"baseline_code_structure_hash": "
|
|
637
|
+
"baseline_code_signature_text": "def get_node_blobs(self, commit_hash: str) -> dict[str, bytes]:",
|
|
638
|
+
"baseline_code_structure_hash": "7518243aeddcb0655879143807114fbeb826325af0a4123a2ba38f5111bc444b"
|
|
630
639
|
},
|
|
631
640
|
"py://packages/pyquipu-cli/tests/unit/test_view_model.py#MockHistoryReader.get_node_content": {
|
|
632
641
|
"baseline_code_signature_text": "def get_node_content(self, node: QuipuNode) -> str:",
|
|
@@ -641,16 +650,16 @@
|
|
|
641
650
|
"baseline_code_structure_hash": "eeb815e029cbffaf43c5365481a21a4251ca6fb30632886a63a5716104041b0e"
|
|
642
651
|
},
|
|
643
652
|
"py://packages/pyquipu-cli/tests/unit/test_view_model.py#MockHistoryReader.get_private_data": {
|
|
644
|
-
"baseline_code_signature_text": "def get_private_data(self, node_commit_hash: str) ->
|
|
645
|
-
"baseline_code_structure_hash": "
|
|
653
|
+
"baseline_code_signature_text": "def get_private_data(self, node_commit_hash: str) -> str | None:",
|
|
654
|
+
"baseline_code_structure_hash": "f89eb26a5371e45416b6f432a473f88cd63353152433e66e86f35265a7658191"
|
|
646
655
|
},
|
|
647
656
|
"py://packages/pyquipu-cli/tests/unit/test_view_model.py#MockHistoryReader.load_all_nodes": {
|
|
648
|
-
"baseline_code_signature_text": "def load_all_nodes(self) ->
|
|
649
|
-
"baseline_code_structure_hash": "
|
|
657
|
+
"baseline_code_signature_text": "def load_all_nodes(self) -> list[QuipuNode]:",
|
|
658
|
+
"baseline_code_structure_hash": "c5356664632a9b785d7fe92e32dbe0c2f1a17f3e47b114c31bdaed8d6a801709"
|
|
650
659
|
},
|
|
651
660
|
"py://packages/pyquipu-cli/tests/unit/test_view_model.py#MockHistoryReader.load_nodes_paginated": {
|
|
652
|
-
"baseline_code_signature_text": "def load_nodes_paginated(self, limit: int, offset: int) ->
|
|
653
|
-
"baseline_code_structure_hash": "
|
|
661
|
+
"baseline_code_signature_text": "def load_nodes_paginated(self, limit: int, offset: int) -> list[QuipuNode]:",
|
|
662
|
+
"baseline_code_structure_hash": "562ea54003c14803e8c89699ab31b0595f9e236068865e3088685a8b78595134"
|
|
654
663
|
},
|
|
655
664
|
"py://packages/pyquipu-cli/tests/unit/test_view_model.py#TestGraphViewModel": {
|
|
656
665
|
"baseline_code_signature_text": "class TestGraphViewModel:",
|
|
@@ -14,7 +14,7 @@ def populated_workspace(quipu_workspace):
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
def test_cli_back_forward_flow(runner, populated_workspace, monkeypatch):
|
|
17
|
-
workspace, hash_a,
|
|
17
|
+
workspace, hash_a, _hash_b = populated_workspace
|
|
18
18
|
mock_bus_nav = MagicMock()
|
|
19
19
|
mock_bus_helper = MagicMock()
|
|
20
20
|
monkeypatch.setattr("quipu.cli.commands.navigation.bus", mock_bus_nav)
|
|
@@ -41,7 +41,7 @@ def test_cli_back_forward_flow(runner, populated_workspace, monkeypatch):
|
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
def test_cli_boundary_messages(runner, populated_workspace, monkeypatch):
|
|
44
|
-
workspace, hash_a,
|
|
44
|
+
workspace, hash_a, _hash_b = populated_workspace
|
|
45
45
|
mock_bus = MagicMock()
|
|
46
46
|
monkeypatch.setattr("quipu.cli.commands.navigation.bus", mock_bus)
|
|
47
47
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
from needle.pointer import L
|
|
2
1
|
from unittest import mock
|
|
3
2
|
from unittest.mock import MagicMock
|
|
4
3
|
|
|
4
|
+
from needle.pointer import L
|
|
5
5
|
from quipu.cli.main import app
|
|
6
6
|
|
|
7
7
|
|
|
@@ -49,12 +49,13 @@ def test_discard_interactive_abort(runner, quipu_workspace, monkeypatch):
|
|
|
49
49
|
work_dir, _, engine = quipu_workspace
|
|
50
50
|
mock_bus = MagicMock()
|
|
51
51
|
monkeypatch.setattr("quipu.cli.commands.workspace.bus", mock_bus)
|
|
52
|
+
monkeypatch.setattr("click.getchar", lambda echo=False: "n")
|
|
52
53
|
|
|
53
54
|
(work_dir / "file.txt").write_text("v1")
|
|
54
55
|
engine.capture_drift(engine.git_db.get_tree_hash())
|
|
55
56
|
(work_dir / "file.txt").write_text("v2")
|
|
56
57
|
|
|
57
|
-
result = runner.invoke(app, ["discard", "-w", str(work_dir)]
|
|
58
|
+
result = runner.invoke(app, ["discard", "-w", str(work_dir)])
|
|
58
59
|
|
|
59
60
|
assert result.exit_code == 1
|
|
60
61
|
mock_bus.warning.assert_called_once_with(L.common.prompt.cancel)
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from datetime import datetime
|
|
2
2
|
from pathlib import Path
|
|
3
|
-
from typing import Dict, List, Optional, Set
|
|
4
3
|
|
|
5
4
|
import pytest
|
|
6
5
|
from quipu.cli.view_model import GraphViewModel
|
|
@@ -11,10 +10,10 @@ from quipu.spec.protocols.storage import HistoryReader
|
|
|
11
10
|
class MockHistoryReader(HistoryReader):
|
|
12
11
|
def __init__(
|
|
13
12
|
self,
|
|
14
|
-
nodes:
|
|
15
|
-
ancestors:
|
|
16
|
-
descendants:
|
|
17
|
-
private_data:
|
|
13
|
+
nodes: list[QuipuNode],
|
|
14
|
+
ancestors: set[str] | None = None,
|
|
15
|
+
descendants: set[str] | None = None,
|
|
16
|
+
private_data: dict[str, str] | None = None,
|
|
18
17
|
):
|
|
19
18
|
self._nodes = sorted(nodes, key=lambda n: n.timestamp, reverse=True)
|
|
20
19
|
self._ancestors = ancestors or set()
|
|
@@ -24,13 +23,13 @@ class MockHistoryReader(HistoryReader):
|
|
|
24
23
|
def get_node_count(self) -> int:
|
|
25
24
|
return len(self._nodes)
|
|
26
25
|
|
|
27
|
-
def load_nodes_paginated(self, limit: int, offset: int) ->
|
|
26
|
+
def load_nodes_paginated(self, limit: int, offset: int) -> list[QuipuNode]:
|
|
28
27
|
return self._nodes[offset : offset + limit]
|
|
29
28
|
|
|
30
|
-
def get_ancestor_output_trees(self, start_output_tree_hash: str) ->
|
|
29
|
+
def get_ancestor_output_trees(self, start_output_tree_hash: str) -> set[str]:
|
|
31
30
|
return self._ancestors
|
|
32
31
|
|
|
33
|
-
def get_descendant_output_trees(self, start_output_tree_hash: str) ->
|
|
32
|
+
def get_descendant_output_trees(self, start_output_tree_hash: str) -> set[str]:
|
|
34
33
|
return self._descendants
|
|
35
34
|
|
|
36
35
|
def get_node_position(self, output_tree_hash: str) -> int:
|
|
@@ -39,26 +38,26 @@ class MockHistoryReader(HistoryReader):
|
|
|
39
38
|
return i
|
|
40
39
|
return -1
|
|
41
40
|
|
|
42
|
-
def get_private_data(self, node_commit_hash: str) ->
|
|
41
|
+
def get_private_data(self, node_commit_hash: str) -> str | None:
|
|
43
42
|
return self._private_data.get(node_commit_hash)
|
|
44
43
|
|
|
45
44
|
def get_node_content(self, node: QuipuNode) -> str:
|
|
46
45
|
# For simplicity, mock content is stored in the node's summary
|
|
47
46
|
return node.summary
|
|
48
47
|
|
|
49
|
-
def get_node_blobs(self, commit_hash: str) ->
|
|
48
|
+
def get_node_blobs(self, commit_hash: str) -> dict[str, bytes]:
|
|
50
49
|
return {}
|
|
51
50
|
|
|
52
51
|
# --- Unused abstract methods ---
|
|
53
|
-
def load_all_nodes(self) ->
|
|
52
|
+
def load_all_nodes(self) -> list[QuipuNode]:
|
|
54
53
|
return self._nodes
|
|
55
54
|
|
|
56
55
|
def find_nodes(
|
|
57
56
|
self,
|
|
58
|
-
summary_regex:
|
|
59
|
-
node_type:
|
|
57
|
+
summary_regex: str | None = None,
|
|
58
|
+
node_type: str | None = None,
|
|
60
59
|
limit: int = 10,
|
|
61
|
-
) ->
|
|
60
|
+
) -> list[QuipuNode]:
|
|
62
61
|
return []
|
|
63
62
|
|
|
64
63
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -3,8 +3,8 @@ from pathlib import Path
|
|
|
3
3
|
from typing import Annotated
|
|
4
4
|
|
|
5
5
|
import typer
|
|
6
|
-
from quipu.application.factory import create_engine
|
|
7
6
|
from needle.pointer import L
|
|
7
|
+
from quipu.application.factory import create_engine
|
|
8
8
|
from quipu.common.bus import bus
|
|
9
9
|
|
|
10
10
|
from ..config import DEFAULT_WORK_DIR, LOG_LEVEL
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/tests/integration/test_cli_interaction.stitcher.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyquipu_cli-0.3.2 → pyquipu_cli-0.4.0}/tests/integration/test_unfriendly_paths.stitcher.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|