Skip to content

Commit 3b5541c

Browse files
committed
refactor: replace requests with httpx
Swap the HTTP client from requests to httpx for a lighter dependency footprint. Update README to highlight the lightweight design.
1 parent 6b808a0 commit 3b5541c

5 files changed

Lines changed: 67 additions & 103 deletions

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ fzf-powered OpenAPI API client.
44

55
Browse, search, and call any OpenAPI endpoint from the terminal.
66

7+
Lightweight by design — a single Python file that leans on [fzf](https://github.com/junegunn/fzf) for the interactive UI, with only [httpx](https://www.python-httpx.org/) and [PyYAML](https://pyyaml.org/) as Python dependencies.
8+
79
![demo](demo.gif)
810

911
## Install

apick.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from datetime import UTC, datetime
1212
from urllib.parse import urlencode, urlparse
1313

14-
import requests
14+
import httpx
1515
import yaml
1616

1717
HISTORY_FILE = os.path.join(os.path.expanduser("~"), ".apick", "history.json")
@@ -37,7 +37,7 @@ def highlight_json(text: str) -> str:
3737
def fetch_spec(source: str) -> dict:
3838
"""Fetch and parse an OpenAPI spec from a URL or local file."""
3939
if urlparse(source).scheme in ("http", "https"):
40-
resp = requests.get(source, timeout=30)
40+
resp = httpx.get(source, timeout=30)
4141
resp.raise_for_status()
4242
content = resp.text
4343
else:
@@ -444,11 +444,11 @@ def execute_request(
444444
if body is not None:
445445
kwargs["json"] = body
446446

447-
resp = requests.request(method, url, **kwargs) # noqa: S113 (timeout is in kwargs)
447+
resp = httpx.request(method, url, **kwargs)
448448

449449
# Status line
450450
color = "\033[32m" if resp.status_code < 400 else "\033[31m"
451-
print(f"\n{color}{resp.status_code} {resp.reason}\033[0m")
451+
print(f"\n{color}{resp.status_code} {resp.reason_phrase}\033[0m")
452452

453453
# Response body
454454
ct = resp.headers.get("content-type", "")
@@ -631,7 +631,7 @@ def main():
631631
return
632632
try:
633633
execute_request(method, url, headers, body)
634-
except requests.RequestException as e:
634+
except httpx.HTTPError as e:
635635
print(f"\n\033[31mRequest failed: {e}\033[0m", file=sys.stderr)
636636
sys.exit(1)
637637
return
@@ -697,7 +697,7 @@ def main():
697697
try:
698698
status_code = execute_request(ep["method"], url, headers, body)
699699
_save_to_history(ep["method"], url, headers, body, args.spec, ep["summary"], status_code)
700-
except requests.RequestException as e:
700+
except httpx.HTTPError as e:
701701
_save_to_history(ep["method"], url, headers, body, args.spec, ep["summary"], None)
702702
print(f"\n\033[31mRequest failed: {e}\033[0m", file=sys.stderr)
703703
sys.exit(1)

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ readme = "README.md"
1010
license = "MIT"
1111
requires-python = ">=3.11"
1212
dependencies = [
13-
"requests",
13+
"httpx",
1414
"pyyaml",
1515
]
1616
keywords = ["openapi", "api", "fzf", "cli"]

tests/test_apick.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ def test_load_from_url(self):
341341
mock_resp.text = json.dumps(spec_data)
342342
mock_resp.raise_for_status = MagicMock()
343343

344-
with patch("apick.requests.get", return_value=mock_resp) as mock_get:
344+
with patch("apick.httpx.get", return_value=mock_resp) as mock_get:
345345
result = apick.fetch_spec("https://example.com/spec.json")
346346
mock_get.assert_called_once_with("https://example.com/spec.json", timeout=30)
347347
assert result == spec_data
@@ -477,10 +477,10 @@ class TestExecuteRequest:
477477
def test_returns_status_code(self):
478478
mock_resp = MagicMock()
479479
mock_resp.status_code = 200
480-
mock_resp.reason = "OK"
480+
mock_resp.reason_phrase = "OK"
481481
mock_resp.headers = {"content-type": "text/plain"}
482482
mock_resp.text = "ok"
483483

484-
with patch("apick.requests.request", return_value=mock_resp):
484+
with patch("apick.httpx.request", return_value=mock_resp):
485485
result = apick.execute_request("GET", "https://example.com", {})
486486
assert result == 200

0 commit comments

Comments
 (0)