papycli 0.16.1__tar.gz → 0.16.2__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.
Files changed (78) hide show
  1. {papycli-0.16.1 → papycli-0.16.2}/.github/workflows/docs.yml +1 -1
  2. papycli-0.16.2/.release-please-manifest.json +3 -0
  3. {papycli-0.16.1 → papycli-0.16.2}/CHANGELOG.md +7 -0
  4. {papycli-0.16.1 → papycli-0.16.2}/PKG-INFO +1 -1
  5. {papycli-0.16.1 → papycli-0.16.2}/mkdocs.yml +2 -1
  6. {papycli-0.16.1 → papycli-0.16.2}/pyproject.toml +1 -1
  7. {papycli-0.16.1 → papycli-0.16.2}/src/papycli/api_call.py +3 -2
  8. papycli-0.16.1/.release-please-manifest.json +0 -3
  9. papycli-0.16.1/design/2026-03-27-completion-static-script.md +0 -664
  10. papycli-0.16.1/design/2026-03-28-claude-md-simplification-plan.md +0 -188
  11. papycli-0.16.1/design/2026-03-28-claude-md-simplification.md +0 -100
  12. {papycli-0.16.1 → papycli-0.16.2}/.claude/rules/cli-spec.md +0 -0
  13. {papycli-0.16.1 → papycli-0.16.2}/.claude/rules/data-format.md +0 -0
  14. {papycli-0.16.1 → papycli-0.16.2}/.claude/rules/workflow.md +0 -0
  15. {papycli-0.16.1 → papycli-0.16.2}/.claude/settings.json +0 -0
  16. {papycli-0.16.1 → papycli-0.16.2}/.github/copilot-instructions.md +0 -0
  17. {papycli-0.16.1 → papycli-0.16.2}/.github/workflows/copilot-review.yml +0 -0
  18. {papycli-0.16.1 → papycli-0.16.2}/.github/workflows/release-please.yml +0 -0
  19. {papycli-0.16.1 → papycli-0.16.2}/.gitignore +0 -0
  20. {papycli-0.16.1 → papycli-0.16.2}/.pre-commit-config.yaml +0 -0
  21. {papycli-0.16.1 → papycli-0.16.2}/.python-version +0 -0
  22. {papycli-0.16.1 → papycli-0.16.2}/CLAUDE.md +0 -0
  23. {papycli-0.16.1 → papycli-0.16.2}/LICENSE +0 -0
  24. {papycli-0.16.1 → papycli-0.16.2}/README.ja.md +0 -0
  25. {papycli-0.16.1 → papycli-0.16.2}/README.md +0 -0
  26. {papycli-0.16.1 → papycli-0.16.2}/design/design_doc.md +0 -0
  27. {papycli-0.16.1 → papycli-0.16.2}/docs/superpowers/plans/2026-04-01-config-add-upgrade.md +0 -0
  28. {papycli-0.16.1 → papycli-0.16.2}/docs/superpowers/plans/2026-04-02-dotenv-autoload.md +0 -0
  29. {papycli-0.16.1 → papycli-0.16.2}/docs/superpowers/specs/2026-04-01-config-add-upgrade-design.md +0 -0
  30. {papycli-0.16.1 → papycli-0.16.2}/docs/superpowers/specs/2026-04-02-dotenv-autoload-design.md +0 -0
  31. {papycli-0.16.1 → papycli-0.16.2}/examples/petstore/docker-compose.yml +0 -0
  32. {papycli-0.16.1 → papycli-0.16.2}/examples/petstore/petstore-oas3.json +0 -0
  33. {papycli-0.16.1 → papycli-0.16.2}/examples/request_filter/README.md +0 -0
  34. {papycli-0.16.1 → papycli-0.16.2}/examples/request_filter/pyproject.toml +0 -0
  35. {papycli-0.16.1 → papycli-0.16.2}/examples/request_filter/src/papycli_debug_filter/__init__.py +0 -0
  36. {papycli-0.16.1 → papycli-0.16.2}/examples/response_filter/README.md +0 -0
  37. {papycli-0.16.1 → papycli-0.16.2}/examples/response_filter/pyproject.toml +0 -0
  38. {papycli-0.16.1 → papycli-0.16.2}/examples/response_filter/src/papycli_debug_response_filter/__init__.py +0 -0
  39. {papycli-0.16.1/docs → papycli-0.16.2/manual}/development.md +0 -0
  40. {papycli-0.16.1/docs → papycli-0.16.2/manual}/index.md +0 -0
  41. {papycli-0.16.1/docs → papycli-0.16.2/manual}/installation.md +0 -0
  42. {papycli-0.16.1/docs → papycli-0.16.2/manual}/ja/development.md +0 -0
  43. {papycli-0.16.1/docs → papycli-0.16.2/manual}/ja/index.md +0 -0
  44. {papycli-0.16.1/docs → papycli-0.16.2/manual}/ja/installation.md +0 -0
  45. {papycli-0.16.1/docs → papycli-0.16.2/manual}/ja/plugins.md +0 -0
  46. {papycli-0.16.1/docs → papycli-0.16.2/manual}/ja/quickstart.md +0 -0
  47. {papycli-0.16.1/docs → papycli-0.16.2/manual}/ja/reference.md +0 -0
  48. {papycli-0.16.1/docs → papycli-0.16.2/manual}/plugins.md +0 -0
  49. {papycli-0.16.1/docs → papycli-0.16.2/manual}/quickstart.md +0 -0
  50. {papycli-0.16.1/docs → papycli-0.16.2/manual}/reference.md +0 -0
  51. {papycli-0.16.1 → papycli-0.16.2}/release-please-config.json +0 -0
  52. {papycli-0.16.1 → papycli-0.16.2}/src/papycli/__init__.py +0 -0
  53. {papycli-0.16.1 → papycli-0.16.2}/src/papycli/checker.py +0 -0
  54. {papycli-0.16.1 → papycli-0.16.2}/src/papycli/completion.py +0 -0
  55. {papycli-0.16.1 → papycli-0.16.2}/src/papycli/config.py +0 -0
  56. {papycli-0.16.1 → papycli-0.16.2}/src/papycli/filters.py +0 -0
  57. {papycli-0.16.1 → papycli-0.16.2}/src/papycli/i18n.py +0 -0
  58. {papycli-0.16.1 → papycli-0.16.2}/src/papycli/init_cmd.py +0 -0
  59. {papycli-0.16.1 → papycli-0.16.2}/src/papycli/main.py +0 -0
  60. {papycli-0.16.1 → papycli-0.16.2}/src/papycli/response_checker.py +0 -0
  61. {papycli-0.16.1 → papycli-0.16.2}/src/papycli/spec_loader.py +0 -0
  62. {papycli-0.16.1 → papycli-0.16.2}/src/papycli/summary.py +0 -0
  63. {papycli-0.16.1 → papycli-0.16.2}/tests/integration/__init__.py +0 -0
  64. {papycli-0.16.1 → papycli-0.16.2}/tests/integration/conftest.py +0 -0
  65. {papycli-0.16.1 → papycli-0.16.2}/tests/integration/test_integration.py +0 -0
  66. {papycli-0.16.1 → papycli-0.16.2}/tests/unittest/conftest.py +0 -0
  67. {papycli-0.16.1 → papycli-0.16.2}/tests/unittest/test_api_call.py +0 -0
  68. {papycli-0.16.1 → papycli-0.16.2}/tests/unittest/test_checker.py +0 -0
  69. {papycli-0.16.1 → papycli-0.16.2}/tests/unittest/test_completion.py +0 -0
  70. {papycli-0.16.1 → papycli-0.16.2}/tests/unittest/test_config.py +0 -0
  71. {papycli-0.16.1 → papycli-0.16.2}/tests/unittest/test_filters.py +0 -0
  72. {papycli-0.16.1 → papycli-0.16.2}/tests/unittest/test_i18n.py +0 -0
  73. {papycli-0.16.1 → papycli-0.16.2}/tests/unittest/test_init_cmd.py +0 -0
  74. {papycli-0.16.1 → papycli-0.16.2}/tests/unittest/test_main.py +0 -0
  75. {papycli-0.16.1 → papycli-0.16.2}/tests/unittest/test_response_checker.py +0 -0
  76. {papycli-0.16.1 → papycli-0.16.2}/tests/unittest/test_spec_loader.py +0 -0
  77. {papycli-0.16.1 → papycli-0.16.2}/tests/unittest/test_summary.py +0 -0
  78. {papycli-0.16.1 → papycli-0.16.2}/uv.lock +0 -0
@@ -5,7 +5,7 @@ on:
5
5
  branches:
6
6
  - main
7
7
  paths:
8
- - "docs/**"
8
+ - "manual/**"
9
9
  - "mkdocs.yml"
10
10
  workflow_dispatch:
11
11
 
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "0.16.2"
3
+ }
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.16.2](https://github.com/tmonj1/papycli/compare/v0.16.1...v0.16.2) (2026-04-11)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * api_call.py の mypy エラーを修正 (ResponseContext | None の型不整合) ([#176](https://github.com/tmonj1/papycli/issues/176)) ([9b9917c](https://github.com/tmonj1/papycli/commit/9b9917c2f8d3ea8b660d5618b15c1dfa0fa28c15)), closes [#175](https://github.com/tmonj1/papycli/issues/175)
9
+
3
10
  ## [0.16.1](https://github.com/tmonj1/papycli/compare/v0.16.0...v0.16.1) (2026-04-08)
4
11
 
5
12
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: papycli
3
- Version: 0.16.1
3
+ Version: 0.16.2
4
4
  Summary: A CLI tool to call REST APIs defined in OpenAPI 3.0 specs
5
5
  Project-URL: Homepage, https://github.com/tmonj1/papycli
6
6
  Project-URL: Repository, https://github.com/tmonj1/papycli
@@ -3,7 +3,8 @@ site_description: Python CLI for OpenAPI 3.0 REST APIs
3
3
  site_url: https://tmonj1.github.io/papycli/
4
4
  repo_url: https://github.com/tmonj1/papycli
5
5
  repo_name: tmonj1/papycli
6
- edit_uri: edit/main/docs/
6
+ docs_dir: manual
7
+ edit_uri: edit/main/manual/
7
8
 
8
9
  theme:
9
10
  name: material
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "papycli"
3
- version = "0.16.1"
3
+ version = "0.16.2"
4
4
  description = "A CLI tool to call REST APIs defined in OpenAPI 3.0 specs"
5
5
  readme = "README.md"
6
6
  license = {text = "MIT"}
@@ -451,10 +451,11 @@ def call_api(
451
451
  request_body=ctx.body,
452
452
  schema=resp_schema,
453
453
  )
454
- resp_ctx = apply_response_filters(resp_ctx, response_filters)
455
- if resp_ctx is None:
454
+ filtered_ctx = apply_response_filters(resp_ctx, response_filters)
455
+ if filtered_ctx is None:
456
456
  # フィルターが None を返してチェーンを中断した。出力を抑制するため None を返す。
457
457
  return None
458
+ resp_ctx = filtered_ctx
458
459
 
459
460
  # フィルターがフィールドを変更した場合、resp に反映する。
460
461
  # ボディ: 値の等価比較で変更を検出し、_content・encoding・Content-Type を更新する。
@@ -1,3 +0,0 @@
1
- {
2
- ".": "0.16.1"
3
- }
@@ -1,664 +0,0 @@
1
- # Shell Completion 高速化(静的スクリプト生成)実装計画
2
-
3
- > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
4
-
5
- **Goal:** `config completion-script` が補完データを埋め込んだ静的 bash/zsh スクリプトを出力するようにし、Tab 補完時の Python プロセス起動をゼロにする。
6
-
7
- **Architecture:** `completion.py` に `generate_static_script(shell, cmd_name, apidef, api_names)` を追加する。この関数はリソースパス・パラメータ名・enum 値を shell の case 文として埋め込んだ完全な補完スクリプトを返す。`main.py` の `cmd_config_completion_script` がこの関数を呼ぶよう変更する。ユーザーの利用方法(`eval "$(papycli config completion-script bash)"`)は変わらない。既存の `generate_script` と `_complete` サブコマンドは後方互換のため残す。
8
-
9
- **Tech Stack:** Python 3.12, bash 3.x+, zsh 5.x+, pytest, ruff, mypy
10
-
11
- ---
12
-
13
- ## ファイル変更マップ
14
-
15
- | ファイル | 変更種別 | 内容 |
16
- |---|---|---|
17
- | `src/papycli/completion.py` | 追加 | 静的テンプレート・データ構築ヘルパー・`generate_static_script` |
18
- | `src/papycli/main.py` | 変更 | `cmd_config_completion_script` が `generate_static_script` を呼ぶ |
19
- | `tests/unittest/test_completion.py` | 追加 | `TestGenerateStaticScript` クラス |
20
- | `tests/unittest/test_main.py` | 追加 | `TestCompletionScriptStatic` クラス |
21
-
22
- ---
23
-
24
- ## Task 1: `generate_static_script` と補完データ構築ヘルパーの追加
25
-
26
- **Files:**
27
- - Modify: `src/papycli/completion.py`
28
- - Modify: `tests/unittest/test_completion.py`
29
-
30
- - [ ] **Step 1-1: 失敗するテストを書く**
31
-
32
- `tests/unittest/test_completion.py` の末尾にクラスを追加する。ファイル先頭の既存 import ブロックに `generate_static_script` を追加する(新しい `from` 行は追加しない)。
33
-
34
- ```python
35
- # 既存 import ブロックに追加(既存行は省略):
36
- from papycli.completion import (
37
- CONFIG_SUBCOMMANDS,
38
- TOP_LEVEL_COMMANDS,
39
- _used_param_names,
40
- completions_for_context,
41
- generate_script,
42
- generate_static_script, # ← 追加
43
- )
44
- ```
45
-
46
- ファイル末尾に以下のクラスを追加する:
47
-
48
- ```python
49
- class TestGenerateStaticScript:
50
- def test_bash_contains_resources(self) -> None:
51
- script = generate_static_script("bash", "papycli", APIDEF, ["petstore"])
52
- assert "/pet/findByStatus" in script
53
- assert "/pet/{petId}" in script
54
-
55
- def test_bash_contains_api_names(self) -> None:
56
- script = generate_static_script("bash", "papycli", APIDEF, ["petstore", "myapi"])
57
- assert "petstore" in script
58
- assert "myapi" in script
59
-
60
- def test_bash_contains_enum_values(self) -> None:
61
- script = generate_static_script("bash", "papycli", APIDEF, ["petstore"])
62
- assert "available" in script
63
- assert "pending" in script
64
- assert "sold" in script
65
-
66
- def test_bash_contains_required_param_marker(self) -> None:
67
- script = generate_static_script("bash", "papycli", APIDEF, ["petstore"])
68
- # POST /pet の name は required → name* が含まれる
69
- assert "name*" in script
70
-
71
- def test_bash_has_completion_function_and_binding(self) -> None:
72
- script = generate_static_script("bash", "papycli", APIDEF, ["petstore"])
73
- assert "_papycli_completion()" in script
74
- assert "complete -o nospace -F _papycli_completion papycli" in script
75
-
76
- def test_bash_no_python_call(self) -> None:
77
- script = generate_static_script("bash", "papycli", APIDEF, ["petstore"])
78
- assert "_complete" not in script
79
-
80
- def test_bash_none_apidef_generates_valid_script(self) -> None:
81
- script = generate_static_script("bash", "papycli", None, None)
82
- assert "_papycli_completion()" in script
83
- assert "get post put patch delete" in script
84
- assert "_complete" not in script
85
-
86
- def test_bash_custom_cmd_name(self) -> None:
87
- script = generate_static_script("bash", "petcli", APIDEF, ["petstore"])
88
- assert "_petcli_completion()" in script
89
- assert "complete -o nospace -F _petcli_completion petcli" in script
90
-
91
- def test_zsh_has_compdef(self) -> None:
92
- script = generate_static_script("zsh", "papycli", APIDEF, ["petstore"])
93
- assert "compdef _papycli papycli" in script
94
- assert "/pet/findByStatus" in script
95
-
96
- def test_zsh_no_python_call(self) -> None:
97
- script = generate_static_script("zsh", "papycli", APIDEF, ["petstore"])
98
- assert "_complete" not in script
99
-
100
- def test_zsh_contains_enum_values(self) -> None:
101
- script = generate_static_script("zsh", "papycli", APIDEF, ["petstore"])
102
- assert "available" in script
103
- ```
104
-
105
- - [ ] **Step 1-2: テスト実行(失敗確認)**
106
-
107
- ```bash
108
- uv run pytest tests/unittest/test_completion.py::TestGenerateStaticScript -v 2>&1 | head -20
109
- ```
110
-
111
- Expected: `ImportError` または `cannot import name 'generate_static_script'`
112
-
113
- - [ ] **Step 1-3: `completion.py` に実装を追加する**
114
-
115
- `src/papycli/completion.py` のファイル末尾(`get_completions` 関数の後)に以下を追加する。
116
-
117
- ```python
118
- # ---------------------------------------------------------------------------
119
- # 静的補完スクリプト生成
120
- # ---------------------------------------------------------------------------
121
-
122
- _STATIC_BASH_TEMPLATE = """\
123
- _@@SAFENAME@@_completion() {
124
- local cur prev pprev
125
- cur="${COMP_WORDS[COMP_CWORD]}"
126
- prev=""
127
- pprev=""
128
- [[ $COMP_CWORD -ge 1 ]] && prev="${COMP_WORDS[COMP_CWORD-1]}"
129
- [[ $COMP_CWORD -ge 2 ]] && pprev="${COMP_WORDS[COMP_CWORD-2]}"
130
-
131
- if [[ ${COMP_CWORD} -eq 1 ]]; then
132
- COMPREPLY=($(compgen -W "get post put patch delete config spec summary" -- "$cur"))
133
- return
134
- fi
135
-
136
- local cmd="${COMP_WORDS[1]}"
137
-
138
- if [[ "$cmd" == "config" ]]; then
139
- case ${COMP_CWORD} in
140
- 2) COMPREPLY=($(compgen -W "add alias completion-script list log remove use" -- "$cur")) ;;
141
- 3) case "${COMP_WORDS[2]}" in
142
- remove|use) COMPREPLY=($(compgen -W "@@API_NAMES@@" -- "$cur")) ;;
143
- add) COMPREPLY=($(compgen -f -- "$cur"))
144
- compopt -o filenames 2>/dev/null ;;
145
- esac ;;
146
- esac
147
- return
148
- fi
149
-
150
- if [[ "$cmd" == "summary" && ${COMP_CWORD} -eq 2 ]]; then
151
- COMPREPLY=($(compgen -W "--csv @@ALL_RESOURCES@@" -- "$cur"))
152
- return
153
- fi
154
-
155
- if [[ "$cmd" == "spec" ]]; then
156
- if [[ ${COMP_CWORD} -eq 2 ]]; then
157
- COMPREPLY=($(compgen -W "--full @@ALL_RESOURCES@@" -- "$cur"))
158
- elif [[ ${COMP_CWORD} -eq 3 && "${COMP_WORDS[2]}" == "--full" ]]; then
159
- COMPREPLY=($(compgen -W "@@ALL_RESOURCES@@" -- "$cur"))
160
- fi
161
- return
162
- fi
163
-
164
- case "$cmd" in get|post|put|patch|delete) ;; *) return ;; esac
165
-
166
- if [[ ${COMP_CWORD} -eq 2 ]]; then
167
- case "$cmd" in
168
- @@METHOD_RESOURCE_CASES@@
169
- esac
170
- return
171
- fi
172
-
173
- local resource="${COMP_WORDS[2]}"
174
- local ctx="${cmd}:${resource}"
175
-
176
- if [[ "$prev" == "-q" ]]; then
177
- case "$ctx" in
178
- @@Q_PARAM_CASES@@
179
- esac
180
- return
181
- fi
182
-
183
- if [[ "$pprev" == "-q" ]]; then
184
- local pname="${prev%\\*}"
185
- case "${ctx}:${pname}" in
186
- @@Q_ENUM_CASES@@
187
- esac
188
- return
189
- fi
190
-
191
- if [[ "$prev" == "-p" ]]; then
192
- case "$ctx" in
193
- @@P_PARAM_CASES@@
194
- esac
195
- return
196
- fi
197
-
198
- if [[ "$pprev" == "-p" ]]; then
199
- local pname="${prev%\\*}"
200
- case "${ctx}:${pname}" in
201
- @@P_ENUM_CASES@@
202
- esac
203
- return
204
- fi
205
-
206
- COMPREPLY=($(compgen -W "-q -p -d -H --summary -v --verbose --check --check-strict --response-check" -- "$cur"))
207
- }
208
-
209
- complete -o nospace -F _@@SAFENAME@@_completion @@CMDNAME@@
210
- """
211
-
212
- _STATIC_ZSH_TEMPLATE = """\
213
- _@@SAFENAME@@() {
214
- local cur="${words[CURRENT]}"
215
- local prev="${words[CURRENT-1]:-}"
216
- local pprev="${words[CURRENT-2]:-}"
217
- local cword=$((CURRENT - 1))
218
- local -a _c
219
-
220
- if [[ $cword -eq 1 ]]; then
221
- _c=(get post put patch delete config spec summary)
222
- _describe 'command' _c && return
223
- fi
224
-
225
- local cmd="${words[2]}"
226
-
227
- if [[ "$cmd" == "config" ]]; then
228
- case $cword in
229
- 2) _c=(add alias completion-script list log remove use)
230
- _describe 'subcommand' _c ;;
231
- 3) case "${words[3]}" in
232
- remove|use) _c=(@@API_NAMES_ZSH@@); _describe 'api' _c ;;
233
- add) _files ;;
234
- esac ;;
235
- esac
236
- return
237
- fi
238
-
239
- if [[ "$cmd" == "summary" && $cword -eq 2 ]]; then
240
- _c=(--csv @@ALL_RESOURCES_ZSH@@)
241
- _describe 'resource' _c
242
- return
243
- fi
244
-
245
- if [[ "$cmd" == "spec" ]]; then
246
- if [[ $cword -eq 2 ]]; then
247
- _c=(--full @@ALL_RESOURCES_ZSH@@)
248
- _describe 'resource' _c
249
- elif [[ $cword -eq 3 && "${words[3]}" == "--full" ]]; then
250
- _c=(@@ALL_RESOURCES_ZSH@@)
251
- _describe 'resource' _c
252
- fi
253
- return
254
- fi
255
-
256
- case "$cmd" in get|post|put|patch|delete) ;; *) return ;; esac
257
-
258
- if [[ $cword -eq 2 ]]; then
259
- case "$cmd" in
260
- @@ZSH_METHOD_RESOURCE_CASES@@
261
- esac
262
- return
263
- fi
264
-
265
- local resource="${words[3]}"
266
- local ctx="${cmd}:${resource}"
267
-
268
- if [[ "$prev" == "-q" ]]; then
269
- case "$ctx" in
270
- @@ZSH_Q_PARAM_CASES@@
271
- esac
272
- return
273
- fi
274
-
275
- if [[ "$pprev" == "-q" ]]; then
276
- local pname="${prev%\\*}"
277
- case "${ctx}:${pname}" in
278
- @@ZSH_Q_ENUM_CASES@@
279
- esac
280
- return
281
- fi
282
-
283
- if [[ "$prev" == "-p" ]]; then
284
- case "$ctx" in
285
- @@ZSH_P_PARAM_CASES@@
286
- esac
287
- return
288
- fi
289
-
290
- if [[ "$pprev" == "-p" ]]; then
291
- local pname="${prev%\\*}"
292
- case "${ctx}:${pname}" in
293
- @@ZSH_P_ENUM_CASES@@
294
- esac
295
- return
296
- fi
297
-
298
- _c=(-q -p -d -H --summary -v --verbose --check --check-strict --response-check)
299
- _describe 'option' _c
300
- }
301
- compdef _@@SAFENAME@@ @@CMDNAME@@
302
- """
303
-
304
-
305
- def _shell_word_list(items: list[str]) -> str:
306
- """スペース区切りの単語列をダブルクォートで囲んで返す(bash compgen -W 用)。"""
307
- escaped = " ".join(w.replace("\\", "\\\\").replace('"', '\\"') for w in items)
308
- return f'"{escaped}"'
309
-
310
-
311
- def _zsh_array_elems(items: list[str]) -> str:
312
- """zsh 配列リテラルの要素部分(括弧なし)を返す。"""
313
- return " ".join(f'"{w}"' for w in items)
314
-
315
-
316
- def _bash_method_resource_cases(apidef: dict[str, Any]) -> str:
317
- lines: list[str] = []
318
- for method in ("get", "post", "put", "patch", "delete"):
319
- resources = sorted(
320
- p for p, ops in apidef.items() if any(o["method"] == method for o in ops)
321
- )
322
- if resources:
323
- lines.append(
324
- f' {method}) COMPREPLY=($(compgen -W {_shell_word_list(resources)} -- "$cur")) ;;'
325
- )
326
- return "\n".join(lines)
327
-
328
-
329
- def _build_param_names(params: list[dict[str, Any]]) -> list[str]:
330
- """required パラメータに * を付けてリストを返す。"""
331
- return (
332
- [p["name"] + "*" for p in params if p.get("required")]
333
- + [p["name"] for p in params if not p.get("required")]
334
- )
335
-
336
-
337
- def _bash_param_cases(apidef: dict[str, Any], kind: str) -> str:
338
- key = "query_parameters" if kind == "query" else "post_parameters"
339
- lines: list[str] = []
340
- for path in sorted(apidef):
341
- for op in apidef[path]:
342
- params = op.get(key, [])
343
- if not params:
344
- continue
345
- method = op["method"]
346
- names = _build_param_names(params)
347
- lines.append(
348
- f' "{method}:{path}") COMPREPLY=($(compgen -W {_shell_word_list(names)} -- "$cur")) ;;'
349
- )
350
- return "\n".join(lines)
351
-
352
-
353
- def _bash_enum_cases(apidef: dict[str, Any], kind: str) -> str:
354
- key = "query_parameters" if kind == "query" else "post_parameters"
355
- lines: list[str] = []
356
- for path in sorted(apidef):
357
- for op in apidef[path]:
358
- method = op["method"]
359
- for p in op.get(key, []):
360
- if "enum" not in p:
361
- continue
362
- vals = [str(v) for v in p["enum"]]
363
- lines.append(
364
- f' "{method}:{path}:{p["name"]}") COMPREPLY=($(compgen -W {_shell_word_list(vals)} -- "$cur")) ;;'
365
- )
366
- return "\n".join(lines)
367
-
368
-
369
- def _zsh_method_resource_cases(apidef: dict[str, Any]) -> str:
370
- lines: list[str] = []
371
- for method in ("get", "post", "put", "patch", "delete"):
372
- resources = sorted(
373
- p for p, ops in apidef.items() if any(o["method"] == method for o in ops)
374
- )
375
- if resources:
376
- lines.append(
377
- f" {method}) _c=({_zsh_array_elems(resources)}); _describe 'resource' _c ;;"
378
- )
379
- return "\n".join(lines)
380
-
381
-
382
- def _zsh_param_cases(apidef: dict[str, Any], kind: str) -> str:
383
- key = "query_parameters" if kind == "query" else "post_parameters"
384
- lines: list[str] = []
385
- for path in sorted(apidef):
386
- for op in apidef[path]:
387
- params = op.get(key, [])
388
- if not params:
389
- continue
390
- method = op["method"]
391
- names = _build_param_names(params)
392
- lines.append(
393
- f' "{method}:{path}") _c=({_zsh_array_elems(names)}); _describe \'\' _c ;;'
394
- )
395
- return "\n".join(lines)
396
-
397
-
398
- def _zsh_enum_cases(apidef: dict[str, Any], kind: str) -> str:
399
- key = "query_parameters" if kind == "query" else "post_parameters"
400
- lines: list[str] = []
401
- for path in sorted(apidef):
402
- for op in apidef[path]:
403
- method = op["method"]
404
- for p in op.get(key, []):
405
- if "enum" not in p:
406
- continue
407
- vals = [str(v) for v in p["enum"]]
408
- lines.append(
409
- f' "{method}:{path}:{p["name"]}") _c=({_zsh_array_elems(vals)}); _describe \'\' _c ;;'
410
- )
411
- return "\n".join(lines)
412
-
413
-
414
- def generate_static_script(
415
- shell: str,
416
- cmd_name: str,
417
- apidef: dict[str, Any] | None,
418
- api_names: list[str] | None,
419
- ) -> str:
420
- """補完データ埋め込み済みの静的シェル補完スクリプトを返す。
421
-
422
- Args:
423
- shell: "bash" または "zsh"
424
- cmd_name: 補完対象のコマンド名
425
- apidef: API 定義 dict。None の場合は API 固有の補完候補なし。
426
- api_names: 登録済み API 名リスト。None の場合は空。
427
-
428
- Raises:
429
- ValueError: cmd_name に安全でない文字が含まれる場合。
430
- """
431
- cmd_name = Path(cmd_name).stem
432
- if not _SAFE_CMD_RE.match(cmd_name):
433
- raise ValueError(
434
- f"Invalid command name '{cmd_name}': "
435
- "must start with a letter or digit, and contain only letters, digits, hyphens, and underscores."
436
- )
437
- safe = cmd_name.replace("-", "_")
438
- names = api_names or []
439
- adef = apidef or {}
440
- all_resources = sorted(adef.keys())
441
-
442
- if shell == "bash":
443
- script = _STATIC_BASH_TEMPLATE
444
- script = script.replace("@@CMDNAME@@", cmd_name)
445
- script = script.replace("@@SAFENAME@@", safe)
446
- script = script.replace("@@API_NAMES@@", " ".join(names))
447
- script = script.replace("@@ALL_RESOURCES@@", " ".join(all_resources))
448
- script = script.replace("@@METHOD_RESOURCE_CASES@@", _bash_method_resource_cases(adef))
449
- script = script.replace("@@Q_PARAM_CASES@@", _bash_param_cases(adef, "query"))
450
- script = script.replace("@@Q_ENUM_CASES@@", _bash_enum_cases(adef, "query"))
451
- script = script.replace("@@P_PARAM_CASES@@", _bash_param_cases(adef, "body"))
452
- script = script.replace("@@P_ENUM_CASES@@", _bash_enum_cases(adef, "body"))
453
- return script
454
-
455
- # zsh
456
- script = _STATIC_ZSH_TEMPLATE
457
- script = script.replace("@@CMDNAME@@", cmd_name)
458
- script = script.replace("@@SAFENAME@@", safe)
459
- script = script.replace("@@API_NAMES_ZSH@@", _zsh_array_elems(names))
460
- script = script.replace("@@ALL_RESOURCES_ZSH@@", _zsh_array_elems(all_resources))
461
- script = script.replace("@@ZSH_METHOD_RESOURCE_CASES@@", _zsh_method_resource_cases(adef))
462
- script = script.replace("@@ZSH_Q_PARAM_CASES@@", _zsh_param_cases(adef, "query"))
463
- script = script.replace("@@ZSH_Q_ENUM_CASES@@", _zsh_enum_cases(adef, "query"))
464
- script = script.replace("@@ZSH_P_PARAM_CASES@@", _zsh_param_cases(adef, "body"))
465
- script = script.replace("@@ZSH_P_ENUM_CASES@@", _zsh_enum_cases(adef, "body"))
466
- return script
467
- ```
468
-
469
- - [ ] **Step 1-4: テスト実行(成功確認)**
470
-
471
- ```bash
472
- uv run pytest tests/unittest/test_completion.py::TestGenerateStaticScript -v
473
- ```
474
-
475
- Expected: 11 tests PASS
476
-
477
- - [ ] **Step 1-5: ruff + mypy チェック**
478
-
479
- ```bash
480
- uv run ruff check src/papycli/completion.py && uv run mypy src/papycli/completion.py
481
- ```
482
-
483
- Expected: no errors / warnings
484
-
485
- - [ ] **Step 1-6: コミット**
486
-
487
- ```bash
488
- git add src/papycli/completion.py tests/unittest/test_completion.py
489
- git commit -m "feat: add generate_static_script for Python-free shell completion"
490
- ```
491
-
492
- ---
493
-
494
- ## Task 2: `cmd_config_completion_script` を静的スクリプト生成に切り替える
495
-
496
- **Files:**
497
- - Modify: `src/papycli/main.py`
498
- - Modify: `tests/unittest/test_main.py`
499
-
500
- - [ ] **Step 2-1: 失敗するテストを書く**
501
-
502
- `tests/unittest/test_main.py` の末尾に追加する。
503
-
504
- ```python
505
- class TestCompletionScriptStatic:
506
- def test_bash_no_python_call(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
507
- """生成スクリプトに _complete 呼び出しが含まれないこと。"""
508
- monkeypatch.setenv("PAPYCLI_CONF_DIR", str(tmp_path))
509
- runner = CliRunner()
510
- result = runner.invoke(cli, ["config", "completion-script", "bash"])
511
- assert result.exit_code == 0
512
- assert "_complete" not in result.output
513
- assert "_papycli_completion()" in result.output
514
-
515
- def test_zsh_no_python_call(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
516
- monkeypatch.setenv("PAPYCLI_CONF_DIR", str(tmp_path))
517
- runner = CliRunner()
518
- result = runner.invoke(cli, ["config", "completion-script", "zsh"])
519
- assert result.exit_code == 0
520
- assert "_complete" not in result.output
521
- assert "compdef _papycli papycli" in result.output
522
-
523
- @pytest.mark.skipif(not PETSTORE_PATH.exists(), reason="petstore-oas3.json not found")
524
- def test_bash_with_apidef_contains_resources(
525
- self, petstore_conf_dir: Path, monkeypatch: pytest.MonkeyPatch
526
- ) -> None:
527
- """apidef がある場合、生成スクリプトにリソースパスが含まれること。"""
528
- monkeypatch.setenv("PAPYCLI_CONF_DIR", str(petstore_conf_dir))
529
- runner = CliRunner()
530
- result = runner.invoke(cli, ["config", "completion-script", "bash"])
531
- assert result.exit_code == 0
532
- assert "/pet" in result.output
533
- assert "/store/inventory" in result.output
534
- ```
535
-
536
- - [ ] **Step 2-2: テスト実行(失敗確認)**
537
-
538
- ```bash
539
- uv run pytest tests/unittest/test_main.py::TestCompletionScriptStatic -v 2>&1 | head -20
540
- ```
541
-
542
- Expected: `test_bash_no_python_call` が FAIL(現状のスクリプトに `_complete` が含まれるため)
543
-
544
- - [ ] **Step 2-3: `main.py` の import と `cmd_config_completion_script` を更新する**
545
-
546
- **import 行の変更:**
547
-
548
- 変更前(`main.py` の `completion` import 行):
549
- ```python
550
- from papycli.completion import _SAFE_CMD_RE, generate_script, get_completions
551
- ```
552
-
553
- 変更後:
554
- ```python
555
- from papycli.completion import _SAFE_CMD_RE, generate_script, generate_static_script, get_completions
556
- ```
557
-
558
- **関数本体の変更:**
559
-
560
- 変更前(`cmd_config_completion_script` 関数本体):
561
- ```python
562
- root_name = click.get_current_context().find_root().info_name or ""
563
- cmd_name = Path(root_name).stem # .stem で Windows の ".exe" 等を除去する
564
- try:
565
- click.echo(generate_script(shell, cmd_name), nl=False)
566
- except ValueError as e:
567
- click.echo(f"Error: {e}", err=True)
568
- sys.exit(1)
569
- ```
570
-
571
- 変更後:
572
- ```python
573
- root_name = click.get_current_context().find_root().info_name or ""
574
- cmd_name = Path(root_name).stem # .stem で Windows の ".exe" 等を除去する
575
- conf_dir = get_conf_dir()
576
- try:
577
- conf = load_conf(conf_dir)
578
- api_names: list[str] = [
579
- k for k in conf if k not in ("default", "aliases") and isinstance(conf[k], dict)
580
- ]
581
- apidef, _ = load_current_apidef(conf_dir, conf=conf)
582
- except Exception:
583
- api_names = []
584
- apidef = None
585
- try:
586
- click.echo(generate_static_script(shell, cmd_name, apidef, api_names), nl=False)
587
- except ValueError as e:
588
- click.echo(f"Error: {e}", err=True)
589
- sys.exit(1)
590
- ```
591
-
592
- - [ ] **Step 2-4: テスト実行(成功確認)**
593
-
594
- ```bash
595
- uv run pytest tests/unittest/test_main.py::TestCompletionScriptStatic -v
596
- ```
597
-
598
- Expected: 3 tests PASS
599
-
600
- - [ ] **Step 2-5: 全ユニットテスト実行(既存テストの破損確認)**
601
-
602
- ```bash
603
- uv run pytest tests/unittest/ -v
604
- ```
605
-
606
- Expected: 全テスト PASS
607
-
608
- - [ ] **Step 2-6: ruff + mypy チェック**
609
-
610
- ```bash
611
- uv run ruff check src/papycli/main.py && uv run mypy src/papycli/main.py
612
- ```
613
-
614
- Expected: no errors / warnings
615
-
616
- - [ ] **Step 2-7: コミット**
617
-
618
- ```bash
619
- git add src/papycli/main.py tests/unittest/test_main.py
620
- git commit -m "feat: switch config completion-script to static script generation"
621
- ```
622
-
623
- ---
624
-
625
- ## Task 3: 全テスト実行と最終確認
626
-
627
- **Files:** 変更なし
628
-
629
- - [ ] **Step 3-1: 全テスト実行**
630
-
631
- ```bash
632
- uv run pytest tests/ -v
633
- ```
634
-
635
- Expected: 全テスト PASS
636
-
637
- - [ ] **Step 3-2: 生成スクリプトの内容確認**
638
-
639
- ```bash
640
- uv run papycli config completion-script bash 2>/dev/null | head -30
641
- ```
642
-
643
- Expected: `_papycli_completion()` 関数の定義が出力される。`_complete` の文字列が含まれない。
644
-
645
- - [ ] **Step 3-3: ruff 全体チェック**
646
-
647
- ```bash
648
- uv run ruff check src/
649
- ```
650
-
651
- Expected: no errors
652
-
653
- ---
654
-
655
- ## 移行メモ(実装者向け)
656
-
657
- 既存ユーザーが古いスクリプト(`papycli _complete` を呼ぶ動的版)を `.bashrc` に設定している場合、papycli をアップグレード後に以下を再実行する必要がある:
658
-
659
- ```bash
660
- eval "$(papycli config completion-script bash)" # bash
661
- eval "$(papycli config completion-script zsh)" # zsh
662
- ```
663
-
664
- また、`config add`・`config use`・`config remove` で API 設定を変更した後も、補完候補を更新するために同コマンドを再実行する必要がある。
@@ -1,188 +0,0 @@
1
- # CLAUDE.md 簡潔化 実装計画
2
-
3
- > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
4
-
5
- **Goal:** CLAUDE.md を約 277 行から約 110 行に削減し、コンテキスト消費を抑える。
6
-
7
- **Architecture:** 1 ファイル (`CLAUDE.md`) を書き換えるだけのドキュメント変更。テストコードなし。削除・圧縮の判断基準は `design/2026-03-28-claude-md-simplification.md` に記載。
8
-
9
- **Tech Stack:** なし(テキスト編集のみ)
10
-
11
- ---
12
-
13
- ### Task 1: CLAUDE.md を簡潔版に書き換える
14
-
15
- **Files:**
16
- - Modify: `CLAUDE.md`
17
-
18
- - [ ] **Step 1: 現在の行数を確認する**
19
-
20
- ```bash
21
- wc -l CLAUDE.md
22
- ```
23
-
24
- Expected: `277 CLAUDE.md`
25
-
26
- - [ ] **Step 2: CLAUDE.md を以下の内容に全置換する**
27
-
28
- ```markdown
29
- # CLAUDE.md
30
-
31
- ## プロジェクト概要
32
-
33
- `papycli` は OpenAPI 3.0 仕様を読み込み、REST API エンドポイントをターミナルから直接呼び出せるインタラクティブな CLI を提供する Python 製ツールです。
34
-
35
- ---
36
-
37
- ## 開発環境
38
-
39
- - Python 3.12 以上 / uv で仮想環境を管理(Linux / macOS のみ)
40
- - テスト: `uv run pytest`
41
- - Lint・フォーマット: `uv run ruff check` / `uv run ruff format`
42
- - 型チェック: `uv run mypy src/`
43
-
44
- ---
45
-
46
- ## 主要モジュール
47
-
48
- - `main.py` — CLI エントリポイント・引数パース
49
- - `init_cmd.py` — `config add`(spec 変換・保存)
50
- - `spec_loader.py` — OpenAPI spec 読み込み・$ref 解決・内部形式変換
51
- - `api_call.py` — HTTP リクエスト実行・パステンプレートマッチング
52
- - `checker.py` — `--check` / `--check-strict` パラメータ検証
53
- - `completion.py` — bash/zsh 補完スクリプト生成
54
- - `config.py` — 設定ファイル読み書き・ログパス管理
55
- - `filters.py` — リクエスト・レスポンスフィルタープラグイン機構
56
- - `response_checker.py` — `--response-check` レスポンス検証
57
- - `summary.py` — summary コマンド・CSV 出力
58
- - `i18n.py` — 日英ヘルプテキスト切り替え
59
-
60
- ---
61
-
62
- ## 内部データフォーマット
63
-
64
- ### API 定義ファイル (`apis/<name>.json`)
65
-
66
- `{ "<path>": [ { "method", "query_parameters", "post_parameters" } ] }` の形式。
67
-
68
- - `method`: `"get"` / `"post"` / `"put"` / `"patch"` / `"delete"`
69
- - `query_parameters` / `post_parameters`: `[{ "name", "type", "required", "enum"(省略可) }]`
70
- - path にはパステンプレート(`/pet/{petId}` 形式)も使用可
71
-
72
- ### 設定ファイル (`papycli.conf`)
73
-
74
- `{ "default": "<api-name>", "<api-name>": { "openapispec", "apidef", "url" } }` の形式。
75
-
76
- ---
77
-
78
- ## CLI 仕様
79
-
80
- ### コマンド構文
81
-
82
- \`\`\`
83
- papycli <method> <resource> [options]
84
- papycli config add <spec-file>
85
- papycli config use <api-name>
86
- papycli config remove <api-name>
87
- papycli config list
88
- papycli config log [PATH] [--unset]
89
- papycli config completion-script <bash|zsh>
90
- papycli spec [resource]
91
- papycli spec --full [resource]
92
- papycli summary [resource] [--csv]
93
- papycli --version
94
- papycli --help / -h
95
- \`\`\`
96
-
97
- ### サポートするメソッド
98
-
99
- `get | post | put | patch | delete` をサポートする。
100
-
101
- ### パステンプレートのマッチング
102
-
103
- リソースパスに数値や文字列が含まれる場合(例:`/pet/99`)、API 定義内のテンプレート(`/pet/{petId}`)にマッチさせ、値を埋め込んでリクエストを送信する。
104
-
105
- ---
106
-
107
- ## 環境変数
108
-
109
- | 変数 | デフォルト | 説明 |
110
- |------|-----------|------|
111
- | `PAPYCLI_CONF_DIR` | `~/.papycli` | 設定ディレクトリのパス |
112
- | `PAPYCLI_CUSTOM_HEADER` | (なし) | 全リクエストに付与するカスタムヘッダー(改行区切りで複数指定可) |
113
-
114
- ---
115
-
116
- ## テスト方針
117
-
118
- - `tests/unittest/` 以下にユニットテストを配置する
119
- - `tests/integration/` 以下に統合テストを配置する
120
- - HTTP リクエストは `responses` ライブラリ等でモックして実テストしない
121
- - OpenAPI spec の変換ロジックは代表的なケースを網羅するテストを書く
122
-
123
- ---
124
-
125
- ## コーディング規約
126
-
127
- - フォーマッタ・Lint は `ruff` を使用する
128
- - 型ヒントを積極的に使用し、`mypy` でチェックを通す
129
- - 関数・モジュールの公開 API にのみ docstring を書く(内部実装には不要)
130
- - エラーメッセージはユーザーが原因を特定しやすい内容にする
131
-
132
- ---
133
-
134
- ## コード調査・編集のワークフロー
135
-
136
- - シンボル操作はファイルを直接読む前にできるだけSerenaを使うこと
137
- - ファイル内容の検索には可能なら `grep` ではなく `rg`(ripgrep)を使うこと
138
-
139
- ---
140
-
141
- ## Git リポジトリ運用 (GitHub)
142
-
143
- ### issue 管理
144
-
145
- - ソースコードやドキュメントの追加・修正は原則として最初に issue を作成し、それに対応する形で行う
146
- - issue には適切なラベルをつける。使用するラベルは以下のいずれか
147
- - 機能以外のバグの場合、`ci`、`chore` などのラベルも追加する
148
-
149
- | ラベル | 用途 |
150
- |---------------|------|
151
- | `feature` | 新機能の追加 |
152
- | `bug` | バグ修正 |
153
- | `refactor` | 機能変更を伴わないリファクタリング |
154
- | `test` | テストコードの追加 |
155
- | `ci` | GitHub ActionsなどContinuous Integrationに関係する変更 |
156
- | `documentation` | ドキュメントのみの変更 |
157
- | `chore` | 上記以外 (ビルド・依存関係・設定等のメンテナンス) |
158
-
159
- ### ブランチ・コミット・PR
160
-
161
- - ソースコード修正は必ず最新の `main` ブランチからピックブランチを作成しておこなう
162
- - ソースコード修正時、異なるタイプの修正 (たとえば機能追加とリファクタリング) は極力コミットを分ける。
163
- - Pythonのソースコードを追加・修正した場合、`ruff` と `mypy` でチェックし、警告がなくなるようにしておく
164
- - コミットメッセージは原則として Conventional Commits に従う
165
- - ユーザーから見て機能に変更がないときは `feat` は使わない
166
- - 破壊的変更を伴う場合、`feat!:` や `fix!` のようにコミットメッセージのタイプに**必ず**`!`を付ける
167
- - `ci` や `chore` のバグ修正の場合、`fix(ci):`、`fix(chore)` のように機能上の不具合修正でないことがわかるように明記する
168
- - コミットに互換性を損なう破壊的変更が含まれる場合、"BREAKING CHANGE:" フッターを**必ず**追加する
169
- - 重要: プルリクエスト (PR) のレビュー指摘に対するコード修正のときだけ Conventional Commits で定義されていない `review:` プレフィクスを付ける(CHANGELOG対象から外すため)
170
- - PR でレビュー指摘を受けた場合、必要であればコードを修正し、修正コミットをプッシュする
171
- - PR で `Nit` の指摘に対しては「このままとします」と回答し、コードは修正しなくてよい
172
- - プッシュ後、修正内容を簡潔にまとめてPRに返信する
173
- ```
174
-
175
- - [ ] **Step 3: 行数を確認する**
176
-
177
- ```bash
178
- wc -l CLAUDE.md
179
- ```
180
-
181
- Expected: 110 行前後(100〜120 行の範囲)
182
-
183
- - [ ] **Step 4: コミットする**
184
-
185
- ```bash
186
- git add CLAUDE.md
187
- git commit -m "docs: simplify CLAUDE.md from 277 to ~110 lines"
188
- ```
@@ -1,100 +0,0 @@
1
- # CLAUDE.md 簡潔化 設計ドキュメント
2
-
3
- ## 目的
4
-
5
- CLAUDE.md がコンテキストを圧迫しないよう、約 277 行から約 100 行に削減する。
6
- 詳細設計情報は `design_doc.md`(コンテキスト外)に既に存在するため、
7
- CLAUDE.md は「Claude が自力で導出できない情報」と「行動ルール」だけに絞る。
8
-
9
- ## 方針
10
-
11
- 削除・圧縮の判断基準:
12
- - **削除**: Glob/ls/コード読解で容易に確認できる情報
13
- - **圧縮**: 有用だが現在の記述量が過剰な情報
14
- - **維持**: 行動ルール・非自明な仕様・コンテキスト節約後も価値が高いもの
15
-
16
- ## セクション別の変更内容
17
-
18
- ### 開発環境(22行 → 8行)
19
-
20
- ツール表とセットアップ節を削除し、`uv run` コマンド 3 つだけ箇条書きで残す。
21
-
22
- ```markdown
23
- ## 開発環境
24
-
25
- - Python 3.12 以上 / uv で仮想環境を管理(Linux / macOS のみ)
26
- - テスト: `uv run pytest`
27
- - Lint・フォーマット: `uv run ruff check` / `uv run ruff format`
28
- - 型チェック: `uv run mypy src/`
29
- ```
30
-
31
- ### ディレクトリ構成ツリー(42行 → 削除)
32
-
33
- 全ファイル名を列挙したツリーは Claude が Glob/ls で確認できるため削除する。
34
-
35
- ### 主要モジュール説明(32行 → 12行)
36
-
37
- 詳細説明をやめ、`file.py — 役割` の1行形式に統一する。
38
-
39
- ```markdown
40
- ## 主要モジュール
41
-
42
- - `main.py` — CLI エントリポイント・引数パース
43
- - `init_cmd.py` — `config add`(spec 変換・保存)
44
- - `spec_loader.py` — OpenAPI spec 読み込み・$ref 解決・内部形式変換
45
- - `api_call.py` — HTTP リクエスト実行・パステンプレートマッチング
46
- - `checker.py` — `--check` / `--check-strict` パラメータ検証
47
- - `completion.py` — bash/zsh 補完スクリプト生成
48
- - `config.py` — 設定ファイル読み書き・ログパス管理
49
- - `filters.py` — リクエスト・レスポンスフィルタープラグイン機構
50
- - `response_checker.py` — `--response-check` レスポンス検証
51
- - `spec_loader.py` — OpenAPI spec 読み込み・$ref 解決
52
- - `summary.py` — summary コマンド・CSV 出力
53
- - `i18n.py` — 日英ヘルプテキスト切り替え
54
- ```
55
-
56
- ### 内部データフォーマット(40行 → 15行)
57
-
58
- JSON サンプルを削除し、スキーマをインライン記法+箇条書きで表現する。
59
-
60
- ```markdown
61
- ## 内部データフォーマット
62
-
63
- ### API 定義ファイル (`apis/<name>.json`)
64
-
65
- `{ "<path>": [ { "method", "query_parameters", "post_parameters" } ] }` の形式。
66
- - `method`: `"get"` / `"post"` / `"put"` / `"patch"` / `"delete"`
67
- - `query_parameters` / `post_parameters`: `[{ "name", "type", "required", "enum"(省略可) }]`
68
- - path にはパステンプレート(`/pet/{petId}` 形式)も使用可
69
-
70
- ### 設定ファイル (`papycli.conf`)
71
-
72
- `{ "default": "<api-name>", "<api-name>": { "openapispec", "apidef", "url" } }` の形式。
73
- ```
74
-
75
- ### CLI 仕様(27行 → 15行)
76
-
77
- コマンド一覧(15行)とパステンプレートマッチング(2行)を維持する。
78
- パラメータ詳細(`-q`, `-p`, `-d`, `-H`, `--check`, `--response-check` の説明10行)は
79
- `--help` で確認できるため削除する。
80
-
81
- ### 環境変数・テスト方針・コーディング規約・調査ワークフロー・Git 運用
82
-
83
- 変更なし。
84
-
85
- ## 削減後の想定行数
86
-
87
- | セクション | 現在 | 変更後 |
88
- |---|---|---|
89
- | プロジェクト概要 | 5 | 5 |
90
- | 開発環境 | 22 | 8 |
91
- | ディレクトリ構成ツリー | 42 | 0 |
92
- | 主要モジュール | 32 | 14 |
93
- | 内部データフォーマット | 40 | 15 |
94
- | CLI 仕様 | 27 | 15 |
95
- | 環境変数 | 5 | 5 |
96
- | テスト方針 | 6 | 6 |
97
- | コーディング規約 | 6 | 6 |
98
- | 調査ワークフロー | 4 | 4 |
99
- | Git 運用 | 30 | 30 |
100
- | **合計** | **277** | **108** |
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