pytest-nats 0.0.2.dev1__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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mikołaj Nowak
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.
@@ -0,0 +1,186 @@
1
+ Metadata-Version: 2.4
2
+ Name: pytest-nats
3
+ Version: 0.0.2.dev1
4
+ Summary: Pytest helpers for running ad-hoc NATS servers
5
+ License-Expression: MIT
6
+ License-File: LICENSE
7
+ Classifier: Framework :: Pytest
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Classifier: Programming Language :: Python :: 3.14
14
+ Classifier: Programming Language :: Python :: 3.15
15
+ Classifier: Typing :: Typed
16
+ Project-URL: Repository, https://github.com/m3nowak/pytest-nats
17
+ Project-URL: Issues, https://github.com/m3nowak/pytest-nats/issues
18
+ Requires-Python: >=3.11
19
+ Requires-Dist: httpx2>=2.12.0
20
+ Requires-Dist: platformdirs>=4.11.5
21
+ Requires-Dist: pytest>=8.4.2
22
+ Description-Content-Type: text/markdown
23
+
24
+ # pytest-nats
25
+
26
+ Pytest helpers for starting isolated test NATS servers.
27
+
28
+ ## Installation
29
+
30
+ ```shell
31
+ pip install pytest-nats
32
+ ```
33
+
34
+ pytest-nats does not register a global pytest plugin. Declare each server fixture
35
+ explicitly in `conftest.py`; the variable name becomes the fixture name:
36
+
37
+ ```python
38
+ from pytest_nats import nats_server_fixture
39
+
40
+ nats_server = nats_server_fixture()
41
+ ```
42
+
43
+ Tests receive a read-only `NatsServer` with the client URL, host, dynamic port,
44
+ resolved NATS version, JetStream state, and live `stdout` and `stderr` snapshots:
45
+
46
+ ```python
47
+ from pytest_nats import NatsServer
48
+
49
+
50
+ def test_messaging(nats_server: NatsServer) -> None:
51
+ assert nats_server.url == f"nats://127.0.0.1:{nats_server.port}"
52
+ assert not nats_server.jetstream_enabled
53
+ ```
54
+
55
+ The fixture binds its unauthenticated client and internal monitoring listeners
56
+ only to `127.0.0.1`, selects dynamic ports, and waits for both a NATS protocol
57
+ exchange and the health endpoint before yielding. It terminates the server and
58
+ removes generated configuration and data at the end of the selected scope.
59
+
60
+ ## JetStream
61
+
62
+ Enable JetStream when declaring the fixture. One server supports both memory-
63
+ and file-backed streams; client code remains responsible for creating streams
64
+ and consumers.
65
+
66
+ ```python
67
+ from pytest_nats import nats_server_fixture
68
+
69
+ jetstream_server = nats_server_fixture(
70
+ jetstream=True,
71
+ max_memory_store=512 * 1024 * 1024,
72
+ max_file_store=2 * 1024 * 1024 * 1024,
73
+ )
74
+ ```
75
+
76
+ The default aggregate limits are 256 MiB of memory and 1 GiB of file storage.
77
+ File data is isolated per server and removed during teardown.
78
+
79
+ ## Fixture Scope
80
+
81
+ Function scope is the default. Module and session scopes retain server and
82
+ JetStream state for their normal pytest lifetime:
83
+
84
+ ```python
85
+ module_nats = nats_server_fixture(scope="module")
86
+ session_nats = nats_server_fixture(scope="session", jetstream=True)
87
+ ```
88
+
89
+ Supported scopes are `function`, `module`, and `session`.
90
+
91
+ ## NATS executable selection
92
+
93
+ By default, pytest-nats finds `nats-server` on setup-time `PATH` and validates
94
+ that it reports a NATS 2.x semantic version. Use `Local` to select another
95
+ command name or path. Relative paths containing a directory are resolved from
96
+ pytest's root path.
97
+
98
+ ```python
99
+ from pathlib import Path
100
+
101
+ from pytest_nats import GitHub, Local, Mise, Provision, nats_server_fixture
102
+
103
+ default_local_nats = nats_server_fixture()
104
+ alternate_local_nats = nats_server_fixture(Local("nats-server-another"))
105
+ local_path_nats = nats_server_fixture(Local(Path("tools/nats-server")))
106
+ latest_nats = nats_server_fixture(Provision())
107
+ mise_nats = nats_server_fixture(Mise("2.12"))
108
+ github_nats = nats_server_fixture(GitHub("2.12.15", cache_dir=Path(".cache/nats")))
109
+ ```
110
+
111
+ `Local`, `Provision`, `Mise`, and `GitHub` are immutable source values. Raw
112
+ strings and paths are not accepted as the fixture's `binary` argument.
113
+ `Provision` prefers Mise when it is available on setup-time `PATH` and uses
114
+ GitHub otherwise. Automatic provisioning accepts `latest`, major, major-minor,
115
+ and exact stable NATS 2.x selectors that can select releases starting at 2.2.0.
116
+ `startup_timeout` sets the positive setup deadline in seconds and defaults to
117
+ 10 seconds.
118
+
119
+ ### mise
120
+
121
+ [mise](https://mise.jdx.dev/) is a development-tool version manager. `Mise`
122
+ asks the `mise` executable on `PATH` to install and locate the selector through its
123
+ [GitHub backend](https://mise.jdx.dev/dev-tools/backends/github.html). The
124
+ selector is passed directly to Mise. Successful acquisition is reused for the
125
+ rest of the pytest process, while failures remain retryable.
126
+
127
+ ### GitHub
128
+
129
+ `GitHub` downloads official
130
+ [NATS Server releases](https://github.com/nats-io/nats-server/releases),
131
+ verifies their published checksums, and atomically stores executables in the
132
+ selected cache directory. Existing regular executable cache entries are trusted
133
+ without running or rehashing them. Set the optional `GITHUB_TOKEN` environment variable
134
+ to authenticate GitHub API and download requests, which can avoid anonymous API
135
+ rate limits. See GitHub's
136
+ [personal access token documentation](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)
137
+ for token creation and handling guidance.
138
+
139
+ Executable lookup, version resolution, and provisioning failures raise
140
+ `NatsExecutableError`. Its `category` is an `ExecutableErrorCategory` value.
141
+ Server startup and lifecycle failures raise `NatsServerError`; its `returncode`,
142
+ `stdout`, and `stderr` attributes retain available diagnostics.
143
+
144
+ ## Development
145
+
146
+ Install [mise](https://mise.jdx.dev/getting-started.html), then install the project
147
+ tools and dependencies:
148
+
149
+ ```shell
150
+ mise run install
151
+ mise run setup
152
+ ```
153
+
154
+ Run tests and checks:
155
+
156
+ ```shell
157
+ mise run test
158
+ mise run check
159
+ ```
160
+
161
+ Apply automatic lint and formatting fixes:
162
+
163
+ ```shell
164
+ mise run fix
165
+ ```
166
+
167
+ ## Releasing
168
+
169
+ Releases run from `.github/workflows/release.yml`. The workflow accepts a stable,
170
+ canonical PEP 440 version, runs the complete CI workflow, builds and validates
171
+ the source distribution and wheel, publishes them to PyPI, then publishes the
172
+ draft GitHub Release. Run it from the `main` branch in the GitHub Actions UI.
173
+ The first intended version is `0.0.1`, which creates tag `v0.0.1`.
174
+
175
+ Before the first release, create a pending Trusted Publisher on PyPI with these
176
+ values:
177
+
178
+ - PyPI project: `pytest-nats`
179
+ - GitHub owner: `m3nowak`
180
+ - GitHub repository: `pytest-nats`
181
+ - Workflow filename: `release.yml`
182
+ - Environment: `pypi`
183
+
184
+ Create the `pypi` environment in the GitHub repository without required
185
+ reviewers. The workflow requests an OIDC token only in the PyPI publication job;
186
+ no PyPI API token is needed.
@@ -0,0 +1,163 @@
1
+ # pytest-nats
2
+
3
+ Pytest helpers for starting isolated test NATS servers.
4
+
5
+ ## Installation
6
+
7
+ ```shell
8
+ pip install pytest-nats
9
+ ```
10
+
11
+ pytest-nats does not register a global pytest plugin. Declare each server fixture
12
+ explicitly in `conftest.py`; the variable name becomes the fixture name:
13
+
14
+ ```python
15
+ from pytest_nats import nats_server_fixture
16
+
17
+ nats_server = nats_server_fixture()
18
+ ```
19
+
20
+ Tests receive a read-only `NatsServer` with the client URL, host, dynamic port,
21
+ resolved NATS version, JetStream state, and live `stdout` and `stderr` snapshots:
22
+
23
+ ```python
24
+ from pytest_nats import NatsServer
25
+
26
+
27
+ def test_messaging(nats_server: NatsServer) -> None:
28
+ assert nats_server.url == f"nats://127.0.0.1:{nats_server.port}"
29
+ assert not nats_server.jetstream_enabled
30
+ ```
31
+
32
+ The fixture binds its unauthenticated client and internal monitoring listeners
33
+ only to `127.0.0.1`, selects dynamic ports, and waits for both a NATS protocol
34
+ exchange and the health endpoint before yielding. It terminates the server and
35
+ removes generated configuration and data at the end of the selected scope.
36
+
37
+ ## JetStream
38
+
39
+ Enable JetStream when declaring the fixture. One server supports both memory-
40
+ and file-backed streams; client code remains responsible for creating streams
41
+ and consumers.
42
+
43
+ ```python
44
+ from pytest_nats import nats_server_fixture
45
+
46
+ jetstream_server = nats_server_fixture(
47
+ jetstream=True,
48
+ max_memory_store=512 * 1024 * 1024,
49
+ max_file_store=2 * 1024 * 1024 * 1024,
50
+ )
51
+ ```
52
+
53
+ The default aggregate limits are 256 MiB of memory and 1 GiB of file storage.
54
+ File data is isolated per server and removed during teardown.
55
+
56
+ ## Fixture Scope
57
+
58
+ Function scope is the default. Module and session scopes retain server and
59
+ JetStream state for their normal pytest lifetime:
60
+
61
+ ```python
62
+ module_nats = nats_server_fixture(scope="module")
63
+ session_nats = nats_server_fixture(scope="session", jetstream=True)
64
+ ```
65
+
66
+ Supported scopes are `function`, `module`, and `session`.
67
+
68
+ ## NATS executable selection
69
+
70
+ By default, pytest-nats finds `nats-server` on setup-time `PATH` and validates
71
+ that it reports a NATS 2.x semantic version. Use `Local` to select another
72
+ command name or path. Relative paths containing a directory are resolved from
73
+ pytest's root path.
74
+
75
+ ```python
76
+ from pathlib import Path
77
+
78
+ from pytest_nats import GitHub, Local, Mise, Provision, nats_server_fixture
79
+
80
+ default_local_nats = nats_server_fixture()
81
+ alternate_local_nats = nats_server_fixture(Local("nats-server-another"))
82
+ local_path_nats = nats_server_fixture(Local(Path("tools/nats-server")))
83
+ latest_nats = nats_server_fixture(Provision())
84
+ mise_nats = nats_server_fixture(Mise("2.12"))
85
+ github_nats = nats_server_fixture(GitHub("2.12.15", cache_dir=Path(".cache/nats")))
86
+ ```
87
+
88
+ `Local`, `Provision`, `Mise`, and `GitHub` are immutable source values. Raw
89
+ strings and paths are not accepted as the fixture's `binary` argument.
90
+ `Provision` prefers Mise when it is available on setup-time `PATH` and uses
91
+ GitHub otherwise. Automatic provisioning accepts `latest`, major, major-minor,
92
+ and exact stable NATS 2.x selectors that can select releases starting at 2.2.0.
93
+ `startup_timeout` sets the positive setup deadline in seconds and defaults to
94
+ 10 seconds.
95
+
96
+ ### mise
97
+
98
+ [mise](https://mise.jdx.dev/) is a development-tool version manager. `Mise`
99
+ asks the `mise` executable on `PATH` to install and locate the selector through its
100
+ [GitHub backend](https://mise.jdx.dev/dev-tools/backends/github.html). The
101
+ selector is passed directly to Mise. Successful acquisition is reused for the
102
+ rest of the pytest process, while failures remain retryable.
103
+
104
+ ### GitHub
105
+
106
+ `GitHub` downloads official
107
+ [NATS Server releases](https://github.com/nats-io/nats-server/releases),
108
+ verifies their published checksums, and atomically stores executables in the
109
+ selected cache directory. Existing regular executable cache entries are trusted
110
+ without running or rehashing them. Set the optional `GITHUB_TOKEN` environment variable
111
+ to authenticate GitHub API and download requests, which can avoid anonymous API
112
+ rate limits. See GitHub's
113
+ [personal access token documentation](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)
114
+ for token creation and handling guidance.
115
+
116
+ Executable lookup, version resolution, and provisioning failures raise
117
+ `NatsExecutableError`. Its `category` is an `ExecutableErrorCategory` value.
118
+ Server startup and lifecycle failures raise `NatsServerError`; its `returncode`,
119
+ `stdout`, and `stderr` attributes retain available diagnostics.
120
+
121
+ ## Development
122
+
123
+ Install [mise](https://mise.jdx.dev/getting-started.html), then install the project
124
+ tools and dependencies:
125
+
126
+ ```shell
127
+ mise run install
128
+ mise run setup
129
+ ```
130
+
131
+ Run tests and checks:
132
+
133
+ ```shell
134
+ mise run test
135
+ mise run check
136
+ ```
137
+
138
+ Apply automatic lint and formatting fixes:
139
+
140
+ ```shell
141
+ mise run fix
142
+ ```
143
+
144
+ ## Releasing
145
+
146
+ Releases run from `.github/workflows/release.yml`. The workflow accepts a stable,
147
+ canonical PEP 440 version, runs the complete CI workflow, builds and validates
148
+ the source distribution and wheel, publishes them to PyPI, then publishes the
149
+ draft GitHub Release. Run it from the `main` branch in the GitHub Actions UI.
150
+ The first intended version is `0.0.1`, which creates tag `v0.0.1`.
151
+
152
+ Before the first release, create a pending Trusted Publisher on PyPI with these
153
+ values:
154
+
155
+ - PyPI project: `pytest-nats`
156
+ - GitHub owner: `m3nowak`
157
+ - GitHub repository: `pytest-nats`
158
+ - Workflow filename: `release.yml`
159
+ - Environment: `pypi`
160
+
161
+ Create the `pypi` environment in the GitHub repository without required
162
+ reviewers. The workflow requests an OIDC token only in the PyPI publication job;
163
+ no PyPI API token is needed.
@@ -0,0 +1,88 @@
1
+ [project]
2
+ name = "pytest-nats"
3
+ dynamic = []
4
+ description = "Pytest helpers for running ad-hoc NATS servers"
5
+ readme = "README.md"
6
+ requires-python = ">=3.11"
7
+ license = "MIT"
8
+ license-files = [
9
+ "LICENSE",
10
+ ]
11
+ classifiers = [
12
+ "Framework :: Pytest",
13
+ "Intended Audience :: Developers",
14
+ "Programming Language :: Python :: 3",
15
+ "Programming Language :: Python :: 3.11",
16
+ "Programming Language :: Python :: 3.12",
17
+ "Programming Language :: Python :: 3.13",
18
+ "Programming Language :: Python :: 3.14",
19
+ "Programming Language :: Python :: 3.15",
20
+ "Typing :: Typed",
21
+ ]
22
+ dependencies = [
23
+ "httpx2>=2.12.0",
24
+ "platformdirs>=4.11.5",
25
+ "pytest>=8.4.2",
26
+ ]
27
+ version = "0.0.2.dev1"
28
+
29
+ [project.urls]
30
+ Repository = "https://github.com/m3nowak/pytest-nats"
31
+ Issues = "https://github.com/m3nowak/pytest-nats/issues"
32
+
33
+ [build-system]
34
+ requires = [
35
+ "pdm-backend>=2.4.0,<3",
36
+ ]
37
+ build-backend = "pdm.backend"
38
+
39
+ [tool.pdm.version]
40
+ source = "scm"
41
+ tag_filter = "v*"
42
+ fallback_version = "0.0.0"
43
+
44
+ [tool.pyright]
45
+ include = [
46
+ "src",
47
+ "tests",
48
+ ]
49
+ pythonVersion = "3.11"
50
+ typeCheckingMode = "strict"
51
+
52
+ [tool.pytest.ini_options]
53
+ addopts = [
54
+ "--strict-config",
55
+ "--strict-markers",
56
+ "-m",
57
+ "not integration",
58
+ ]
59
+ markers = [
60
+ "integration: uses real NATS providers and requires PYTEST_NATS_RUN_INTEGRATION=1",
61
+ ]
62
+ testpaths = [
63
+ "tests",
64
+ ]
65
+
66
+ [tool.ruff]
67
+ line-length = 120
68
+ target-version = "py311"
69
+
70
+ [tool.ruff.lint]
71
+ extend-select = [
72
+ "ANN001",
73
+ "ANN002",
74
+ "ANN003",
75
+ "ANN201",
76
+ "ANN202",
77
+ "ANN204",
78
+ "ANN205",
79
+ "ANN206",
80
+ ]
81
+
82
+ [dependency-groups]
83
+ dev = [
84
+ "nats-py>=2.11.0",
85
+ "pyright>=1.1.405",
86
+ "pytest-httpx2>=1.0.0",
87
+ "ruff>=0.12.12",
88
+ ]
@@ -0,0 +1,16 @@
1
+ """Pytest helpers for running test NATS servers."""
2
+
3
+ from ._provisioning import ExecutableErrorCategory, GitHub, Local, Mise, NatsExecutableError, Provision
4
+ from ._runtime import NatsServer, NatsServerError, nats_server_fixture
5
+
6
+ __all__ = [
7
+ "ExecutableErrorCategory",
8
+ "GitHub",
9
+ "Local",
10
+ "Mise",
11
+ "NatsExecutableError",
12
+ "NatsServer",
13
+ "NatsServerError",
14
+ "Provision",
15
+ "nats_server_fixture",
16
+ ]