gyomu-cli 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.
@@ -0,0 +1,29 @@
1
+ venv/
2
+ .idea/
3
+
4
+ /build/
5
+ /dist/
6
+ /src/gyomu.egg-info/
7
+ /.coverage
8
+ /htmlcov/
9
+ __pycache__/
10
+ *.py[cod]
11
+
12
+ .env
13
+ .env.*
14
+ !.env.example
15
+
16
+ .mypy_cache/
17
+ .ruff_cache/
18
+ htmlcov/
19
+ *.egg-info/
20
+ log/
21
+
22
+
23
+ # gyomu ai related
24
+ **/.gyomu/cache
25
+ **/.gyomu/snapshot
26
+ **/.gyomu/checkpoint
27
+
28
+ # snapshot
29
+ __snapshots__
@@ -0,0 +1,15 @@
1
+ Metadata-Version: 2.5
2
+ Name: gyomu-cli
3
+ Version: 0.4.0
4
+ Summary: Gyomu CLI
5
+ Requires-Python: >=3.13
6
+ Requires-Dist: gyomu-infra
7
+ Requires-Dist: gyomu-schema
8
+ Requires-Dist: gyomu-workflow
9
+ Requires-Dist: returns
10
+ Requires-Dist: typer>=0.27.2
11
+ Description-Content-Type: text/markdown
12
+
13
+ # gyomu-cli
14
+
15
+ cli application for Gyomu Python.
@@ -0,0 +1,3 @@
1
+ # gyomu-cli
2
+
3
+ cli application for Gyomu Python.
@@ -0,0 +1,29 @@
1
+ [project]
2
+ name = "gyomu-cli"
3
+ dynamic = ["version"]
4
+ description = "Gyomu CLI"
5
+ readme = "README.md"
6
+ requires-python = ">=3.13"
7
+ dependencies = [
8
+ "gyomu-schema",
9
+ "gyomu-infra",
10
+ "returns",
11
+ "gyomu-workflow",
12
+ "typer>=0.27.2",
13
+ ]
14
+
15
+ [build-system]
16
+ requires = ["hatchling"]
17
+ build-backend = "hatchling.build"
18
+
19
+
20
+ [tool.uv.sources]
21
+ gyomu-schema = { workspace = true }
22
+ gyomu-infra = { workspace = true }
23
+ gyomu-workflow = { workspace = true }
24
+
25
+ [tool.hatch.version]
26
+ path = "../../version/__about__.py"
27
+
28
+ [project.scripts]
29
+ gyomu = "gyomu_cli.main:app"
File without changes
@@ -0,0 +1,119 @@
1
+ import asyncio
2
+
3
+ import typer
4
+ from gyomu_ai.provider.pydantic_ai.google import (
5
+ create_default_pydantic_ai_model_registry,
6
+ )
7
+ from gyomu_ai.provider.pydantic_ai.route_registry import AiConfiguration, initialize_ai
8
+ from gyomu_ai.provider.pydantic_ai.routing import (
9
+ ModelRoute,
10
+ ModelRouteId,
11
+ ModelRoutes,
12
+ RouteNode,
13
+ )
14
+ from gyomu_ai_compiler.pipelines.docstring_update import DocstringRouteId
15
+ from gyomu_infra.logger import logger
16
+ from gyomu_schema.option.retry import RetryObserver
17
+ from gyomu_workflow.snapshot.models import (
18
+ DocstringExecutionOption,
19
+ FileFilter,
20
+ SnapshotActionOption,
21
+ SnapshotExecutionOption,
22
+ SnapshotTargetOption,
23
+ )
24
+ from gyomu_workflow.snapshot.run import run_snapshot
25
+ from gyomu_workflow.snapshot.translate import translate_snapshot_request
26
+ from gyomu_workflow.snapshot.validate import validate_snapshot_request
27
+ from returns.result import Failure
28
+
29
+ app = typer.Typer()
30
+
31
+ hello_app = typer.Typer()
32
+ app.add_typer(hello_app, name="hello")
33
+
34
+
35
+ # @hello_app.command()
36
+ @app.command()
37
+ def greet(name: str = "World") -> None:
38
+ print(f"Hello, {name}!")
39
+
40
+
41
+ @app.command()
42
+ def greet2(name: str = "World") -> None:
43
+ print(f"Hello, {name}!")
44
+
45
+
46
+ @hello_app.command("greet")
47
+ def greet3(name: str = "World") -> None:
48
+ print(f"Hello, {name}!")
49
+
50
+
51
+ def register_google_routing(
52
+ route_id_list: list[ModelRouteId],
53
+ retry_observer: RetryObserver | None = None,
54
+ ) -> None:
55
+ route: RouteNode = RouteNode(registry=create_default_pydantic_ai_model_registry())
56
+ routes: dict[ModelRouteId, ModelRoute] = {}
57
+ for route_id in route_id_list:
58
+ routes[route_id] = ModelRoute((route,))
59
+ initialize_ai(
60
+ AiConfiguration(
61
+ model_routes=ModelRoutes(routes=routes), retry_observer=retry_observer
62
+ )
63
+ )
64
+
65
+
66
+ @app.command()
67
+ def snapshot(
68
+ package: str,
69
+ docstring: bool = True,
70
+ all: bool = False,
71
+ commit: bool = True,
72
+ filter: str | None = None,
73
+ log_keyword: str | None = None,
74
+ ) -> None:
75
+ register_google_routing(route_id_list=[DocstringRouteId])
76
+ option = SnapshotExecutionOption(
77
+ commit=commit,
78
+ target=SnapshotTargetOption(
79
+ all=all,
80
+ file_filter=FileFilter(pattern=filter) if filter is not None else None,
81
+ ),
82
+ action=SnapshotActionOption(
83
+ docstring=DocstringExecutionOption(
84
+ enabled=docstring, log_keyword=log_keyword
85
+ ),
86
+ ),
87
+ )
88
+ request_result = translate_snapshot_request(package, option)
89
+ if isinstance(request_result, Failure):
90
+ logger.error_object(request_result.failure())
91
+ return
92
+ request = request_result.unwrap()
93
+ logger.info(
94
+ f"commit: {request.option.commit}, "
95
+ f"docstring:{request.option.action.docstring.enabled}, "
96
+ f"all={request.option.target.all}"
97
+ )
98
+ if filter:
99
+ assert option.target.file_filter
100
+ logger.info(f"filter: {option.target.file_filter.pattern}")
101
+ if log_keyword:
102
+ logger.info(f"log_keyword: {request.option.action.docstring.log_keyword}")
103
+
104
+ validation_result = validate_snapshot_request(request)
105
+ if isinstance(validation_result, Failure):
106
+ logger.error_object(validation_result.failure())
107
+ return
108
+
109
+ snapshot_result = asyncio.run(run_snapshot(request))
110
+ if isinstance(snapshot_result, Failure):
111
+ logger.error_object(snapshot_result.failure())
112
+ return
113
+
114
+ logger.info("Done")
115
+ # logger.error_object(request.unwrap(), 3)
116
+
117
+
118
+ if __name__ == "__main__":
119
+ app()
File without changes
@@ -0,0 +1,186 @@
1
+ from pathlib import Path
2
+
3
+ import pytest
4
+ from gyomu_cli.main import app
5
+ from gyomu_python_analysis.project.context import ProjectContext
6
+ from gyomu_schema.error.gyomu import GyomuError
7
+ from gyomu_schema.schemas.types import FullPath
8
+ from gyomu_workflow.snapshot.models import (
9
+ DocstringExecutionOption,
10
+ SnapshotActionOption,
11
+ SnapshotExecutionOption,
12
+ SnapshotRequest,
13
+ SnapshotTargetOption,
14
+ )
15
+ from pytest_mock import MockerFixture
16
+ from returns.result import Failure, Success
17
+ from typer.testing import CliRunner
18
+
19
+ runner = CliRunner()
20
+
21
+
22
+ @pytest.fixture
23
+ def snapshot_request(mocker: MockerFixture) -> SnapshotRequest:
24
+ return SnapshotRequest(
25
+ repository_root_path=FullPath(Path("/tmp")),
26
+ project_context=mocker.Mock(spec=ProjectContext),
27
+ option=SnapshotExecutionOption(
28
+ commit=True,
29
+ action=SnapshotActionOption(
30
+ docstring=DocstringExecutionOption(enabled=True),
31
+ ),
32
+ target=SnapshotTargetOption(),
33
+ ),
34
+ )
35
+
36
+
37
+ def test_snapshot_success(mocker: MockerFixture, snapshot_request: SnapshotRequest):
38
+ mocker.patch(
39
+ "gyomu_cli.main.register_google_routing",
40
+ return_value=None,
41
+ )
42
+ mocker.patch(
43
+ "gyomu_cli.main.translate_snapshot_request",
44
+ return_value=Success(snapshot_request),
45
+ )
46
+ mocker.patch(
47
+ "gyomu_cli.main.validate_snapshot_request",
48
+ return_value=Success(None),
49
+ )
50
+ run_snapshot = mocker.patch(
51
+ "gyomu_cli.main.run_snapshot",
52
+ return_value=Success(None),
53
+ )
54
+
55
+ result = runner.invoke(
56
+ app,
57
+ [
58
+ "snapshot",
59
+ "test-package",
60
+ "--docstring",
61
+ "--all",
62
+ "--commit",
63
+ "--log-keyword",
64
+ "test",
65
+ ],
66
+ )
67
+
68
+ assert result.exit_code == 0
69
+
70
+ run_snapshot.assert_awaited_once_with(snapshot_request)
71
+
72
+
73
+ def test_snapshot_translate_failure(
74
+ mocker: MockerFixture,
75
+ ):
76
+
77
+ error = GyomuError(
78
+ message="translate failed",
79
+ domain="test",
80
+ operation="translate",
81
+ reason="invalid_input",
82
+ )
83
+
84
+ mocker.patch(
85
+ "gyomu_cli.main.register_google_routing",
86
+ return_value=None,
87
+ )
88
+ mocker.patch(
89
+ "gyomu_cli.main.translate_snapshot_request",
90
+ return_value=Failure(error),
91
+ )
92
+ validate_snapshot_request = mocker.patch(
93
+ "gyomu_cli.main.validate_snapshot_request",
94
+ )
95
+ run_snapshot = mocker.patch(
96
+ "gyomu_cli.main.run_snapshot",
97
+ )
98
+
99
+ result = runner.invoke(
100
+ app,
101
+ [
102
+ "snapshot",
103
+ "test-package",
104
+ ],
105
+ )
106
+
107
+ assert result.exit_code == 0
108
+
109
+ validate_snapshot_request.assert_not_called()
110
+ run_snapshot.assert_not_called()
111
+
112
+
113
+ def test_snapshot_validation_failure(
114
+ mocker: MockerFixture, snapshot_request: SnapshotRequest
115
+ ):
116
+
117
+ error = GyomuError(
118
+ message="validation failed",
119
+ domain="test",
120
+ operation="validate",
121
+ reason="invalid_input",
122
+ )
123
+
124
+ mocker.patch(
125
+ "gyomu_cli.main.register_google_routing",
126
+ return_value=None,
127
+ )
128
+ mocker.patch(
129
+ "gyomu_cli.main.translate_snapshot_request",
130
+ return_value=Success(snapshot_request),
131
+ )
132
+ mocker.patch(
133
+ "gyomu_cli.main.validate_snapshot_request",
134
+ return_value=Failure(error),
135
+ )
136
+ run_snapshot = mocker.patch(
137
+ "gyomu_cli.main.run_snapshot",
138
+ )
139
+
140
+ result = runner.invoke(
141
+ app,
142
+ [
143
+ "snapshot",
144
+ "test-package",
145
+ ],
146
+ )
147
+
148
+ assert result.exit_code == 0
149
+
150
+ run_snapshot.assert_not_called()
151
+
152
+
153
+ def test_snapshot_run_failure(mocker: MockerFixture, snapshot_request: SnapshotRequest):
154
+
155
+ error = GyomuError(
156
+ message="run failed",
157
+ domain="test",
158
+ operation="run",
159
+ reason="invalid_input",
160
+ )
161
+ mocker.patch(
162
+ "gyomu_cli.main.register_google_routing",
163
+ return_value=None,
164
+ )
165
+ mocker.patch(
166
+ "gyomu_cli.main.translate_snapshot_request",
167
+ return_value=Success(snapshot_request),
168
+ )
169
+ mocker.patch(
170
+ "gyomu_cli.main.validate_snapshot_request",
171
+ return_value=Success(None),
172
+ )
173
+ mocker.patch(
174
+ "gyomu_cli.main.run_snapshot",
175
+ return_value=Failure(error),
176
+ )
177
+
178
+ result = runner.invoke(
179
+ app,
180
+ [
181
+ "snapshot",
182
+ "test-package",
183
+ ],
184
+ )
185
+
186
+ assert result.exit_code == 0