Skip to content

Commit 7e0c612

Browse files
authored
Merge pull request #2 from taskiq-python/feature/stream
2 parents 442de0f + 8a3d1fe commit 7e0c612

26 files changed

+828
-109
lines changed

.github/workflows/test.yml

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: "Testing package"
22

33
on:
4-
pull_request:
4+
push:
55

66
jobs:
77
py-lint:
@@ -13,7 +13,7 @@ jobs:
1313
- mypy
1414
runs-on: ubuntu-latest
1515
steps:
16-
- uses: actions/checkout@v2
16+
- uses: actions/checkout@v6
1717
- name: Set up Python
1818
uses: actions/setup-python@v4
1919
with:
@@ -25,7 +25,7 @@ jobs:
2525
fmt:
2626
runs-on: ubuntu-latest
2727
steps:
28-
- uses: actions/checkout@v1
28+
- uses: actions/checkout@v6
2929
- uses: actions-rs/toolchain@v1
3030
with:
3131
toolchain: stable
@@ -39,13 +39,45 @@ jobs:
3939
checks: write
4040
runs-on: ubuntu-latest
4141
steps:
42-
- uses: actions/checkout@v1
42+
- uses: actions/checkout@v6
4343
- uses: actions-rs/toolchain@v1
4444
with:
4545
toolchain: stable
4646
components: clippy
4747
override: true
4848
- uses: auguwu/clippy-action@1.4.0
4949
with:
50-
token: ${{secrets.GITHUB_TOKEN}}
51-
deny: warnings
50+
token: ${{secrets.GITHUB_TOKEN}}
51+
pytest:
52+
runs-on: ubuntu-latest
53+
steps:
54+
- uses: actions/checkout@v6
55+
- uses: actions-rs/toolchain@v1
56+
with:
57+
toolchain: stable
58+
components: clippy
59+
override: true
60+
- uses: actions/setup-python@v6
61+
with:
62+
python-version: 3.x
63+
- name: Install uv
64+
uses: astral-sh/setup-uv@v7
65+
- id: prepare-container
66+
name: Prepare docker container
67+
run: docker compose up -d --wait
68+
- id: setup-venv
69+
name: Setup virtualenv
70+
run: python -m venv .venv
71+
- name: Build lib
72+
uses: PyO3/maturin-action@v1
73+
with:
74+
command: dev --uv
75+
sccache: true
76+
- name: Run pytest
77+
run: |
78+
set -e
79+
source .venv/bin/activate
80+
pytest -vv -n auto python/tests
81+
- name: Teardown docker
82+
if: always()
83+
run: docker compose down

.pre-commit-config.yaml

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@ repos:
3939
args:
4040
- fmt
4141

42-
- id: clippy
42+
- id: clippy-fix
4343
types:
4444
- rust
45-
name: rust clippy
45+
name: fixing fixable clippy
4646
language: system
4747
pass_filenames: false
4848
entry: cargo
@@ -51,6 +51,16 @@ repos:
5151
- --fix
5252
- --allow-dirty
5353

54+
- id: clippy-check
55+
types:
56+
- rust
57+
name: rust clippy
58+
language: system
59+
pass_filenames: false
60+
entry: cargo
61+
args:
62+
- clippy
63+
5464
- id: check
5565
types:
5666
- rust

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
[package]
22
name = "natsrpy"
3-
version = "0.0.1"
3+
# Don't update version manually. It's set during release workflow.
4+
version = "0.0.0"
45
edition = "2024"
6+
description = "Python NATS client written in Rust"
7+
repository = "https://github.com/taskiq-python/natsrpy"
8+
license-file = "LICENSE"
9+
publish = false
510

611
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
712
[lib]
8-
name = "_inner"
913
crate-type = ["cdylib"]
14+
name = "_inner"
1015

1116
[dependencies]
1217
async-nats = "0.46"

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2022-present Pavel Kirilin
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.

README.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
[![PyPI](https://img.shields.io/pypi/v/natsrpy?style=for-the-badge)](https://pypi.org/project/scyllapy/)
2+
[![PyPI - Downloads](https://img.shields.io/pypi/dm/natsrpy?style=for-the-badge)](https://pypistats.org/packages/scyllapy)
3+
4+
# Nats client
5+
6+
This is a client library for [NATS](https://nats.io) written in rust.
7+
8+
Credits for [Intree](https://intree.com) for supporting this project.
9+
10+
11+
## installation
12+
13+
This package can be installed from pypi:
14+
15+
```bash
16+
pip install natsrpy
17+
```
18+
19+
Or alternatively you ca build it yourself using maturin, and stable rust.
20+
21+
## Development
22+
23+
We use stable rust and pyo3 for writing python extension module.
24+
25+
In order to run the project use maturin:
26+
27+
```bash
28+
# To create .venv folder
29+
uv venv
30+
# To build and install the package in a virtual environment
31+
maturin dev --uv
32+
```
33+
34+
For lints please use `pre-commit`.
35+
36+
```bash
37+
pre-commit run -a
38+
```

docker-compose.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
services:
2+
nats:
3+
image: nats:2.12.5-alpine
4+
command: -m 8222 --jetstream
5+
healthcheck:
6+
test:
7+
- CMD
8+
- "sh"
9+
- "-c"
10+
- "wget http://localhost:8222/healthz -q -O - | xargs | grep ok || exit 1"
11+
interval: 5s
12+
timeout: 3s
13+
retries: 20
14+
ports:
15+
- 4222:4222

pyproject.toml

Lines changed: 101 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,117 @@
11
[project]
22
name = "natsrpy"
3-
requires-python = ">=3.8"
3+
description = "Nats client library written in rust"
4+
readme = "README.md"
5+
requires-python = ">=3.10"
6+
license-files = ["LICENSE"]
47
classifiers = [
8+
"Development Status :: 3 - Alpha",
9+
"Intended Audience :: Developers",
10+
"License :: OSI Approved :: MIT License",
511
"Programming Language :: Python :: Implementation :: CPython",
612
"Programming Language :: Python :: Implementation :: PyPy",
713
"Programming Language :: Rust",
14+
"Topic :: System :: Networking",
815
]
916
dynamic = ["version"]
1017

18+
[[project.authors]]
19+
name = "Pavel Kirilin"
20+
email = "s3riussan@gmail.com"
21+
22+
[dependency-groups]
23+
dev = [
24+
"anyio>=4,<5",
25+
"pytest>=9,<10",
26+
"pytest-xdist>=3,<4",
27+
]
28+
1129
[build-system]
1230
requires = ["maturin>=1.12,<2.0"]
1331
build-backend = "maturin"
1432

1533
[tool.maturin]
1634
bindings = "pyo3"
17-
python-source = "python"
18-
module-name = "natsrpy._inner"
1935
features = ["pyo3/extension-module"]
36+
module-name = "natsrpy._inner"
37+
python-source = "python"
38+
39+
[tool.mypy]
40+
python_version = "3.10"
41+
strict = true
42+
ignore_missing_imports = true
43+
packages = ["natsrpy"]
44+
pretty = true
45+
implicit_reexport = true
46+
allow_untyped_decorators = true
47+
warn_return_any = false
48+
49+
[tool.pytest]
50+
anyio_mode = "auto"
51+
52+
[tool.ruff]
53+
target-version = "py310"
54+
exclude = [".venv/"]
55+
line-length = 88
56+
57+
[tool.ruff.lint]
58+
mccabe = { max-complexity = 10 }
59+
# List of enabled rulsets.
60+
# See https://docs.astral.sh/ruff/rules/ for more information.
61+
select = [
62+
"E", # Error
63+
"F", # Pyflakes
64+
"W", # Pycodestyle
65+
"C90", # McCabe complexity
66+
"I", # Isort
67+
"N", # pep8-naming
68+
"D", # Pydocstyle
69+
"ANN", # Pytype annotations
70+
"S", # Bandit
71+
"B", # Bugbear
72+
"COM", # Commas
73+
"C4", # Comprehensions
74+
"ISC", # Implicit string concat
75+
"PIE", # Unnecessary code
76+
"T20", # Catch prints
77+
"PYI", # validate pyi files
78+
"Q", # Checks for quotes
79+
"RSE", # Checks raise statements
80+
"RET", # Checks return statements
81+
"SLF", # Self checks
82+
"SIM", # Simplificator
83+
"PTH", # Pathlib checks
84+
"ERA", # Checks for commented out code
85+
"PL", # PyLint checks
86+
"RUF", # Specific to Ruff checks
87+
"UP", # Pyupgrade
88+
]
89+
ignore = [
90+
"D105", # Missing docstring in magic method
91+
"D107", # Missing docstring in __init__
92+
"D212", # Multi-line docstring summary should start at the first line
93+
"D401", # First line should be in imperative mood
94+
"D104", # Missing docstring in public package
95+
"D100", # Missing docstring in public module
96+
"ANN401", # typing.Any are disallowed in `**kwargs
97+
"PLR0913", # Too many arguments for function call
98+
"D106", # Missing docstring in public nested class
99+
"PYI021", # Docstrings should not be included in stubs
100+
]
101+
102+
[tool.ruff.lint.per-file-ignores]
103+
"python/tests/*" = [
104+
"S101", # Use of assert detected
105+
"S301", # Use of pickle detected
106+
"D103", # Missing docstring in public function
107+
"SLF001", # Private member accessed
108+
"S311", # Standard pseudo-random generators are not suitable for security/cryptographic purposes
109+
"D101", # Missing docstring in public class
110+
]
111+
112+
[tool.ruff.lint.pydocstyle]
113+
convention = "pep257"
114+
ignore-decorators = ["typing.overload"]
115+
116+
[tool.ruff.lint.pylint]
117+
allow-magic-value-types = ["int", "str", "float"]

python/natsrpy/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from natsrpy._inner import Message, Nats, Subscription
22

33
__all__ = [
4+
"Message",
45
"Nats",
56
"Subscription",
6-
"Message",
77
]

python/natsrpy/_inner/__init__.pyi

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,43 @@
1+
from datetime import timedelta
2+
from typing import Any
3+
14
from natsrpy._inner.js import JetStream
25
from natsrpy._inner.message import Message
36

47
class Subscription:
5-
def __aiter__(self) -> "Subscription": ...
8+
def __aiter__(self) -> Subscription: ...
69
async def __anext__(self) -> Message: ...
710

811
class Nats:
912
def __init__(
1013
self,
1114
/,
1215
addrs: list[str] = ["nats://localhost:4222"],
13-
user_and_pass=None,
14-
nkey=None,
15-
token=None,
16-
custom_inbox_prefix=None,
17-
read_buffer_capacity=65535,
18-
sender_capacity=128,
19-
max_reconnects=None,
20-
connection_timeout=5.0,
21-
request_timeout=10.0,
16+
user_and_pass: tuple[str, str] | None = None,
17+
nkey: str | None = None,
18+
token: str | None = None,
19+
custom_inbox_prefix: str | None = None,
20+
read_buffer_capacity: int = 65535,
21+
sender_capacity: int = 128,
22+
max_reconnects: int | None = None,
23+
connection_timeout: timedelta = ...,
24+
request_timeout: timedelta = ...,
2225
) -> None: ...
2326
async def startup(self) -> None: ...
27+
async def shutdown(self) -> None: ...
2428
async def publish(
2529
self,
2630
subject: str,
2731
payload: bytes,
2832
*,
29-
headers: dict[str, str] | None = None,
33+
headers: dict[str, Any] | None = None,
3034
reply: str | None = None,
3135
err_on_disconnect: bool = False,
3236
) -> None: ...
3337
async def request(self, subject: str, payload: bytes) -> None: ...
3438
async def drain(self) -> None: ...
3539
async def flush(self) -> None: ...
36-
async def close(self) -> None: ...
37-
async def subscribe(self, topic: str) -> Subscription: ...
40+
async def subscribe(self, subject: str) -> Subscription: ...
3841
async def jetstream(self) -> JetStream: ...
3942

40-
__all__ = ["Subscription", "Nats", "Message"]
43+
__all__ = ["Message", "Nats", "Subscription"]

0 commit comments

Comments
 (0)