python-nats-py
CLEAN
maintainer Smoolak
0 votes
scanned 2026-09-21 00:26:32.109917
Triggered rules
Clean
AI review downgraded a static finding
llm_review
The static rules flagged this LOW, but an AI model (qwen/qwen3-235b-a22b-2507) reviewed the full PKGBUILD and judged it CLEAN (confidence 95%): The package builds a well-known Python NATS client from its official GitHub repository, applies minor patches for compatibility, and runs standard tests; there is no execution of untrusted remote code or supply-chain risk.
1 higher static finding superseded - not the current verdict (shown for transparency)
Low
Few votes, recently uploaded
zero_votes_recent
Uploaded within the last 14 days with 2 or fewer community votes — little peer review so far.
PKGBUILD
1
# Maintainer: Smoolak <smoolak@gmail.com>
2
3
pkgname=python-nats-py
4
_pkgname=nats.py
5
pkgver=2.16.0
6
pkgrel=1
7
pkgdesc="Asyncio NATS client for Python"
8
arch=('any')
9
url="https://github.com/nats-io/nats.py"
10
license=('Apache-2.0')
11
depends=('python>=3.7')
12
optdepends=(
13
'python-aiohttp: WebSocket transport support'
14
'python-fast-mail-parser: accelerated message-header parsing'
15
'python-nkeys: NKey and JWT authentication support'
16
)
17
makedepends=(
18
'python-build'
19
'python-installer'
20
'python-uv-build>=0.9.28'
21
)
22
checkdepends=(
23
'nats-server>=2.12'
24
'python-aiofiles'
25
'python-aiohttp'
26
'python-fast-mail-parser'
27
'python-nkeys'
28
'python-pytest>=9.0.3'
29
'python-pytest-asyncio>=0.21'
30
)
31
_archive="$_pkgname-$pkgver"
32
source=(
33
"$pkgname-$pkgver.tar.gz::$url/archive/refs/tags/v$pkgver.tar.gz"
34
'fast-parser-header-name-validation.patch'
35
)
36
sha256sums=(
37
'efe0fe244f02c18de7816a214825e383fcd8d38382ba8d6faf51abc3d142e7a8'
38
'44e236d00ac84672c8fbe58c61339593fa192c14a4d55ed594e1b8378bf23c90'
39
)
40
41
prepare() {
42
cd "$_archive"
43
44
# Arch ships uv_build 0.11, whose backend remains compatible with this
45
# pure-Python project; drop upstream's build-environment-only <0.10 pin.
46
sed -i 's/uv_build>=0.9.28,<0.10.0/uv_build>=0.9.28/' nats/pyproject.toml
47
48
# Keep optional fast_mail_parser behavior aligned with the built-in
49
# parser: malformed non-ASCII header names are not valid tokens.
50
patch -Np1 -i "$srcdir/fast-parser-header-name-validation.patch"
51
}
52
53
build() {
54
cd "$_archive/nats"
55
python -m build --wheel --no-isolation
56
}
57
58
check() {
59
cd "$_archive"
60
61
local _checkroot="$srcdir/_check"
62
local _server_version
63
local _site
64
rm -rf "$_checkroot"
65
python -m installer --destdir="$_checkroot" nats/dist/*.whl
66
_site=$(python -c 'import site; print(site.getsitepackages()[0])')
67
68
# Run upstream's complete client suite against the built wheel and the
69
# packaged nats-server. Upstream itself marks two flaky cases and its
70
# external multi-client compatibility harness as unavailable here.
71
_server_version=$(nats-server --version | awk '{print $2}')
72
NATS_SERVER_VERSION="$_server_version" \
73
PYTHONPATH="$_checkroot$_site:$PWD/nats" \
74
pytest -vv -s \
75
nats/tests/test_client.py::ProcessHeadersTest::test_non_ascii_in_name_is_skipped_not_replaced
76
NATS_SERVER_VERSION="$_server_version" \
77
PYTHONPATH="$_checkroot$_site:$PWD/nats" \
78
pytest -vv -s --continue-on-collection-errors nats/tests
79
80
# Representative installed-wheel workflow: request/reply plus JetStream.
81
PYTHONPATH="$_checkroot$_site" python - <<'PY'
82
import asyncio
83
import subprocess
84
import tempfile
85
86
import nats
87
88
89
async def exercise():
90
with tempfile.TemporaryDirectory() as store:
91
server = subprocess.Popen(
92
[
93
"nats-server",
94
"-a", "127.0.0.1",
95
"-p", "45222",
96
"-m", "48222",
97
"-js",
98
"-sd", store,
99
],
100
stdout=subprocess.DEVNULL,
101
stderr=subprocess.DEVNULL,
102
)
103
try:
104
for _ in range(100):
105
try:
106
nc = await nats.connect("nats://127.0.0.1:45222")
107
break
108
except (ConnectionRefusedError, OSError):
109
await asyncio.sleep(0.05)
110
else:
111
raise RuntimeError("nats-server did not become ready")
112
113
async def responder(message):
114
await message.respond(message.data.upper())
115
116
await nc.subscribe("orders.normalize", cb=responder)
117
response = await nc.request("orders.normalize", b"invoice-42", timeout=2)
118
assert response.data == b"INVOICE-42"
119
120
js = nc.jetstream()
121
await js.add_stream(name="ORDERS", subjects=["orders.created"])
122
ack = await js.publish("orders.created", b"invoice-42")
123
assert ack.stream == "ORDERS" and ack.seq == 1
124
stored = await js.get_msg("ORDERS", seq=1)
125
assert stored.data == b"invoice-42"
126
await nc.drain()
127
finally:
128
server.terminate()
129
try:
130
server.wait(timeout=5)
131
except subprocess.TimeoutExpired:
132
server.kill()
133
server.wait(timeout=5)
134
135
136
asyncio.run(exercise())
137
PY
138
}
139
140
package() {
141
cd "$_archive/nats"
142
python -m installer --destdir="$pkgdir" dist/*.whl
143
install -Dm644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE"
144
}
145
Scan history
| Scanned at (UTC) | Severity | Rules |
|---|---|---|
| 2026-09-21 00:26:32 | Clean | 2 |
| 2026-09-20 23:33:19 | Low | 1 |