insightfactory-cli 1.0.1.dev5__tar.gz → 1.0.1.dev9__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.
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/.github/workflows/release.yml +3 -1
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/CLAUDE.md +9 -4
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/PKG-INFO +39 -15
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/README.md +38 -14
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/pyproject.toml +1 -1
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/src/if_cli/commands/api.py +22 -5
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/tests/test_api.py +40 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/.github/workflows/ci.yml +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/.github/workflows/claude.yml +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/.gitignore +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/.python-version +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/AGENTS.md +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/src/if_cli/__init__.py +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/src/if_cli/__main__.py +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/src/if_cli/cache.py +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/src/if_cli/cli.py +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/src/if_cli/colour.py +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/src/if_cli/commands/__init__.py +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/src/if_cli/commands/config.py +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/src/if_cli/commands/login.py +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/src/if_cli/commands/logout.py +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/src/if_cli/commands/profiles.py +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/src/if_cli/commands/set_token.py +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/src/if_cli/commands/token.py +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/src/if_cli/config.py +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/src/if_cli/constants.py +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/src/if_cli/http.py +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/src/if_cli/main.py +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/src/if_cli/oauth.py +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/src/if_cli/runtime.py +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/tests/__init__.py +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/tests/cache_writer.py +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/tests/conftest.py +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/tests/helpers.py +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/tests/servers.py +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/tests/test_api_command.py +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/tests/test_cache.py +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/tests/test_cli.py +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/tests/test_config.py +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/tests/test_config_command.py +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/tests/test_login.py +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/tests/test_oauth.py +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/tests/test_oauth_flow.py +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/tests/test_profiles.py +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/tests/test_programmatic_api.py +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/tests/test_runtime.py +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/tests/test_set_token.py +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/tests/test_token.py +0 -0
- {insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/uv.lock +0 -0
{insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/.github/workflows/release.yml
RENAMED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
name: release
|
|
2
2
|
|
|
3
|
-
# CD:
|
|
3
|
+
# CD: a push to develop publishes a `.dev<run_number>` pre-release; a `v*` tag
|
|
4
|
+
# publishes the release. A merge to main runs CI and publishes nothing -- see
|
|
5
|
+
# if_s_insightfactory_cli.yml for why releasing is a deliberate tag push.
|
|
4
6
|
# Verify + build live in insightfactory-ai/if_sre_github_actions
|
|
5
7
|
# (if_s_insightfactory_cli.yml). The publish job stays here because PyPI
|
|
6
8
|
# Trusted Publishing is registered for this repository, workflow `release.yml`,
|
|
@@ -9,6 +9,7 @@ the `if-cli` executable. It uses Python 3.10+, uv, pytest, ruff, and ty.
|
|
|
9
9
|
uv sync
|
|
10
10
|
uv run pytest
|
|
11
11
|
uv run ruff check .
|
|
12
|
+
uv run ruff format --check .
|
|
12
13
|
uv run ty check
|
|
13
14
|
```
|
|
14
15
|
|
|
@@ -22,7 +23,11 @@ uv run ty check
|
|
|
22
23
|
Node CLI (`~/.insightfactory`, `INSIGHTFACTORY_CONFIG_DIR` override).
|
|
23
24
|
- Do not commit credentials, access tokens, refresh tokens, or client secrets.
|
|
24
25
|
- Test fixtures use only neutral hostnames (`factory.example`).
|
|
25
|
-
- Do not publish to PyPI
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
- Do not publish to PyPI from a developer machine. Publishing happens in CI: the
|
|
27
|
+
reusable workflow in `if_sre_github_actions` builds and stages, and the OIDC job
|
|
28
|
+
in `.github/workflows/release.yml` uploads.
|
|
29
|
+
- **A release is a pushed `v*` tag, not a merge.** Merging to `main` runs CI and
|
|
30
|
+
publishes nothing; pushing `v<version>` publishes that version, and the tag must
|
|
31
|
+
match `pyproject.toml`. Pushing `develop` publishes a `.dev{run_number}`
|
|
32
|
+
pre-release. Creating the release tag is a deliberate human act — do not create
|
|
33
|
+
or push one unless asked to cut a release.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: insightfactory-cli
|
|
3
|
-
Version: 1.0.1.
|
|
3
|
+
Version: 1.0.1.dev9
|
|
4
4
|
Summary: Profile-based authentication CLI for the InsightFactory Interfaces API
|
|
5
5
|
Project-URL: Homepage, https://github.com/insightfactory-ai/insightfactory-cli
|
|
6
6
|
Project-URL: Repository, https://github.com/insightfactory-ai/insightfactory-cli
|
|
@@ -102,6 +102,12 @@ prefixes.
|
|
|
102
102
|
Override the config directory with `INSIGHTFACTORY_CONFIG_DIR` (useful in tests
|
|
103
103
|
and CI). The default is `~/.insightfactory`.
|
|
104
104
|
|
|
105
|
+
The request method goes in `-X`; `if-cli api` takes exactly one positional
|
|
106
|
+
argument and reads it as the path. A `curl`-shaped `if-cli api GET /api/schedules`
|
|
107
|
+
therefore parses `GET` as the path — write `if-cli api -X GET /api/schedules`
|
|
108
|
+
instead. The CLI names the misplaced verb rather than reporting a problem with
|
|
109
|
+
`/api/schedules`.
|
|
110
|
+
|
|
105
111
|
On Git Bash (MSYS2) on Windows, path conversion rewrites a leading-slash
|
|
106
112
|
argument such as `/api/agent-projects` into a Windows path. Prefix the command
|
|
107
113
|
with `MSYS_NO_PATHCONV=1`:
|
|
@@ -212,12 +218,16 @@ Python 3.10 or newer is required. Runtime code is stdlib-only.
|
|
|
212
218
|
|
|
213
219
|
## Release
|
|
214
220
|
|
|
215
|
-
|
|
216
|
-
|
|
221
|
+
**A release is cut by pushing a tag, not by merging.** Merging to `main` runs CI and
|
|
222
|
+
publishes nothing.
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
git tag v1.0.1 && git push origin v1.0.1
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Verify and build live in the reusable workflow
|
|
217
229
|
[`if_s_insightfactory_cli.yml`](https://github.com/insightfactory-ai/if_sre_github_actions/blob/main/.github/workflows/if_s_insightfactory_cli.yml)
|
|
218
|
-
in `insightfactory-ai/if_sre_github_actions
|
|
219
|
-
([PR #300](https://github.com/insightfactory-ai/if_sre_github_actions/pull/300)
|
|
220
|
-
must merge before these stubs go green). This repository's
|
|
230
|
+
in `insightfactory-ai/if_sre_github_actions`. This repository's
|
|
221
231
|
`.github/workflows/release.yml` keeps only the OIDC publish job, because PyPI
|
|
222
232
|
Trusted Publishing is registered for **this** repo, workflow `release.yml`, and
|
|
223
233
|
environment `pypi` — a reusable workflow cannot be registered.
|
|
@@ -228,24 +238,38 @@ the reusable workflow and uploads it with `pypa/gh-action-pypi-publish`.
|
|
|
228
238
|
|
|
229
239
|
| Trigger | Published version | PyPI role |
|
|
230
240
|
|---|---|---|
|
|
231
|
-
| Push / merge to `develop` | `1.0.
|
|
232
|
-
| Push
|
|
233
|
-
|
|
|
241
|
+
| Push / merge to `develop` | `1.0.1.dev{N}` | pre-release (`pip install --pre`) |
|
|
242
|
+
| Push of a `v*` tag | the version in `pyproject.toml`, which the tag must match | latest |
|
|
243
|
+
| Merge to `main` | nothing — CI only | — |
|
|
234
244
|
|
|
235
245
|
`N` is `github.run_number` of the reusable workflow: a per-workflow integer
|
|
236
246
|
that goes up on every run and stays the same across re-runs of that run (so a
|
|
237
247
|
failed publish can be retried under the same version). It does not depend on
|
|
238
|
-
git history or clone depth. After a successful
|
|
239
|
-
|
|
240
|
-
landed; PEP 440 puts `1.0.
|
|
248
|
+
git history or clone depth. After a successful release, bump `version` in
|
|
249
|
+
`pyproject.toml` on `develop` so later `.devN` builds sort *after* what just
|
|
250
|
+
landed; PEP 440 puts `1.0.1.devN` before `1.0.1`. Because of that ordering, a
|
|
241
251
|
dependency spec of `insightfactory-cli>=1.0.0` does not match develop-channel
|
|
242
252
|
`.devN` builds; an in-process consumer that wants them must specify a
|
|
243
253
|
pre-release-bearing spec such as `insightfactory-cli>=1.0.0.dev0` (which also
|
|
244
254
|
matches the final `1.0.0` release).
|
|
245
255
|
|
|
246
|
-
A
|
|
247
|
-
|
|
248
|
-
|
|
256
|
+
A `v*` tag whose name does not match `pyproject.toml` fails before publishing.
|
|
257
|
+
|
|
258
|
+
The two channels treat an already-published version differently, on purpose:
|
|
259
|
+
|
|
260
|
+
- **Release channel (a tag):** publishing fails, naming the fix. A tag is a request to
|
|
261
|
+
release that version; if it cannot be honoured, the run must say so rather than report
|
|
262
|
+
success having published nothing. (git also refuses to push a tag that already exists,
|
|
263
|
+
so this is hard to reach.)
|
|
264
|
+
- **Dev channel (`develop`):** publishing is skipped quietly. `.dev{N}` uses
|
|
265
|
+
`github.run_number`, which is stable across re-runs of one run, so an already-present
|
|
266
|
+
version there can only mean a re-run of a run that already published — real idempotency,
|
|
267
|
+
not a swallowed mistake.
|
|
268
|
+
|
|
269
|
+
This split is why releasing moved off `main`. While a merge was the trigger, an
|
|
270
|
+
already-published version *had* to be tolerated as a no-op for merges to stay green — so a
|
|
271
|
+
merge that released nothing looked exactly like one that released, and a forgotten version
|
|
272
|
+
bump shipped nothing silently.
|
|
249
273
|
|
|
250
274
|
## Differences from the Node CLI
|
|
251
275
|
|
|
@@ -86,6 +86,12 @@ prefixes.
|
|
|
86
86
|
Override the config directory with `INSIGHTFACTORY_CONFIG_DIR` (useful in tests
|
|
87
87
|
and CI). The default is `~/.insightfactory`.
|
|
88
88
|
|
|
89
|
+
The request method goes in `-X`; `if-cli api` takes exactly one positional
|
|
90
|
+
argument and reads it as the path. A `curl`-shaped `if-cli api GET /api/schedules`
|
|
91
|
+
therefore parses `GET` as the path — write `if-cli api -X GET /api/schedules`
|
|
92
|
+
instead. The CLI names the misplaced verb rather than reporting a problem with
|
|
93
|
+
`/api/schedules`.
|
|
94
|
+
|
|
89
95
|
On Git Bash (MSYS2) on Windows, path conversion rewrites a leading-slash
|
|
90
96
|
argument such as `/api/agent-projects` into a Windows path. Prefix the command
|
|
91
97
|
with `MSYS_NO_PATHCONV=1`:
|
|
@@ -196,12 +202,16 @@ Python 3.10 or newer is required. Runtime code is stdlib-only.
|
|
|
196
202
|
|
|
197
203
|
## Release
|
|
198
204
|
|
|
199
|
-
|
|
200
|
-
|
|
205
|
+
**A release is cut by pushing a tag, not by merging.** Merging to `main` runs CI and
|
|
206
|
+
publishes nothing.
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
git tag v1.0.1 && git push origin v1.0.1
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Verify and build live in the reusable workflow
|
|
201
213
|
[`if_s_insightfactory_cli.yml`](https://github.com/insightfactory-ai/if_sre_github_actions/blob/main/.github/workflows/if_s_insightfactory_cli.yml)
|
|
202
|
-
in `insightfactory-ai/if_sre_github_actions
|
|
203
|
-
([PR #300](https://github.com/insightfactory-ai/if_sre_github_actions/pull/300)
|
|
204
|
-
must merge before these stubs go green). This repository's
|
|
214
|
+
in `insightfactory-ai/if_sre_github_actions`. This repository's
|
|
205
215
|
`.github/workflows/release.yml` keeps only the OIDC publish job, because PyPI
|
|
206
216
|
Trusted Publishing is registered for **this** repo, workflow `release.yml`, and
|
|
207
217
|
environment `pypi` — a reusable workflow cannot be registered.
|
|
@@ -212,24 +222,38 @@ the reusable workflow and uploads it with `pypa/gh-action-pypi-publish`.
|
|
|
212
222
|
|
|
213
223
|
| Trigger | Published version | PyPI role |
|
|
214
224
|
|---|---|---|
|
|
215
|
-
| Push / merge to `develop` | `1.0.
|
|
216
|
-
| Push
|
|
217
|
-
|
|
|
225
|
+
| Push / merge to `develop` | `1.0.1.dev{N}` | pre-release (`pip install --pre`) |
|
|
226
|
+
| Push of a `v*` tag | the version in `pyproject.toml`, which the tag must match | latest |
|
|
227
|
+
| Merge to `main` | nothing — CI only | — |
|
|
218
228
|
|
|
219
229
|
`N` is `github.run_number` of the reusable workflow: a per-workflow integer
|
|
220
230
|
that goes up on every run and stays the same across re-runs of that run (so a
|
|
221
231
|
failed publish can be retried under the same version). It does not depend on
|
|
222
|
-
git history or clone depth. After a successful
|
|
223
|
-
|
|
224
|
-
landed; PEP 440 puts `1.0.
|
|
232
|
+
git history or clone depth. After a successful release, bump `version` in
|
|
233
|
+
`pyproject.toml` on `develop` so later `.devN` builds sort *after* what just
|
|
234
|
+
landed; PEP 440 puts `1.0.1.devN` before `1.0.1`. Because of that ordering, a
|
|
225
235
|
dependency spec of `insightfactory-cli>=1.0.0` does not match develop-channel
|
|
226
236
|
`.devN` builds; an in-process consumer that wants them must specify a
|
|
227
237
|
pre-release-bearing spec such as `insightfactory-cli>=1.0.0.dev0` (which also
|
|
228
238
|
matches the final `1.0.0` release).
|
|
229
239
|
|
|
230
|
-
A
|
|
231
|
-
|
|
232
|
-
|
|
240
|
+
A `v*` tag whose name does not match `pyproject.toml` fails before publishing.
|
|
241
|
+
|
|
242
|
+
The two channels treat an already-published version differently, on purpose:
|
|
243
|
+
|
|
244
|
+
- **Release channel (a tag):** publishing fails, naming the fix. A tag is a request to
|
|
245
|
+
release that version; if it cannot be honoured, the run must say so rather than report
|
|
246
|
+
success having published nothing. (git also refuses to push a tag that already exists,
|
|
247
|
+
so this is hard to reach.)
|
|
248
|
+
- **Dev channel (`develop`):** publishing is skipped quietly. `.dev{N}` uses
|
|
249
|
+
`github.run_number`, which is stable across re-runs of one run, so an already-present
|
|
250
|
+
version there can only mean a re-run of a run that already published — real idempotency,
|
|
251
|
+
not a swallowed mistake.
|
|
252
|
+
|
|
253
|
+
This split is why releasing moved off `main`. While a merge was the trigger, an
|
|
254
|
+
already-published version *had* to be tolerated as a no-op for merges to stay green — so a
|
|
255
|
+
merge that released nothing looked exactly like one that released, and a forgotten version
|
|
256
|
+
bump shipped nothing silently.
|
|
233
257
|
|
|
234
258
|
## Differences from the Node CLI
|
|
235
259
|
|
|
@@ -61,6 +61,27 @@ def describe_route(document: dict[str, Any], method: str, path: str) -> dict[str
|
|
|
61
61
|
return operation if isinstance(operation, dict) else None
|
|
62
62
|
|
|
63
63
|
|
|
64
|
+
def _is_absolute_http_url(api_path: str) -> bool:
|
|
65
|
+
parsed = parse_url(api_path)
|
|
66
|
+
return parsed.scheme in {"http", "https"} and bool(parsed.hostname)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def _die_on_misplaced_http_method(api_path: str, positionals: list[str]) -> None:
|
|
70
|
+
"""Explain a `curl`-shaped `if-cli api GET /path`, where the verb is read as the path.
|
|
71
|
+
|
|
72
|
+
Recognition spans every verb a user might reach for, not just the ones -X accepts:
|
|
73
|
+
naming the misplaced verb is more useful than a path error even for TRACE, which
|
|
74
|
+
-X then rejects on its own terms.
|
|
75
|
+
"""
|
|
76
|
+
method = api_path.lower()
|
|
77
|
+
if method not in HTTP_METHODS:
|
|
78
|
+
return
|
|
79
|
+
targets = [value for value in positionals[1:] if value.startswith("/") or _is_absolute_http_url(value)]
|
|
80
|
+
target = targets[0] if targets else "/api/path"
|
|
81
|
+
suggestion = f"if-cli api -X {method.upper()} {target}"
|
|
82
|
+
die(f"'{api_path}' looks like an HTTP method, not a path — did you mean: {suggestion} ?")
|
|
83
|
+
|
|
84
|
+
|
|
64
85
|
def _die_on_msys_mangled_path(api_path: str) -> None:
|
|
65
86
|
if not WINDOWS_DRIVE_PATH.search(api_path):
|
|
66
87
|
return
|
|
@@ -73,11 +94,6 @@ def _die_on_msys_mangled_path(api_path: str) -> None:
|
|
|
73
94
|
)
|
|
74
95
|
|
|
75
96
|
|
|
76
|
-
def _is_absolute_http_url(api_path: str) -> bool:
|
|
77
|
-
parsed = parse_url(api_path)
|
|
78
|
-
return parsed.scheme in {"http", "https"} and bool(parsed.hostname)
|
|
79
|
-
|
|
80
|
-
|
|
81
97
|
def resolve_api_url(host: str, api_path: str) -> ParseResult:
|
|
82
98
|
if not api_path.startswith("/") and not _is_absolute_http_url(api_path):
|
|
83
99
|
_die_on_msys_mangled_path(api_path)
|
|
@@ -145,6 +161,7 @@ def api_command(argv: list[str]) -> None:
|
|
|
145
161
|
api_path = positionals[0] if positionals else None
|
|
146
162
|
if not api_path:
|
|
147
163
|
die(API_USAGE)
|
|
164
|
+
_die_on_misplaced_http_method(api_path, positionals)
|
|
148
165
|
|
|
149
166
|
if values["method"] is not None:
|
|
150
167
|
method = values["method"].upper()
|
|
@@ -37,6 +37,46 @@ def test_api_rejects_unsupported_request_methods_with_a_cli_error():
|
|
|
37
37
|
assert "unsupported request method 'TRACE'" in result.stderr
|
|
38
38
|
|
|
39
39
|
|
|
40
|
+
def test_api_names_a_misplaced_http_method_instead_of_blaming_the_path():
|
|
41
|
+
result = run_cli(["api", "GET", "/api/schedules"])
|
|
42
|
+
assert result.returncode == 1
|
|
43
|
+
assert "'GET' looks like an HTTP method, not a path" in result.stderr
|
|
44
|
+
assert "did you mean: if-cli api -X GET /api/schedules ?" in result.stderr
|
|
45
|
+
assert "API path must begin with" not in result.stderr
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def test_api_detects_a_misplaced_http_method_in_any_case_and_position():
|
|
49
|
+
lowercase = run_cli(["api", "put", "/api/orchestration/run"])
|
|
50
|
+
assert lowercase.returncode == 1
|
|
51
|
+
assert "'put' looks like an HTTP method, not a path" in lowercase.stderr
|
|
52
|
+
assert "did you mean: if-cli api -X PUT /api/orchestration/run ?" in lowercase.stderr
|
|
53
|
+
|
|
54
|
+
before_profile = run_cli(["api", "DELETE", "/api/schedules/1", "-p", "example-dev"])
|
|
55
|
+
assert before_profile.returncode == 1
|
|
56
|
+
assert "did you mean: if-cli api -X DELETE /api/schedules/1 ?" in before_profile.stderr
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def test_api_keeps_a_same_origin_absolute_url_in_the_correction():
|
|
60
|
+
result = run_cli(["api", "GET", "https://factory.example/api/schedules"])
|
|
61
|
+
assert result.returncode == 1
|
|
62
|
+
assert "did you mean: if-cli api -X GET https://factory.example/api/schedules ?" in result.stderr
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def test_api_names_a_misplaced_verb_that_x_would_not_accept():
|
|
66
|
+
result = run_cli(["api", "TRACE", "/api/schedules"])
|
|
67
|
+
assert result.returncode == 1
|
|
68
|
+
assert "'TRACE' looks like an HTTP method, not a path" in result.stderr
|
|
69
|
+
assert "did you mean: if-cli api -X TRACE /api/schedules ?" in result.stderr
|
|
70
|
+
assert "API path must begin with" not in result.stderr
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def test_api_suggests_a_placeholder_path_when_only_a_method_was_supplied():
|
|
74
|
+
result = run_cli(["api", "POST"])
|
|
75
|
+
assert result.returncode == 1
|
|
76
|
+
assert "'POST' looks like an HTTP method, not a path" in result.stderr
|
|
77
|
+
assert "did you mean: if-cli api -X POST /api/path ?" in result.stderr
|
|
78
|
+
|
|
79
|
+
|
|
40
80
|
def test_discovers_and_sorts_all_openapi_operations():
|
|
41
81
|
assert discover_routes(OPENAPI) == [
|
|
42
82
|
"DELETE /api/agent-projects/{id} Delete an agent project",
|
|
File without changes
|
{insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/.github/workflows/claude.yml
RENAMED
|
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
|
{insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/src/if_cli/commands/__init__.py
RENAMED
|
File without changes
|
{insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/src/if_cli/commands/config.py
RENAMED
|
File without changes
|
{insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/src/if_cli/commands/login.py
RENAMED
|
File without changes
|
{insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/src/if_cli/commands/logout.py
RENAMED
|
File without changes
|
{insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/src/if_cli/commands/profiles.py
RENAMED
|
File without changes
|
{insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/src/if_cli/commands/set_token.py
RENAMED
|
File without changes
|
{insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/src/if_cli/commands/token.py
RENAMED
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/tests/test_config_command.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{insightfactory_cli-1.0.1.dev5 → insightfactory_cli-1.0.1.dev9}/tests/test_programmatic_api.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|