sirr 0.1.0__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,49 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ tags: ["v*"]
7
+ pull_request:
8
+ branches: [main]
9
+
10
+ jobs:
11
+ lint:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ - uses: actions/setup-python@v5
16
+ with:
17
+ python-version: "3.13"
18
+ - run: pip install ruff
19
+ - run: ruff check src/ tests/
20
+ - run: ruff format --check src/ tests/
21
+
22
+ test:
23
+ runs-on: ubuntu-latest
24
+ strategy:
25
+ matrix:
26
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
27
+ steps:
28
+ - uses: actions/checkout@v4
29
+ - uses: actions/setup-python@v5
30
+ with:
31
+ python-version: ${{ matrix.python-version }}
32
+ - run: pip install -e ".[dev]"
33
+ - run: pytest --cov=sirr --cov-report=term-missing
34
+
35
+ publish:
36
+ needs: [lint, test]
37
+ runs-on: ubuntu-latest
38
+ if: startsWith(github.ref, 'refs/tags/v')
39
+ permissions:
40
+ id-token: write
41
+ environment: release
42
+ steps:
43
+ - uses: actions/checkout@v4
44
+ - uses: actions/setup-python@v5
45
+ with:
46
+ python-version: "3.13"
47
+ - run: pip install build
48
+ - run: python -m build
49
+ - uses: pypa/gh-action-pypi-publish@release/v1
sirr-0.1.0/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ dist/
5
+ build/
6
+ .eggs/
7
+ *.egg
8
+ .ruff_cache/
9
+ .pytest_cache/
10
+ .coverage
11
+ htmlcov/
12
+ *.so
13
+ .venv/
14
+ venv/
15
+ env/
sirr-0.1.0/CLAUDE.md ADDED
@@ -0,0 +1,84 @@
1
+ # sirr Python Client — Claude Development Guide
2
+
3
+ ## Purpose
4
+
5
+ Python HTTP client for the Sirr API. Published to PyPI as `sirr`.
6
+ Supports both sync and async usage.
7
+
8
+ ## Architecture
9
+
10
+ ```
11
+ src/sirr/
12
+ ├── __init__.py # Re-exports: SirrClient, AsyncSirrClient, SecretMeta, SirrError
13
+ ├── _exceptions.py # SirrError(status, message)
14
+ ├── _models.py # SecretMeta frozen dataclass with from_dict()
15
+ ├── _transport.py # Shared: build_headers, normalize_server, handle_response
16
+ ├── _client.py # SirrClient (sync, httpx.Client)
17
+ ├── _async_client.py # AsyncSirrClient (async, httpx.AsyncClient)
18
+ └── py.typed # PEP 561 marker
19
+ ```
20
+
21
+ **DRY strategy**: `_transport.py` handles headers, URL normalization, and response parsing.
22
+ Both clients call into it. No base class — the duplication across 6 methods is minimal.
23
+
24
+ ## API Surface
25
+
26
+ ```python
27
+ class SirrClient:
28
+ def __init__(self, server: str, token: str): ...
29
+
30
+ # Sync
31
+ def push(self, key: str, value: str, *, ttl: int | None = None, reads: int | None = None) -> None
32
+ def get(self, key: str) -> str | None # None if burned/expired
33
+ def delete(self, key: str) -> None
34
+ def list(self) -> list[SecretMeta]
35
+ def pull_all(self) -> dict[str, str]
36
+ def prune(self) -> int
37
+ def env(self) -> ContextManager # injects into os.environ
38
+
39
+ class AsyncSirrClient:
40
+ # Same surface but all methods are async
41
+ # pull_all() uses asyncio.gather for concurrent fetches
42
+ # env() is an @asynccontextmanager
43
+ ```
44
+
45
+ ## Stack
46
+
47
+ - Python 3.10+
48
+ - `httpx` for HTTP (supports both sync and async)
49
+ - `pytest` + `pytest-asyncio` + `respx` for tests
50
+ - `ruff` for linting and formatting
51
+ - `hatchling` build backend
52
+ - Published via `pyproject.toml` (no setup.py)
53
+
54
+ ## Key Rules
55
+
56
+ - `get()` returns `None` on 404 — do not raise
57
+ - All other non-2xx responses raise `SirrError`
58
+ - Never log secret values
59
+ - `env()` context manager must restore original env on exit (even on exception)
60
+ - Keys are URL-encoded in paths (`urllib.parse.quote(key, safe='')`)
61
+
62
+ ## Commands
63
+
64
+ ```bash
65
+ # Install (editable + dev deps)
66
+ pip install -e ".[dev]"
67
+
68
+ # Lint
69
+ ruff check src/ tests/
70
+ ruff format --check src/ tests/
71
+
72
+ # Test
73
+ pytest --cov=sirr --cov-report=term-missing
74
+
75
+ # Build
76
+ python -m build
77
+ ```
78
+
79
+ ## Pre-Commit Checklist
80
+
81
+ Before every commit and push, review and update if needed:
82
+
83
+ 1. **README.md** — Does it reflect new methods or behavior?
84
+ 2. **CLAUDE.md** — New constraints or API decisions worth recording?
sirr-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 sirrlock
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.
sirr-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,203 @@
1
+ Metadata-Version: 2.5
2
+ Name: sirr
3
+ Version: 0.1.0
4
+ Summary: Python client for the Sirr ephemeral secret vault
5
+ Project-URL: Homepage, https://github.com/sirrlock/python
6
+ Project-URL: Repository, https://github.com/sirrlock/python
7
+ Author: sirrlock
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Keywords: agents,ai,ephemeral,secrets,vault
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Typing :: Typed
20
+ Requires-Python: >=3.10
21
+ Requires-Dist: httpx<1,>=0.27
22
+ Provides-Extra: dev
23
+ Requires-Dist: build; extra == 'dev'
24
+ Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
25
+ Requires-Dist: pytest-cov>=6; extra == 'dev'
26
+ Requires-Dist: pytest>=8; extra == 'dev'
27
+ Requires-Dist: respx>=0.22; extra == 'dev'
28
+ Requires-Dist: ruff>=0.9; extra == 'dev'
29
+ Description-Content-Type: text/markdown
30
+
31
+ # sirr (Python)
32
+
33
+ [![CI](https://github.com/sirrlock/python/actions/workflows/ci.yml/badge.svg)](https://github.com/sirrlock/python/actions/workflows/ci.yml)
34
+ [![PyPI](https://img.shields.io/pypi/v/sirr)](https://pypi.org/project/sirr/)
35
+ [![Python](https://img.shields.io/pypi/pyversions/sirr)](https://pypi.org/project/sirr/)
36
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
37
+
38
+ **Ephemeral secrets for Python AI agents. Credentials that delete themselves.**
39
+
40
+ `sirr` is the Python client for [Sirr](https://github.com/sirrlock/sirr) — a self-hosted vault where every secret expires by read count, by time, or both. Built for the Python AI ecosystem: LangChain, CrewAI, AutoGen, LlamaIndex, and any framework that needs to hand credentials to agents without leaving them lying around forever.
41
+
42
+ ---
43
+
44
+ ## The Problem It Solves
45
+
46
+ Python dominates the AI/ML landscape. That means Python is where credentials get handed to agents, embedded in tool calls, interpolated into prompts, and logged by frameworks. Every time an agent reads a database URL or API key, you have limited visibility into what that framework stored, logged, or will use for fine-tuning.
47
+
48
+ The standard answer — "rotate your secrets after every session" — doesn't scale. You forget. It's tedious. It requires manual IAM work.
49
+
50
+ Sirr gives you a better primitive: **credentials that enforce their own expiry.** An agent reads it once. The server deletes it. You don't have to remember to clean anything up.
51
+
52
+ ```python
53
+ # Give a CrewAI agent exactly one read of your API key
54
+ sirr.push("OPENAI_KEY", api_key, reads=1, ttl=600)
55
+
56
+ # Agent calls sirr.get("OPENAI_KEY") → gets the value → record deleted
57
+ # Even if CrewAI logs the value to its trace file, it's already dead on your server
58
+ ```
59
+
60
+ ---
61
+
62
+ ## Install
63
+
64
+ ```bash
65
+ pip install sirr
66
+ ```
67
+
68
+ Requires Python 3.10+. Supports sync and async.
69
+
70
+ ---
71
+
72
+ ## Usage
73
+
74
+ ```python
75
+ import os
76
+ from sirr import SirrClient
77
+
78
+ sirr = SirrClient(
79
+ server=os.environ.get("SIRR_SERVER", "http://localhost:8080"),
80
+ token=os.environ["SIRR_TOKEN"],
81
+ )
82
+
83
+ # Push a one-time secret
84
+ sirr.push("API_KEY", "sk-...", reads=1, ttl=3600)
85
+
86
+ # Retrieve — None if burned or expired
87
+ value = sirr.get("API_KEY")
88
+
89
+ # Pull all secrets into a dict
90
+ secrets = sirr.pull_all()
91
+ # → {"API_KEY": "sk-...", "DB_URL": "postgres://..."}
92
+
93
+ # Inject as environment variables for the duration of a block
94
+ with sirr.env():
95
+ # os.environ["API_KEY"] is set here
96
+ run_agent_task()
97
+ # restored on exit, even on exception
98
+
99
+ # Delete immediately
100
+ sirr.delete("API_KEY")
101
+
102
+ # List active secrets (metadata only — no values)
103
+ entries = sirr.list()
104
+
105
+ # Prune expired secrets
106
+ pruned = sirr.prune()
107
+ ```
108
+
109
+ ### Async
110
+
111
+ ```python
112
+ from sirr import AsyncSirrClient
113
+
114
+ async with AsyncSirrClient(server=..., token=...) as sirr:
115
+ await sirr.push("API_KEY", "sk-...", reads=1, ttl=3600)
116
+ value = await sirr.get("API_KEY")
117
+ ```
118
+
119
+ ---
120
+
121
+ ## AI Workflows
122
+
123
+ ### LangChain tool with scoped credential
124
+
125
+ ```python
126
+ from langchain.tools import tool
127
+
128
+ @tool
129
+ def query_production_db(sql: str) -> str:
130
+ """Run a SQL query against the production database."""
131
+ conn_str = sirr.get("AGENT_DB")
132
+ if conn_str is None:
133
+ raise ValueError("DB credential expired or already used")
134
+ return run_query(conn_str, sql)
135
+ ```
136
+
137
+ ### CrewAI agent with burn-after-use credential
138
+
139
+ ```python
140
+ from crewai import Agent, Task, Crew
141
+
142
+ # Push before the crew runs — burns after first read
143
+ sirr.push("STRIPE_KEY", stripe_key, reads=1, ttl=600)
144
+
145
+ analyst = Agent(
146
+ role="Data Analyst",
147
+ goal="Fetch and analyze payment data",
148
+ tools=[stripe_tool], # tool calls sirr.get("STRIPE_KEY") internally
149
+ )
150
+
151
+ crew = Crew(agents=[analyst], tasks=[analysis_task])
152
+ crew.kickoff()
153
+ # STRIPE_KEY was read once by the tool — already deleted
154
+ ```
155
+
156
+ ### AutoGen multi-agent with isolated credentials
157
+
158
+ ```python
159
+ import autogen
160
+
161
+ # Each agent gets its own scoped, expiring credential
162
+ sirr.push("AGENT_1_DB", db_url_1, reads=5, ttl=3600)
163
+ sirr.push("AGENT_2_DB", db_url_2, reads=5, ttl=3600)
164
+
165
+ # Agents run — their credential budgets are enforced server-side
166
+ # No agent can exceed its read limit even if the framework retries
167
+ ```
168
+
169
+ ### Inject all secrets into a subprocess
170
+
171
+ ```python
172
+ with sirr.env():
173
+ # All Sirr secrets set as os.environ
174
+ subprocess.run(["python", "agent_script.py"])
175
+ # Env restored after block
176
+ ```
177
+
178
+ ### pytest fixture for CI secrets
179
+
180
+ ```python
181
+ import pytest
182
+ from sirr import SirrClient
183
+
184
+ @pytest.fixture(autouse=True)
185
+ def inject_test_secrets():
186
+ sirr = SirrClient(server=os.environ["SIRR_SERVER"], token=os.environ["SIRR_TOKEN"])
187
+ with sirr.env():
188
+ yield
189
+ # Credentials cleaned from env after each test
190
+ ```
191
+
192
+ ---
193
+
194
+ ## Related
195
+
196
+ | Package | Description |
197
+ |---------|-------------|
198
+ | [sirr](https://github.com/sirrlock/sirr) | Rust monorepo: `sirrd` server + `sirr` CLI |
199
+ | [@sirrlock/mcp](https://github.com/sirrlock/mcp) | MCP server for AI assistants |
200
+ | [@sirrlock/node](https://github.com/sirrlock/node) | Node.js / TypeScript SDK |
201
+ | [Sirr.Client (NuGet)](https://github.com/sirrlock/dotnet) | .NET SDK |
202
+ | [sirr.dev](https://sirr.dev) | Documentation |
203
+ | [sirrlock.com](https://sirrlock.com) | Managed cloud + license keys |
sirr-0.1.0/README.md ADDED
@@ -0,0 +1,173 @@
1
+ # sirr (Python)
2
+
3
+ [![CI](https://github.com/sirrlock/python/actions/workflows/ci.yml/badge.svg)](https://github.com/sirrlock/python/actions/workflows/ci.yml)
4
+ [![PyPI](https://img.shields.io/pypi/v/sirr)](https://pypi.org/project/sirr/)
5
+ [![Python](https://img.shields.io/pypi/pyversions/sirr)](https://pypi.org/project/sirr/)
6
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
7
+
8
+ **Ephemeral secrets for Python AI agents. Credentials that delete themselves.**
9
+
10
+ `sirr` is the Python client for [Sirr](https://github.com/sirrlock/sirr) — a self-hosted vault where every secret expires by read count, by time, or both. Built for the Python AI ecosystem: LangChain, CrewAI, AutoGen, LlamaIndex, and any framework that needs to hand credentials to agents without leaving them lying around forever.
11
+
12
+ ---
13
+
14
+ ## The Problem It Solves
15
+
16
+ Python dominates the AI/ML landscape. That means Python is where credentials get handed to agents, embedded in tool calls, interpolated into prompts, and logged by frameworks. Every time an agent reads a database URL or API key, you have limited visibility into what that framework stored, logged, or will use for fine-tuning.
17
+
18
+ The standard answer — "rotate your secrets after every session" — doesn't scale. You forget. It's tedious. It requires manual IAM work.
19
+
20
+ Sirr gives you a better primitive: **credentials that enforce their own expiry.** An agent reads it once. The server deletes it. You don't have to remember to clean anything up.
21
+
22
+ ```python
23
+ # Give a CrewAI agent exactly one read of your API key
24
+ sirr.push("OPENAI_KEY", api_key, reads=1, ttl=600)
25
+
26
+ # Agent calls sirr.get("OPENAI_KEY") → gets the value → record deleted
27
+ # Even if CrewAI logs the value to its trace file, it's already dead on your server
28
+ ```
29
+
30
+ ---
31
+
32
+ ## Install
33
+
34
+ ```bash
35
+ pip install sirr
36
+ ```
37
+
38
+ Requires Python 3.10+. Supports sync and async.
39
+
40
+ ---
41
+
42
+ ## Usage
43
+
44
+ ```python
45
+ import os
46
+ from sirr import SirrClient
47
+
48
+ sirr = SirrClient(
49
+ server=os.environ.get("SIRR_SERVER", "http://localhost:8080"),
50
+ token=os.environ["SIRR_TOKEN"],
51
+ )
52
+
53
+ # Push a one-time secret
54
+ sirr.push("API_KEY", "sk-...", reads=1, ttl=3600)
55
+
56
+ # Retrieve — None if burned or expired
57
+ value = sirr.get("API_KEY")
58
+
59
+ # Pull all secrets into a dict
60
+ secrets = sirr.pull_all()
61
+ # → {"API_KEY": "sk-...", "DB_URL": "postgres://..."}
62
+
63
+ # Inject as environment variables for the duration of a block
64
+ with sirr.env():
65
+ # os.environ["API_KEY"] is set here
66
+ run_agent_task()
67
+ # restored on exit, even on exception
68
+
69
+ # Delete immediately
70
+ sirr.delete("API_KEY")
71
+
72
+ # List active secrets (metadata only — no values)
73
+ entries = sirr.list()
74
+
75
+ # Prune expired secrets
76
+ pruned = sirr.prune()
77
+ ```
78
+
79
+ ### Async
80
+
81
+ ```python
82
+ from sirr import AsyncSirrClient
83
+
84
+ async with AsyncSirrClient(server=..., token=...) as sirr:
85
+ await sirr.push("API_KEY", "sk-...", reads=1, ttl=3600)
86
+ value = await sirr.get("API_KEY")
87
+ ```
88
+
89
+ ---
90
+
91
+ ## AI Workflows
92
+
93
+ ### LangChain tool with scoped credential
94
+
95
+ ```python
96
+ from langchain.tools import tool
97
+
98
+ @tool
99
+ def query_production_db(sql: str) -> str:
100
+ """Run a SQL query against the production database."""
101
+ conn_str = sirr.get("AGENT_DB")
102
+ if conn_str is None:
103
+ raise ValueError("DB credential expired or already used")
104
+ return run_query(conn_str, sql)
105
+ ```
106
+
107
+ ### CrewAI agent with burn-after-use credential
108
+
109
+ ```python
110
+ from crewai import Agent, Task, Crew
111
+
112
+ # Push before the crew runs — burns after first read
113
+ sirr.push("STRIPE_KEY", stripe_key, reads=1, ttl=600)
114
+
115
+ analyst = Agent(
116
+ role="Data Analyst",
117
+ goal="Fetch and analyze payment data",
118
+ tools=[stripe_tool], # tool calls sirr.get("STRIPE_KEY") internally
119
+ )
120
+
121
+ crew = Crew(agents=[analyst], tasks=[analysis_task])
122
+ crew.kickoff()
123
+ # STRIPE_KEY was read once by the tool — already deleted
124
+ ```
125
+
126
+ ### AutoGen multi-agent with isolated credentials
127
+
128
+ ```python
129
+ import autogen
130
+
131
+ # Each agent gets its own scoped, expiring credential
132
+ sirr.push("AGENT_1_DB", db_url_1, reads=5, ttl=3600)
133
+ sirr.push("AGENT_2_DB", db_url_2, reads=5, ttl=3600)
134
+
135
+ # Agents run — their credential budgets are enforced server-side
136
+ # No agent can exceed its read limit even if the framework retries
137
+ ```
138
+
139
+ ### Inject all secrets into a subprocess
140
+
141
+ ```python
142
+ with sirr.env():
143
+ # All Sirr secrets set as os.environ
144
+ subprocess.run(["python", "agent_script.py"])
145
+ # Env restored after block
146
+ ```
147
+
148
+ ### pytest fixture for CI secrets
149
+
150
+ ```python
151
+ import pytest
152
+ from sirr import SirrClient
153
+
154
+ @pytest.fixture(autouse=True)
155
+ def inject_test_secrets():
156
+ sirr = SirrClient(server=os.environ["SIRR_SERVER"], token=os.environ["SIRR_TOKEN"])
157
+ with sirr.env():
158
+ yield
159
+ # Credentials cleaned from env after each test
160
+ ```
161
+
162
+ ---
163
+
164
+ ## Related
165
+
166
+ | Package | Description |
167
+ |---------|-------------|
168
+ | [sirr](https://github.com/sirrlock/sirr) | Rust monorepo: `sirrd` server + `sirr` CLI |
169
+ | [@sirrlock/mcp](https://github.com/sirrlock/mcp) | MCP server for AI assistants |
170
+ | [@sirrlock/node](https://github.com/sirrlock/node) | Node.js / TypeScript SDK |
171
+ | [Sirr.Client (NuGet)](https://github.com/sirrlock/dotnet) | .NET SDK |
172
+ | [sirr.dev](https://sirr.dev) | Documentation |
173
+ | [sirrlock.com](https://sirrlock.com) | Managed cloud + license keys |
@@ -0,0 +1,54 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "sirr"
7
+ version = "0.1.0"
8
+ description = "Python client for the Sirr ephemeral secret vault"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.10"
12
+ authors = [{ name = "sirrlock" }]
13
+ keywords = ["secrets", "vault", "ephemeral", "ai", "agents"]
14
+ classifiers = [
15
+ "Development Status :: 4 - Beta",
16
+ "Intended Audience :: Developers",
17
+ "License :: OSI Approved :: MIT License",
18
+ "Programming Language :: Python :: 3",
19
+ "Programming Language :: Python :: 3.10",
20
+ "Programming Language :: Python :: 3.11",
21
+ "Programming Language :: Python :: 3.12",
22
+ "Programming Language :: Python :: 3.13",
23
+ "Typing :: Typed",
24
+ ]
25
+ dependencies = ["httpx>=0.27,<1"]
26
+
27
+ [project.optional-dependencies]
28
+ dev = [
29
+ "pytest>=8",
30
+ "pytest-asyncio>=0.24",
31
+ "respx>=0.22",
32
+ "ruff>=0.9",
33
+ "pytest-cov>=6",
34
+ "build",
35
+ ]
36
+
37
+ [project.urls]
38
+ Homepage = "https://github.com/sirrlock/python"
39
+ Repository = "https://github.com/sirrlock/python"
40
+
41
+ [tool.hatch.build.targets.wheel]
42
+ packages = ["src/sirr"]
43
+
44
+ [tool.ruff]
45
+ target-version = "py310"
46
+ line-length = 100
47
+ src = ["src", "tests"]
48
+
49
+ [tool.ruff.lint]
50
+ select = ["E", "F", "I", "UP", "B", "SIM", "RUF"]
51
+
52
+ [tool.pytest.ini_options]
53
+ asyncio_mode = "auto"
54
+ testpaths = ["tests"]
@@ -0,0 +1,25 @@
1
+ """sirr — Python client for the Sirr ephemeral secret vault."""
2
+
3
+ from sirr._async_client import AsyncSirrClient
4
+ from sirr._client import SirrClient
5
+ from sirr._exceptions import SirrError
6
+ from sirr._models import (
7
+ ApiKey,
8
+ ApiKeyCreateResult,
9
+ AuditEvent,
10
+ SecretMeta,
11
+ Webhook,
12
+ WebhookCreateResult,
13
+ )
14
+
15
+ __all__ = [
16
+ "ApiKey",
17
+ "ApiKeyCreateResult",
18
+ "AsyncSirrClient",
19
+ "AuditEvent",
20
+ "SecretMeta",
21
+ "SirrClient",
22
+ "SirrError",
23
+ "Webhook",
24
+ "WebhookCreateResult",
25
+ ]