avios-cli 0.1.0__tar.gz → 0.1.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.
- {avios_cli-0.1.0 → avios_cli-0.1.2}/CHANGELOG.md +21 -1
- {avios_cli-0.1.0 → avios_cli-0.1.2}/PKG-INFO +15 -13
- {avios_cli-0.1.0 → avios_cli-0.1.2}/README.md +14 -12
- {avios_cli-0.1.0 → avios_cli-0.1.2}/pyproject.toml +2 -0
- {avios_cli-0.1.0 → avios_cli-0.1.2}/src/avios/__init__.py +1 -1
- {avios_cli-0.1.0 → avios_cli-0.1.2}/src/avios/auth.py +14 -4
- {avios_cli-0.1.0 → avios_cli-0.1.2}/src/avios/cli.py +4 -3
- {avios_cli-0.1.0 → avios_cli-0.1.2}/tests/test_auth.py +1 -1
- {avios_cli-0.1.0 → avios_cli-0.1.2}/.editorconfig +0 -0
- {avios_cli-0.1.0 → avios_cli-0.1.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {avios_cli-0.1.0 → avios_cli-0.1.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {avios_cli-0.1.0 → avios_cli-0.1.2}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {avios_cli-0.1.0 → avios_cli-0.1.2}/.github/dependabot.yml +0 -0
- {avios_cli-0.1.0 → avios_cli-0.1.2}/.github/workflows/ci.yml +0 -0
- {avios_cli-0.1.0 → avios_cli-0.1.2}/.github/workflows/publish.yml +0 -0
- {avios_cli-0.1.0 → avios_cli-0.1.2}/.gitignore +0 -0
- {avios_cli-0.1.0 → avios_cli-0.1.2}/.pre-commit-config.yaml +0 -0
- {avios_cli-0.1.0 → avios_cli-0.1.2}/.python-version +0 -0
- {avios_cli-0.1.0 → avios_cli-0.1.2}/CONTRIBUTING.md +0 -0
- {avios_cli-0.1.0 → avios_cli-0.1.2}/LICENSE +0 -0
- {avios_cli-0.1.0 → avios_cli-0.1.2}/SECURITY.md +0 -0
- {avios_cli-0.1.0 → avios_cli-0.1.2}/docs/dashboard.svg +0 -0
- {avios_cli-0.1.0 → avios_cli-0.1.2}/scripts/screenshot.py +0 -0
- {avios_cli-0.1.0 → avios_cli-0.1.2}/src/avios/client.py +0 -0
- {avios_cli-0.1.0 → avios_cli-0.1.2}/src/avios/config.py +0 -0
- {avios_cli-0.1.0 → avios_cli-0.1.2}/src/avios/endpoints.py +0 -0
- {avios_cli-0.1.0 → avios_cli-0.1.2}/src/avios/models.py +0 -0
- {avios_cli-0.1.0 → avios_cli-0.1.2}/src/avios/session.py +0 -0
- {avios_cli-0.1.0 → avios_cli-0.1.2}/src/avios/tui/__init__.py +0 -0
- {avios_cli-0.1.0 → avios_cli-0.1.2}/src/avios/tui/app.py +0 -0
- {avios_cli-0.1.0 → avios_cli-0.1.2}/src/avios/tui/art.py +0 -0
- {avios_cli-0.1.0 → avios_cli-0.1.2}/src/avios/tui/styles.tcss +0 -0
- {avios_cli-0.1.0 → avios_cli-0.1.2}/src/avios/tui/widgets.py +0 -0
- {avios_cli-0.1.0 → avios_cli-0.1.2}/tests/conftest.py +0 -0
- {avios_cli-0.1.0 → avios_cli-0.1.2}/tests/fixtures/accounts.json +0 -0
- {avios_cli-0.1.0 → avios_cli-0.1.2}/tests/fixtures/balance.json +0 -0
- {avios_cli-0.1.0 → avios_cli-0.1.2}/tests/fixtures/transactions.json +0 -0
- {avios_cli-0.1.0 → avios_cli-0.1.2}/tests/test_cli.py +0 -0
- {avios_cli-0.1.0 → avios_cli-0.1.2}/tests/test_client.py +0 -0
- {avios_cli-0.1.0 → avios_cli-0.1.2}/tests/test_models.py +0 -0
- {avios_cli-0.1.0 → avios_cli-0.1.2}/tests/test_session.py +0 -0
- {avios_cli-0.1.0 → avios_cli-0.1.2}/tests/test_tui.py +0 -0
- {avios_cli-0.1.0 → avios_cli-0.1.2}/uv.lock +0 -0
|
@@ -6,6 +6,23 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.1.2] - 2026-07-24
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
- Login error messages: `[login]` was swallowed by Rich markup (showed
|
|
13
|
+
`avios-cli` instead of `avios-cli[login]`) — error text is now escaped.
|
|
14
|
+
- Login guidance is uvx-aware: suggests `uvx --from 'avios-cli[login]' avios login`,
|
|
15
|
+
the one-time `playwright install chromium`, and the `--from-browser` alternative;
|
|
16
|
+
a missing Chromium at launch now gives a clear install hint.
|
|
17
|
+
|
|
18
|
+
## [0.1.1] - 2026-07-24
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
- Added an `avios-cli` console-script alias so `uvx avios-cli` works (matching the
|
|
22
|
+
package name). The primary command is still `avios`.
|
|
23
|
+
|
|
24
|
+
## [0.1.0] - 2026-07-24
|
|
25
|
+
|
|
9
26
|
### Added
|
|
10
27
|
- Project scaffolding: src-layout `avios` package, hatchling packaging, `avios`
|
|
11
28
|
console script, ruff + mypy + pytest tooling, GitHub Actions CI (Python
|
|
@@ -32,4 +49,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
32
49
|
- Reward-flight **availability** search is not yet implemented (needs a British
|
|
33
50
|
Airways capture).
|
|
34
51
|
|
|
35
|
-
[Unreleased]: https://github.com/alexechoi/avios-cli/
|
|
52
|
+
[Unreleased]: https://github.com/alexechoi/avios-cli/compare/v0.1.2...HEAD
|
|
53
|
+
[0.1.2]: https://github.com/alexechoi/avios-cli/compare/v0.1.1...v0.1.2
|
|
54
|
+
[0.1.1]: https://github.com/alexechoi/avios-cli/compare/v0.1.0...v0.1.1
|
|
55
|
+
[0.1.0]: https://github.com/alexechoi/avios-cli/releases/tag/v0.1.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: avios-cli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: A CLI and TUI for avios.com — view your Avios balance and transactions from the terminal.
|
|
5
5
|
Project-URL: Homepage, https://github.com/alexechoi/avios-cli
|
|
6
6
|
Project-URL: Repository, https://github.com/alexechoi/avios-cli
|
|
@@ -60,9 +60,10 @@ Early alpha, built in the open. See the [roadmap](#roadmap).
|
|
|
60
60
|
Requires Python 3.10+.
|
|
61
61
|
|
|
62
62
|
```bash
|
|
63
|
-
uvx avios-cli --help #
|
|
64
|
-
# or install it:
|
|
63
|
+
uvx avios-cli --help # run without installing
|
|
64
|
+
# or install it, then use the `avios` command:
|
|
65
65
|
pip install avios-cli
|
|
66
|
+
avios --help
|
|
66
67
|
```
|
|
67
68
|
|
|
68
69
|
Or from source, for development:
|
|
@@ -78,21 +79,22 @@ uv run avios --help
|
|
|
78
79
|
|
|
79
80
|
avios.com has no credential API — login is Auth0 Universal Login behind hCaptcha and
|
|
80
81
|
SMS/passkey MFA — so `avios login` rides a real browser session (like `gh`/`aws`
|
|
81
|
-
login).
|
|
82
|
+
login). Login needs the **`login` extra**, so run it with `avios-cli[login]`:
|
|
82
83
|
|
|
83
84
|
```bash
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
Then either open a browser to log in, or import the cookie from a browser you're
|
|
89
|
-
already logged into:
|
|
85
|
+
# open a browser and log in once (first run also downloads Chromium):
|
|
86
|
+
uvx --from 'avios-cli[login]' playwright install chromium
|
|
87
|
+
uvx --from 'avios-cli[login]' avios login
|
|
90
88
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
89
|
+
# ...or skip the browser download and import the cookie from Chrome you're
|
|
90
|
+
# already logged into avios.com with:
|
|
91
|
+
uvx --from 'avios-cli[login]' avios login --from-browser
|
|
94
92
|
```
|
|
95
93
|
|
|
94
|
+
If you installed with `pip install "avios-cli[login]"`, just run `avios login`
|
|
95
|
+
(and `playwright install chromium` once). Plain `uvx avios-cli login` won't work —
|
|
96
|
+
the isolated environment doesn't include the `login` extra.
|
|
97
|
+
|
|
96
98
|
Your session cookie is stored at `~/.config/avios/state.json` (mode `600`). It
|
|
97
99
|
expires after ~a day; just run `avios login` again. Run `avios logout` to remove it.
|
|
98
100
|
|
|
@@ -25,9 +25,10 @@ Early alpha, built in the open. See the [roadmap](#roadmap).
|
|
|
25
25
|
Requires Python 3.10+.
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
|
-
uvx avios-cli --help #
|
|
29
|
-
# or install it:
|
|
28
|
+
uvx avios-cli --help # run without installing
|
|
29
|
+
# or install it, then use the `avios` command:
|
|
30
30
|
pip install avios-cli
|
|
31
|
+
avios --help
|
|
31
32
|
```
|
|
32
33
|
|
|
33
34
|
Or from source, for development:
|
|
@@ -43,21 +44,22 @@ uv run avios --help
|
|
|
43
44
|
|
|
44
45
|
avios.com has no credential API — login is Auth0 Universal Login behind hCaptcha and
|
|
45
46
|
SMS/passkey MFA — so `avios login` rides a real browser session (like `gh`/`aws`
|
|
46
|
-
login).
|
|
47
|
+
login). Login needs the **`login` extra**, so run it with `avios-cli[login]`:
|
|
47
48
|
|
|
48
49
|
```bash
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
Then either open a browser to log in, or import the cookie from a browser you're
|
|
54
|
-
already logged into:
|
|
50
|
+
# open a browser and log in once (first run also downloads Chromium):
|
|
51
|
+
uvx --from 'avios-cli[login]' playwright install chromium
|
|
52
|
+
uvx --from 'avios-cli[login]' avios login
|
|
55
53
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
54
|
+
# ...or skip the browser download and import the cookie from Chrome you're
|
|
55
|
+
# already logged into avios.com with:
|
|
56
|
+
uvx --from 'avios-cli[login]' avios login --from-browser
|
|
59
57
|
```
|
|
60
58
|
|
|
59
|
+
If you installed with `pip install "avios-cli[login]"`, just run `avios login`
|
|
60
|
+
(and `playwright install chromium` once). Plain `uvx avios-cli login` won't work —
|
|
61
|
+
the isolated environment doesn't include the `login` extra.
|
|
62
|
+
|
|
61
63
|
Your session cookie is stored at `~/.config/avios/state.json` (mode `600`). It
|
|
62
64
|
expires after ~a day; just run `avios login` again. Run `avios logout` to remove it.
|
|
63
65
|
|
|
@@ -61,13 +61,22 @@ def login_via_browser(
|
|
|
61
61
|
from playwright.sync_api import sync_playwright
|
|
62
62
|
except ImportError as exc:
|
|
63
63
|
raise LoginError(
|
|
64
|
-
|
|
65
|
-
"
|
|
64
|
+
"Playwright isn't installed. Log in using the 'login' extra:\n"
|
|
65
|
+
" uvx --from 'avios-cli[login]' avios login\n"
|
|
66
|
+
" (first time only: uvx --from 'avios-cli[login]' playwright install chromium)\n"
|
|
67
|
+
"Or import the cookie from Chrome instead (no browser download):\n"
|
|
68
|
+
" uvx --from 'avios-cli[login]' avios login --from-browser"
|
|
66
69
|
) from exc
|
|
67
70
|
|
|
68
71
|
base_url = session.settings.base_url
|
|
69
72
|
with sync_playwright() as pw: # pragma: no cover - requires a real browser
|
|
70
|
-
|
|
73
|
+
try:
|
|
74
|
+
browser = pw.chromium.launch(headless=headless)
|
|
75
|
+
except Exception as exc:
|
|
76
|
+
raise LoginError(
|
|
77
|
+
"Couldn't launch Chromium. Install the browser once with:\n"
|
|
78
|
+
" uvx --from 'avios-cli[login]' playwright install chromium"
|
|
79
|
+
) from exc
|
|
71
80
|
ctx = browser.new_context(user_agent=session.settings.user_agent)
|
|
72
81
|
page = ctx.new_page()
|
|
73
82
|
page.goto(f"{base_url}{DASHBOARD_PATH}")
|
|
@@ -90,7 +99,8 @@ def _default_loader(browser: str) -> Callable[[], Iterable[_RawCookie]]:
|
|
|
90
99
|
import browser_cookie3 as bc3
|
|
91
100
|
except ImportError as exc:
|
|
92
101
|
raise LoginError(
|
|
93
|
-
|
|
102
|
+
"browser-cookie3 isn't installed. Run with the 'login' extra:\n"
|
|
103
|
+
" uvx --from 'avios-cli[login]' avios login --from-browser"
|
|
94
104
|
) from exc
|
|
95
105
|
fn = getattr(bc3, browser, None)
|
|
96
106
|
if fn is None:
|
|
@@ -14,6 +14,7 @@ from typing import Any
|
|
|
14
14
|
import httpx
|
|
15
15
|
import typer
|
|
16
16
|
from rich.console import Console
|
|
17
|
+
from rich.markup import escape
|
|
17
18
|
from rich.table import Table
|
|
18
19
|
|
|
19
20
|
from avios import __version__
|
|
@@ -69,7 +70,7 @@ def _handle_errors() -> Iterator[None]:
|
|
|
69
70
|
console.print("[red]Session expired.[/] Run [bold]avios login[/] again.")
|
|
70
71
|
raise typer.Exit(2) from exc
|
|
71
72
|
except httpx.HTTPError as exc:
|
|
72
|
-
console.print(f"[red]Request failed:[/] {exc}")
|
|
73
|
+
console.print(f"[red]Request failed:[/] {escape(str(exc))}")
|
|
73
74
|
raise typer.Exit(1) from exc
|
|
74
75
|
|
|
75
76
|
|
|
@@ -113,7 +114,7 @@ def login(
|
|
|
113
114
|
)
|
|
114
115
|
count = login_via_browser(session, headless=headless)
|
|
115
116
|
except LoginError as exc:
|
|
116
|
-
console.print(f"[red]{exc}[/]")
|
|
117
|
+
console.print(f"[red]{escape(str(exc))}[/]")
|
|
117
118
|
raise typer.Exit(1) from exc
|
|
118
119
|
|
|
119
120
|
console.print(f"[green]Logged in.[/] Saved {count} avios cookie(s).")
|
|
@@ -123,7 +124,7 @@ def login(
|
|
|
123
124
|
f"[green]✓ Session works.[/] Balance: [bold cyan]{balance.balance:,}[/] Avios"
|
|
124
125
|
)
|
|
125
126
|
except (NotAuthenticated, SessionExpired, httpx.HTTPError) as exc:
|
|
126
|
-
console.print(f"[yellow]Saved, but a test call failed:[/] {exc}")
|
|
127
|
+
console.print(f"[yellow]Saved, but a test call failed:[/] {escape(str(exc))}")
|
|
127
128
|
|
|
128
129
|
|
|
129
130
|
@app.command()
|
|
@@ -104,5 +104,5 @@ def test_login_via_browser_without_playwright(
|
|
|
104
104
|
) -> None:
|
|
105
105
|
monkeypatch.setitem(sys.modules, "playwright", None)
|
|
106
106
|
monkeypatch.setitem(sys.modules, "playwright.sync_api", None)
|
|
107
|
-
with pytest.raises(LoginError, match="Playwright
|
|
107
|
+
with pytest.raises(LoginError, match="Playwright isn't installed"):
|
|
108
108
|
login_via_browser(_session(settings))
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|