papycli 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.
- papycli-0.4.0/.claude/settings.local.json +7 -0
- papycli-0.4.0/.gitignore +207 -0
- papycli-0.4.0/.python-version +1 -0
- papycli-0.4.0/CLAUDE.md +191 -0
- papycli-0.4.0/LICENSE +21 -0
- papycli-0.4.0/PKG-INFO +252 -0
- papycli-0.4.0/README.ja.md +223 -0
- papycli-0.4.0/README.md +225 -0
- papycli-0.4.0/design_doc.md +237 -0
- papycli-0.4.0/examples/docker-compose.yml +5 -0
- papycli-0.4.0/examples/petstore-oas3.json +1239 -0
- papycli-0.4.0/pyproject.toml +66 -0
- papycli-0.4.0/src/papycli/__init__.py +5 -0
- papycli-0.4.0/src/papycli/api_call.py +192 -0
- papycli-0.4.0/src/papycli/completion.py +168 -0
- papycli-0.4.0/src/papycli/config.py +93 -0
- papycli-0.4.0/src/papycli/init_cmd.py +43 -0
- papycli-0.4.0/src/papycli/main.py +231 -0
- papycli-0.4.0/src/papycli/spec_loader.py +142 -0
- papycli-0.4.0/src/papycli/summary.py +110 -0
- papycli-0.4.0/tests/conftest.py +1 -0
- papycli-0.4.0/tests/test_api_call.py +285 -0
- papycli-0.4.0/tests/test_completion.py +294 -0
- papycli-0.4.0/tests/test_config.py +91 -0
- papycli-0.4.0/tests/test_init_cmd.py +129 -0
- papycli-0.4.0/tests/test_main.py +431 -0
- papycli-0.4.0/tests/test_spec_loader.py +280 -0
- papycli-0.4.0/tests/test_summary.py +222 -0
- papycli-0.4.0/uv.lock +474 -0
papycli-0.4.0/.gitignore
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[codz]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
.coverage
|
|
44
|
+
.coverage.*
|
|
45
|
+
.cache
|
|
46
|
+
nosetests.xml
|
|
47
|
+
coverage.xml
|
|
48
|
+
*.cover
|
|
49
|
+
*.py.cover
|
|
50
|
+
.hypothesis/
|
|
51
|
+
.pytest_cache/
|
|
52
|
+
cover/
|
|
53
|
+
|
|
54
|
+
# Translations
|
|
55
|
+
*.mo
|
|
56
|
+
*.pot
|
|
57
|
+
|
|
58
|
+
# Django stuff:
|
|
59
|
+
*.log
|
|
60
|
+
local_settings.py
|
|
61
|
+
db.sqlite3
|
|
62
|
+
db.sqlite3-journal
|
|
63
|
+
|
|
64
|
+
# Flask stuff:
|
|
65
|
+
instance/
|
|
66
|
+
.webassets-cache
|
|
67
|
+
|
|
68
|
+
# Scrapy stuff:
|
|
69
|
+
.scrapy
|
|
70
|
+
|
|
71
|
+
# Sphinx documentation
|
|
72
|
+
docs/_build/
|
|
73
|
+
|
|
74
|
+
# PyBuilder
|
|
75
|
+
.pybuilder/
|
|
76
|
+
target/
|
|
77
|
+
|
|
78
|
+
# Jupyter Notebook
|
|
79
|
+
.ipynb_checkpoints
|
|
80
|
+
|
|
81
|
+
# IPython
|
|
82
|
+
profile_default/
|
|
83
|
+
ipython_config.py
|
|
84
|
+
|
|
85
|
+
# pyenv
|
|
86
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
87
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
88
|
+
# .python-version
|
|
89
|
+
|
|
90
|
+
# pipenv
|
|
91
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
92
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
93
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
94
|
+
# install all needed dependencies.
|
|
95
|
+
#Pipfile.lock
|
|
96
|
+
|
|
97
|
+
# UV
|
|
98
|
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
99
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
100
|
+
# commonly ignored for libraries.
|
|
101
|
+
#uv.lock
|
|
102
|
+
|
|
103
|
+
# poetry
|
|
104
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
105
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
106
|
+
# commonly ignored for libraries.
|
|
107
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
108
|
+
#poetry.lock
|
|
109
|
+
#poetry.toml
|
|
110
|
+
|
|
111
|
+
# pdm
|
|
112
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
113
|
+
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
|
|
114
|
+
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
|
|
115
|
+
#pdm.lock
|
|
116
|
+
#pdm.toml
|
|
117
|
+
.pdm-python
|
|
118
|
+
.pdm-build/
|
|
119
|
+
|
|
120
|
+
# pixi
|
|
121
|
+
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
|
|
122
|
+
#pixi.lock
|
|
123
|
+
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
|
|
124
|
+
# in the .venv directory. It is recommended not to include this directory in version control.
|
|
125
|
+
.pixi
|
|
126
|
+
|
|
127
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
128
|
+
__pypackages__/
|
|
129
|
+
|
|
130
|
+
# Celery stuff
|
|
131
|
+
celerybeat-schedule
|
|
132
|
+
celerybeat.pid
|
|
133
|
+
|
|
134
|
+
# SageMath parsed files
|
|
135
|
+
*.sage.py
|
|
136
|
+
|
|
137
|
+
# Environments
|
|
138
|
+
.env
|
|
139
|
+
.envrc
|
|
140
|
+
.venv
|
|
141
|
+
env/
|
|
142
|
+
venv/
|
|
143
|
+
ENV/
|
|
144
|
+
env.bak/
|
|
145
|
+
venv.bak/
|
|
146
|
+
|
|
147
|
+
# Spyder project settings
|
|
148
|
+
.spyderproject
|
|
149
|
+
.spyproject
|
|
150
|
+
|
|
151
|
+
# Rope project settings
|
|
152
|
+
.ropeproject
|
|
153
|
+
|
|
154
|
+
# mkdocs documentation
|
|
155
|
+
/site
|
|
156
|
+
|
|
157
|
+
# mypy
|
|
158
|
+
.mypy_cache/
|
|
159
|
+
.dmypy.json
|
|
160
|
+
dmypy.json
|
|
161
|
+
|
|
162
|
+
# Pyre type checker
|
|
163
|
+
.pyre/
|
|
164
|
+
|
|
165
|
+
# pytype static type analyzer
|
|
166
|
+
.pytype/
|
|
167
|
+
|
|
168
|
+
# Cython debug symbols
|
|
169
|
+
cython_debug/
|
|
170
|
+
|
|
171
|
+
# PyCharm
|
|
172
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
173
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
174
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
175
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
176
|
+
#.idea/
|
|
177
|
+
|
|
178
|
+
# Abstra
|
|
179
|
+
# Abstra is an AI-powered process automation framework.
|
|
180
|
+
# Ignore directories containing user credentials, local state, and settings.
|
|
181
|
+
# Learn more at https://abstra.io/docs
|
|
182
|
+
.abstra/
|
|
183
|
+
|
|
184
|
+
# Visual Studio Code
|
|
185
|
+
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
|
|
186
|
+
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
|
187
|
+
# and can be added to the global gitignore or merged into this file. However, if you prefer,
|
|
188
|
+
# you could uncomment the following to ignore the entire vscode folder
|
|
189
|
+
# .vscode/
|
|
190
|
+
|
|
191
|
+
# Ruff stuff:
|
|
192
|
+
.ruff_cache/
|
|
193
|
+
|
|
194
|
+
# PyPI configuration file
|
|
195
|
+
.pypirc
|
|
196
|
+
|
|
197
|
+
# Cursor
|
|
198
|
+
# Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to
|
|
199
|
+
# exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
|
|
200
|
+
# refer to https://docs.cursor.com/context/ignore-files
|
|
201
|
+
.cursorignore
|
|
202
|
+
.cursorindexingignore
|
|
203
|
+
|
|
204
|
+
# Marimo
|
|
205
|
+
marimo/_static/
|
|
206
|
+
marimo/_lsp/
|
|
207
|
+
__marimo__/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12
|
papycli-0.4.0/CLAUDE.md
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
## プロジェクト概要
|
|
4
|
+
|
|
5
|
+
`papycli` は OpenAPI 3.0 仕様を読み込み、REST API エンドポイントをターミナルから直接呼び出せるインタラクティブな CLI を提供する Python 製ツールです。
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 開発環境
|
|
10
|
+
|
|
11
|
+
- Python 3.12 以上
|
|
12
|
+
- 依存ライブラリは `pyproject.toml` で管理する
|
|
13
|
+
|
|
14
|
+
### セットアップ
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pip install -e ".[dev]"
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### 開発用ツール
|
|
21
|
+
|
|
22
|
+
| ツール | 用途 |
|
|
23
|
+
|--------|------|
|
|
24
|
+
| `pytest` | テスト実行 |
|
|
25
|
+
| `ruff` | Lint + フォーマット |
|
|
26
|
+
| `mypy` | 型チェック |
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## アーキテクチャ
|
|
31
|
+
|
|
32
|
+
### ディレクトリ構成
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
papycli/
|
|
36
|
+
├── src/
|
|
37
|
+
│ └── papycli/
|
|
38
|
+
│ ├── __init__.py
|
|
39
|
+
│ ├── main.py # エントリポイント・引数パース
|
|
40
|
+
│ ├── init_cmd.py # --init コマンド(spec の変換・保存)
|
|
41
|
+
│ ├── api_call.py # HTTP リクエスト実行
|
|
42
|
+
│ ├── completion.py # シェル補完スクリプト生成
|
|
43
|
+
│ ├── config.py # 設定ファイルの読み書き
|
|
44
|
+
│ ├── spec_loader.py # OpenAPI spec の読み込み・$ref 解決
|
|
45
|
+
│ └── summary.py # --summary / --summary-csv
|
|
46
|
+
├── tests/
|
|
47
|
+
├── examples/
|
|
48
|
+
│ ├── docker-compose.yml
|
|
49
|
+
│ └── petstore-oas3.json
|
|
50
|
+
├── pyproject.toml
|
|
51
|
+
├── README.md
|
|
52
|
+
└── CLAUDE.md
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### 主要モジュール
|
|
56
|
+
|
|
57
|
+
**`main.py`** — CLI エントリポイント
|
|
58
|
+
引数をパースし、各コマンド(`init`、`use`、`conf`、`summary`、`completion-script`、メソッド呼び出し)に処理を委譲する。シェル補完用の `_complete` 内部コマンドもここで定義する。
|
|
59
|
+
|
|
60
|
+
**`init_cmd.py`** — API 初期化
|
|
61
|
+
OpenAPI spec ファイルを受け取り、`$ref` を解決した上で papycli 内部の API 定義フォーマットに変換し、`$PAPYCLI_CONF_DIR/apis/<name>.json` に保存する。設定ファイル (`papycli.conf`) も更新する。
|
|
62
|
+
|
|
63
|
+
**`spec_loader.py`** — spec 読み込み・変換
|
|
64
|
+
OpenAPI spec の JSON/YAML を読み込み、`$ref` を再帰的に解決して、papycli の内部フォーマット(後述)に変換する。Python 標準ライブラリのみ(または最小限の依存)で実装する。
|
|
65
|
+
|
|
66
|
+
**`api_call.py`** — HTTP リクエスト実行
|
|
67
|
+
メソッド・リソースパス・オプションを受け取り、`requests` ライブラリで HTTP リクエストを実行する。パステンプレート(`/pet/{petId}`)のマッチングと値の埋め込みも担当する。
|
|
68
|
+
|
|
69
|
+
**`completion.py`** — シェル補完
|
|
70
|
+
bash / zsh 向けの補完スクリプトを生成する。補完の候補はメソッド、リソースパス、パラメータ名、enum 値の順にコンテキストに応じて提供する。
|
|
71
|
+
|
|
72
|
+
**`config.py`** — 設定管理
|
|
73
|
+
`papycli.conf` の読み書きと、`PAPYCLI_CONF_DIR` 環境変数の解決を行う。
|
|
74
|
+
|
|
75
|
+
**`summary.py`** — サマリー表示
|
|
76
|
+
登録済み API のエンドポイント一覧を整形して出力する。`--summary-csv` では CSV 形式で出力する。
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## 内部データフォーマット
|
|
81
|
+
|
|
82
|
+
### API 定義ファイル (`apis/<name>.json`)
|
|
83
|
+
|
|
84
|
+
```json
|
|
85
|
+
{
|
|
86
|
+
"/pet": [
|
|
87
|
+
{
|
|
88
|
+
"method": "post",
|
|
89
|
+
"query_parameters": [],
|
|
90
|
+
"post_parameters": [
|
|
91
|
+
{"name": "name", "type": "string", "required": true},
|
|
92
|
+
{"name": "status", "type": "string", "required": false, "enum": ["available", "pending", "sold"]},
|
|
93
|
+
{"name": "photoUrls", "type": "array", "required": true}
|
|
94
|
+
]
|
|
95
|
+
}
|
|
96
|
+
],
|
|
97
|
+
"/pet/findByStatus": [
|
|
98
|
+
{
|
|
99
|
+
"method": "get",
|
|
100
|
+
"query_parameters": [
|
|
101
|
+
{"name": "status", "type": "string", "required": false, "enum": ["available", "pending", "sold"]}
|
|
102
|
+
],
|
|
103
|
+
"post_parameters": []
|
|
104
|
+
}
|
|
105
|
+
],
|
|
106
|
+
"/pet/{petId}": [
|
|
107
|
+
{
|
|
108
|
+
"method": "get",
|
|
109
|
+
"query_parameters": [],
|
|
110
|
+
"post_parameters": []
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"method": "delete",
|
|
114
|
+
"query_parameters": [],
|
|
115
|
+
"post_parameters": []
|
|
116
|
+
}
|
|
117
|
+
]
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### 設定ファイル (`papycli.conf`)
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"default": "petstore",
|
|
126
|
+
"petstore": {
|
|
127
|
+
"openapispec": "petstore.json",
|
|
128
|
+
"apidef": "petstore.json",
|
|
129
|
+
"url": "http://localhost:8080/api/v3"
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## CLI 仕様
|
|
137
|
+
|
|
138
|
+
### コマンド構文
|
|
139
|
+
|
|
140
|
+
```
|
|
141
|
+
papycli <method> <resource> [options]
|
|
142
|
+
papycli init <spec-file>
|
|
143
|
+
papycli use <api-name>
|
|
144
|
+
papycli conf
|
|
145
|
+
papycli summary [resource] [--csv]
|
|
146
|
+
papycli completion-script <bash|zsh>
|
|
147
|
+
papycli --version
|
|
148
|
+
papycli --help / -h
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### サポートするメソッド
|
|
152
|
+
|
|
153
|
+
`get | post | put | patch | delete` をサポートする。
|
|
154
|
+
|
|
155
|
+
### パラメータ処理
|
|
156
|
+
|
|
157
|
+
- `-q <name> <value>` — URL クエリパラメータ。同じ名前を繰り返し可能(`?status=a&status=b`)
|
|
158
|
+
- `-p <name> <value>` — JSON ボディパラメータ。同じキーを繰り返すと配列を構築する
|
|
159
|
+
- `-p <name.subname> <value>` — ドット記法で 1 レベルのネストオブジェクトを構築する
|
|
160
|
+
- `-d <json>` — 生の JSON 文字列。`-p` オプションを上書きする
|
|
161
|
+
- `-H <header: value>` — カスタム HTTP ヘッダー
|
|
162
|
+
|
|
163
|
+
### パステンプレートのマッチング
|
|
164
|
+
|
|
165
|
+
リソースパスに数値や文字列が含まれる場合(例:`/pet/99`)、API 定義内のテンプレート(`/pet/{petId}`)にマッチさせ、値を埋め込んでリクエストを送信する。
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## 環境変数
|
|
170
|
+
|
|
171
|
+
| 変数 | デフォルト | 説明 |
|
|
172
|
+
|------|-----------|------|
|
|
173
|
+
| `PAPYCLI_CONF_DIR` | `~/.papycli` | 設定ディレクトリのパス |
|
|
174
|
+
| `PAPYCLI_CUSTOM_HEADER` | (なし) | 全リクエストに付与するカスタムヘッダー(改行区切りで複数指定可) |
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## テスト方針
|
|
179
|
+
|
|
180
|
+
- `tests/` 以下にユニットテストを配置する
|
|
181
|
+
- HTTP リクエストは `responses` ライブラリ等でモックして実テストしない
|
|
182
|
+
- OpenAPI spec の変換ロジックは代表的なケースを網羅するテストを書く
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## コーディング規約
|
|
187
|
+
|
|
188
|
+
- フォーマッタ・Lint は `ruff` を使用する
|
|
189
|
+
- 型ヒントを積極的に使用し、`mypy` でチェックを通す
|
|
190
|
+
- 関数・モジュールの公開 API にのみ docstring を書く(内部実装には不要)
|
|
191
|
+
- エラーメッセージはユーザーが原因を特定しやすい内容にする
|
papycli-0.4.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Taro Monji
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
papycli-0.4.0/PKG-INFO
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: papycli
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: A CLI tool to call REST APIs defined in OpenAPI 3.0 specs
|
|
5
|
+
Project-URL: Homepage, https://github.com/tmonj1/papycli
|
|
6
|
+
Project-URL: Repository, https://github.com/tmonj1/papycli
|
|
7
|
+
Project-URL: Bug Tracker, https://github.com/tmonj1/papycli/issues
|
|
8
|
+
Author-email: tmonj1 <tmonj1@gmail.com>
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: api,cli,http,openapi,rest
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
20
|
+
Classifier: Topic :: Utilities
|
|
21
|
+
Requires-Python: >=3.12
|
|
22
|
+
Requires-Dist: click>=8.1
|
|
23
|
+
Requires-Dist: pyyaml>=6.0
|
|
24
|
+
Requires-Dist: requests>=2.32
|
|
25
|
+
Requires-Dist: rich>=13.0
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
|
|
28
|
+
# papycli — Python CLI for OpenAPI 3.0 REST APIs
|
|
29
|
+
|
|
30
|
+
`papycli` is an interactive CLI that reads OpenAPI 3.0 specs and lets you call REST API endpoints directly from the terminal.
|
|
31
|
+
|
|
32
|
+
## Features
|
|
33
|
+
|
|
34
|
+
- Auto-generates a CLI from any OpenAPI 3.0 spec
|
|
35
|
+
- Shell completion for bash and zsh
|
|
36
|
+
- Register and switch between multiple APIs
|
|
37
|
+
|
|
38
|
+
## Requirements
|
|
39
|
+
|
|
40
|
+
| Item | Notes |
|
|
41
|
+
|------|-------|
|
|
42
|
+
| Python | 3.12 or later |
|
|
43
|
+
|
|
44
|
+
No external tools (e.g. `jq`) required. Works with Python and pip alone.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Installation
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pip install papycli
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Enable Shell Completion
|
|
55
|
+
|
|
56
|
+
**bash:**
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
# Add to ~/.bashrc or ~/.bash_profile
|
|
60
|
+
eval "$(papycli completion-script bash)"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**zsh:**
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# Add to ~/.zshrc
|
|
67
|
+
eval "$(papycli completion-script zsh)"
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Restart your shell or run `source ~/.bashrc` / `source ~/.zshrc` to apply.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Quick Start — Petstore Demo
|
|
75
|
+
|
|
76
|
+
This repository includes a demo using the [Swagger Petstore](https://github.com/swagger-api/swagger-petstore).
|
|
77
|
+
|
|
78
|
+
### 1. Start the Petstore server
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
docker compose -f examples/docker-compose.yml up -d
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
The API will be available at `http://localhost:8080/api/v3/`.
|
|
85
|
+
|
|
86
|
+
### 2. Register the API
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
papycli init examples/petstore-oas3.json
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### 3. Try some commands
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
# List available endpoints
|
|
96
|
+
papycli summary
|
|
97
|
+
|
|
98
|
+
# GET /store/inventory
|
|
99
|
+
papycli get /store/inventory
|
|
100
|
+
|
|
101
|
+
# GET with a path parameter
|
|
102
|
+
papycli get /pet/99
|
|
103
|
+
|
|
104
|
+
# GET with a query parameter
|
|
105
|
+
papycli get /pet/findByStatus -q status available
|
|
106
|
+
|
|
107
|
+
# POST with body parameters
|
|
108
|
+
papycli post /pet -p name "My Dog" -p status available -p photoUrls "http://example.com/photo.jpg"
|
|
109
|
+
|
|
110
|
+
# POST with a raw JSON body
|
|
111
|
+
papycli post /pet -d '{"name": "My Dog", "status": "available", "photoUrls": ["http://example.com/photo.jpg"]}'
|
|
112
|
+
|
|
113
|
+
# Array parameter (repeat the same key)
|
|
114
|
+
papycli put /pet -p id 1 -p name "My Dog" -p photoUrls "http://example.com/a.jpg" -p photoUrls "http://example.com/b.jpg" -p status available
|
|
115
|
+
|
|
116
|
+
# Nested object (dot notation)
|
|
117
|
+
papycli put /pet -p id 1 -p name "My Dog" -p category.id 2 -p category.name "Dogs" -p photoUrls "http://example.com/photo.jpg" -p status available
|
|
118
|
+
|
|
119
|
+
# DELETE /pet/{petId}
|
|
120
|
+
papycli delete /pet/1
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### 4. Tab completion
|
|
124
|
+
|
|
125
|
+
Once shell completion is enabled, tab completion is available:
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
$ papycli <TAB>
|
|
129
|
+
get post put delete patch
|
|
130
|
+
|
|
131
|
+
$ papycli get <TAB>
|
|
132
|
+
/pet/findByStatus /pet/{petId} /store/inventory ...
|
|
133
|
+
|
|
134
|
+
$ papycli get /pet/findByStatus <TAB>
|
|
135
|
+
-q --summary --help
|
|
136
|
+
|
|
137
|
+
$ papycli get /pet/findByStatus -q <TAB>
|
|
138
|
+
status
|
|
139
|
+
|
|
140
|
+
$ papycli get /pet/findByStatus -q status <TAB>
|
|
141
|
+
available pending sold
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Adding Your Own API
|
|
147
|
+
|
|
148
|
+
### Step 1 — Run `init`
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
papycli init your-api-spec.json
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
This command will:
|
|
155
|
+
|
|
156
|
+
1. Resolve all `$ref` references in the OpenAPI spec
|
|
157
|
+
2. Convert the spec to papycli's internal API definition format
|
|
158
|
+
3. Save the result to `$PAPYCLI_CONF_DIR/apis/<name>.json`
|
|
159
|
+
4. Create or update `$PAPYCLI_CONF_DIR/papycli.conf`
|
|
160
|
+
|
|
161
|
+
The API name is derived from the filename (e.g. `your-api-spec.json` → `your-api-spec`).
|
|
162
|
+
|
|
163
|
+
### Step 2 — Set the base URL
|
|
164
|
+
|
|
165
|
+
If the spec contains `servers[0].url`, it is used automatically. Otherwise, edit `$PAPYCLI_CONF_DIR/papycli.conf` and set the `url` field:
|
|
166
|
+
|
|
167
|
+
```json
|
|
168
|
+
{
|
|
169
|
+
"default": "your-api-spec",
|
|
170
|
+
"your-api-spec": {
|
|
171
|
+
"openapispec": "your-api-spec.json",
|
|
172
|
+
"apidef": "your-api-spec.json",
|
|
173
|
+
"url": "https://your-api-base-url/"
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Managing Multiple APIs
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
# Register multiple APIs
|
|
182
|
+
papycli init petstore-oas3.json
|
|
183
|
+
papycli init myapi.json
|
|
184
|
+
|
|
185
|
+
# Switch the active API
|
|
186
|
+
papycli use myapi
|
|
187
|
+
|
|
188
|
+
# Show registered APIs and the current default
|
|
189
|
+
papycli conf
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## Reference
|
|
195
|
+
|
|
196
|
+
```
|
|
197
|
+
# API management commands
|
|
198
|
+
papycli init <spec-file> Initialize an API from an OpenAPI spec file
|
|
199
|
+
papycli use <api-name> Switch the active API
|
|
200
|
+
papycli conf Show current configuration
|
|
201
|
+
papycli summary [resource] List available endpoints (filter by resource prefix)
|
|
202
|
+
Required params marked with *, array params with []
|
|
203
|
+
papycli summary --csv Output endpoints in CSV format
|
|
204
|
+
papycli completion-script <bash|zsh> Print a shell completion script
|
|
205
|
+
|
|
206
|
+
# API call commands
|
|
207
|
+
papycli <method> <resource> [options]
|
|
208
|
+
|
|
209
|
+
Methods:
|
|
210
|
+
get | post | put | patch | delete
|
|
211
|
+
|
|
212
|
+
Options:
|
|
213
|
+
-H <header: value> Custom HTTP header (repeatable)
|
|
214
|
+
-q <name> <value> Query parameter (repeatable)
|
|
215
|
+
-p <name> <value> Body parameter (repeatable)
|
|
216
|
+
- Repeat the same key to build a JSON array:
|
|
217
|
+
-p tags foo -p tags bar → {"tags":["foo","bar"]}
|
|
218
|
+
- Use dot notation to build a nested object:
|
|
219
|
+
-p category.id 1 -p category.name Dogs
|
|
220
|
+
→ {"category":{"id":"1","name":"Dogs"}}
|
|
221
|
+
-d <json> Raw JSON body (overrides -p)
|
|
222
|
+
--summary Show endpoint info without sending a request
|
|
223
|
+
--version Show version
|
|
224
|
+
--help / -h Show help
|
|
225
|
+
|
|
226
|
+
Environment variables:
|
|
227
|
+
PAPYCLI_CONF_DIR Path to the config directory (default: ~/.papycli)
|
|
228
|
+
PAPYCLI_CUSTOM_HEADER Custom HTTP headers applied to every request.
|
|
229
|
+
Separate multiple headers with newlines:
|
|
230
|
+
export PAPYCLI_CUSTOM_HEADER=$'Authorization: Bearer token\nX-Tenant: acme'
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## Limitations
|
|
236
|
+
|
|
237
|
+
- Request bodies are `application/json` only
|
|
238
|
+
- Array parameters support scalar element types only (arrays of objects are not supported)
|
|
239
|
+
- Dot notation for nested objects supports one level of nesting only
|
|
240
|
+
- Pass auth headers via `-H "Authorization: Bearer token"` or the `PAPYCLI_CUSTOM_HEADER` env var
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## Development
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
git clone https://github.com/tmonj1/papycli.git
|
|
248
|
+
cd papycli
|
|
249
|
+
pip install -e ".[dev]"
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
See [CLAUDE.md](CLAUDE.md) for details.
|