sv-number 0.2.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.
- sv_number-0.2.0/.gitignore +46 -0
- sv_number-0.2.0/LICENSE +15 -0
- sv_number-0.2.0/PKG-INFO +125 -0
- sv_number-0.2.0/README.md +113 -0
- sv_number-0.2.0/examples/check.py +21 -0
- sv_number-0.2.0/pyproject.toml +44 -0
- sv_number-0.2.0/src/sv_number/__init__.py +14 -0
- sv_number-0.2.0/src/sv_number/client.py +234 -0
- sv_number-0.2.0/src/sv_number/errors.py +51 -0
- sv_number-0.2.0/src/sv_number/parse.py +53 -0
- sv_number-0.2.0/src/sv_number/types.py +28 -0
- sv_number-0.2.0/tests/test_client.py +104 -0
- sv_number-0.2.0/tests/test_live.py +20 -0
- sv_number-0.2.0/uv.lock +295 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Dependencies
|
|
2
|
+
node_modules/
|
|
3
|
+
.pnp.*
|
|
4
|
+
.yarn/
|
|
5
|
+
.pnpm-store/
|
|
6
|
+
|
|
7
|
+
# Build
|
|
8
|
+
dist/
|
|
9
|
+
build/
|
|
10
|
+
*.tsbuildinfo
|
|
11
|
+
*.egg-info/
|
|
12
|
+
.eggs/
|
|
13
|
+
wheels/
|
|
14
|
+
|
|
15
|
+
# Tests and coverage
|
|
16
|
+
coverage/
|
|
17
|
+
.nyc_output/
|
|
18
|
+
.pytest_cache/
|
|
19
|
+
.mypy_cache/
|
|
20
|
+
.ruff_cache/
|
|
21
|
+
htmlcov/
|
|
22
|
+
.coverage
|
|
23
|
+
.coverage.*
|
|
24
|
+
|
|
25
|
+
# Python
|
|
26
|
+
__pycache__/
|
|
27
|
+
*.py[cod]
|
|
28
|
+
*$py.class
|
|
29
|
+
.venv/
|
|
30
|
+
venv/
|
|
31
|
+
env/
|
|
32
|
+
|
|
33
|
+
# Secrets
|
|
34
|
+
.env
|
|
35
|
+
.env.*
|
|
36
|
+
!.env.example
|
|
37
|
+
AGENTS.md
|
|
38
|
+
|
|
39
|
+
# GitBook / HonKit
|
|
40
|
+
_book/
|
|
41
|
+
|
|
42
|
+
# OS and editors
|
|
43
|
+
.DS_Store
|
|
44
|
+
Thumbs.db
|
|
45
|
+
.idea/
|
|
46
|
+
*.swp
|
sv_number-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
ISC License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 api-kit contributors
|
|
4
|
+
|
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
7
|
+
copyright notice and this permission notice appear in all copies.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
10
|
+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
11
|
+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
12
|
+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
13
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
14
|
+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
15
|
+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
sv_number-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: sv-number
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Python client for the SV Number SMS verification API
|
|
5
|
+
Project-URL: Repository, https://github.com/TysikGG/api-kit
|
|
6
|
+
Project-URL: Documentation, https://sms-verification-number.com/en/api-sms-activate/
|
|
7
|
+
License-Expression: ISC
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Requires-Python: >=3.10
|
|
10
|
+
Requires-Dist: httpx>=0.27
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
|
|
13
|
+
# sv-number
|
|
14
|
+
|
|
15
|
+
[](https://pypi.org/project/sv-number/)
|
|
16
|
+
[](https://pypi.org/project/sv-number/)
|
|
17
|
+
[](https://opensource.org/licenses/ISC)
|
|
18
|
+
|
|
19
|
+
Modern, typed Python client for the [SV Number SMS Verification Service](https://sms-verification-number.com/en/api-sms-activate/). Rent temporary numbers to receive verification SMS across hundreds of platforms. Built on [HTTPX](https://www.python-httpx.org).
|
|
20
|
+
|
|
21
|
+
Official API documentation: <https://sms-verification-number.com/en/api-sms-activate/>
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Features
|
|
26
|
+
|
|
27
|
+
- 📱 **Virtual Number Rental** — Order temporary phone numbers across global countries and services.
|
|
28
|
+
- ⏳ **Automated Polling** — `wait_for_code()` polls the activation status until an OTP arrives or timeout expires.
|
|
29
|
+
- 🏷️ **Price Catalog & Services** — Fetch live rates and availability via `get_prices()` and `get_services_and_cost()`.
|
|
30
|
+
- 🐍 **Modern Python** — Type-annotated, Google-style docstrings, context manager support (`with SvNumber(...) as client:`).
|
|
31
|
+
- 🚨 **Structured Errors** — Clear `SvNumberError` exceptions with API status strings (`NO_NUMBERS`, `BAD_KEY`, `NO_BALANCE`).
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Installation
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
pip install sv-number
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Requires Python 3.10 or higher.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Quick Start (Safe Check)
|
|
46
|
+
|
|
47
|
+
The quick check only inspects your account balance and service catalogs. It does not order numbers or spend credits.
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
import os
|
|
51
|
+
from sv_number import SvNumber
|
|
52
|
+
|
|
53
|
+
api_key = os.environ["SV_NUMBER_API_KEY"]
|
|
54
|
+
|
|
55
|
+
with SvNumber(api_key) as client:
|
|
56
|
+
balance = client.get_balance()
|
|
57
|
+
services = client.get_services_and_cost(country=0)
|
|
58
|
+
print(f"Balance: ${balance}")
|
|
59
|
+
print(f"Available services in country 0: {len(services)}")
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Usage Guide
|
|
65
|
+
|
|
66
|
+
### 1. Renting a Number and Receiving an SMS
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
import os
|
|
70
|
+
from sv_number import SvNumber, SvNumberError
|
|
71
|
+
|
|
72
|
+
api_key = os.environ["SV_NUMBER_API_KEY"]
|
|
73
|
+
|
|
74
|
+
with SvNumber(api_key) as client:
|
|
75
|
+
# 1. Order a number for Telegram ('tg') in country 0
|
|
76
|
+
order = client.get_number("tg", country=0)
|
|
77
|
+
print(f"Rented: {order['phone_number']} (ID: {order['activation_id']})")
|
|
78
|
+
|
|
79
|
+
# 2. Inform the provider that the application has triggered the SMS
|
|
80
|
+
client.ready(order["activation_id"])
|
|
81
|
+
|
|
82
|
+
# 3. Poll for the incoming OTP code
|
|
83
|
+
try:
|
|
84
|
+
code = client.wait_for_code(order["activation_id"], timeout=120.0, interval=3.0)
|
|
85
|
+
print(f"Received SMS code: {code}")
|
|
86
|
+
|
|
87
|
+
# 4. Confirm completion
|
|
88
|
+
client.complete(order["activation_id"])
|
|
89
|
+
except SvNumberError as err:
|
|
90
|
+
if err.code == "TIMEOUT":
|
|
91
|
+
print("Code timed out, canceling order...")
|
|
92
|
+
client.cancel(order["activation_id"])
|
|
93
|
+
else:
|
|
94
|
+
raise
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### 2. Checking Prices
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
with SvNumber(os.environ["SV_NUMBER_API_KEY"]) as client:
|
|
101
|
+
prices = client.get_prices(country=0)
|
|
102
|
+
print("Prices for country 0:", prices)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Error Handling
|
|
108
|
+
|
|
109
|
+
When the API returns an error, the client raises an `SvNumberError`:
|
|
110
|
+
|
|
111
|
+
```python
|
|
112
|
+
from sv_number import SvNumber, SvNumberError
|
|
113
|
+
|
|
114
|
+
try:
|
|
115
|
+
with SvNumber("invalid_key") as client:
|
|
116
|
+
client.get_balance()
|
|
117
|
+
except SvNumberError as err:
|
|
118
|
+
print(f"SV Number API error: {err.code}")
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## License
|
|
124
|
+
|
|
125
|
+
[ISC](LICENSE) © api-kit contributors
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# sv-number
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/sv-number/)
|
|
4
|
+
[](https://pypi.org/project/sv-number/)
|
|
5
|
+
[](https://opensource.org/licenses/ISC)
|
|
6
|
+
|
|
7
|
+
Modern, typed Python client for the [SV Number SMS Verification Service](https://sms-verification-number.com/en/api-sms-activate/). Rent temporary numbers to receive verification SMS across hundreds of platforms. Built on [HTTPX](https://www.python-httpx.org).
|
|
8
|
+
|
|
9
|
+
Official API documentation: <https://sms-verification-number.com/en/api-sms-activate/>
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- 📱 **Virtual Number Rental** — Order temporary phone numbers across global countries and services.
|
|
16
|
+
- ⏳ **Automated Polling** — `wait_for_code()` polls the activation status until an OTP arrives or timeout expires.
|
|
17
|
+
- 🏷️ **Price Catalog & Services** — Fetch live rates and availability via `get_prices()` and `get_services_and_cost()`.
|
|
18
|
+
- 🐍 **Modern Python** — Type-annotated, Google-style docstrings, context manager support (`with SvNumber(...) as client:`).
|
|
19
|
+
- 🚨 **Structured Errors** — Clear `SvNumberError` exceptions with API status strings (`NO_NUMBERS`, `BAD_KEY`, `NO_BALANCE`).
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pip install sv-number
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Requires Python 3.10 or higher.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Quick Start (Safe Check)
|
|
34
|
+
|
|
35
|
+
The quick check only inspects your account balance and service catalogs. It does not order numbers or spend credits.
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
import os
|
|
39
|
+
from sv_number import SvNumber
|
|
40
|
+
|
|
41
|
+
api_key = os.environ["SV_NUMBER_API_KEY"]
|
|
42
|
+
|
|
43
|
+
with SvNumber(api_key) as client:
|
|
44
|
+
balance = client.get_balance()
|
|
45
|
+
services = client.get_services_and_cost(country=0)
|
|
46
|
+
print(f"Balance: ${balance}")
|
|
47
|
+
print(f"Available services in country 0: {len(services)}")
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Usage Guide
|
|
53
|
+
|
|
54
|
+
### 1. Renting a Number and Receiving an SMS
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
import os
|
|
58
|
+
from sv_number import SvNumber, SvNumberError
|
|
59
|
+
|
|
60
|
+
api_key = os.environ["SV_NUMBER_API_KEY"]
|
|
61
|
+
|
|
62
|
+
with SvNumber(api_key) as client:
|
|
63
|
+
# 1. Order a number for Telegram ('tg') in country 0
|
|
64
|
+
order = client.get_number("tg", country=0)
|
|
65
|
+
print(f"Rented: {order['phone_number']} (ID: {order['activation_id']})")
|
|
66
|
+
|
|
67
|
+
# 2. Inform the provider that the application has triggered the SMS
|
|
68
|
+
client.ready(order["activation_id"])
|
|
69
|
+
|
|
70
|
+
# 3. Poll for the incoming OTP code
|
|
71
|
+
try:
|
|
72
|
+
code = client.wait_for_code(order["activation_id"], timeout=120.0, interval=3.0)
|
|
73
|
+
print(f"Received SMS code: {code}")
|
|
74
|
+
|
|
75
|
+
# 4. Confirm completion
|
|
76
|
+
client.complete(order["activation_id"])
|
|
77
|
+
except SvNumberError as err:
|
|
78
|
+
if err.code == "TIMEOUT":
|
|
79
|
+
print("Code timed out, canceling order...")
|
|
80
|
+
client.cancel(order["activation_id"])
|
|
81
|
+
else:
|
|
82
|
+
raise
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### 2. Checking Prices
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
with SvNumber(os.environ["SV_NUMBER_API_KEY"]) as client:
|
|
89
|
+
prices = client.get_prices(country=0)
|
|
90
|
+
print("Prices for country 0:", prices)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Error Handling
|
|
96
|
+
|
|
97
|
+
When the API returns an error, the client raises an `SvNumberError`:
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
from sv_number import SvNumber, SvNumberError
|
|
101
|
+
|
|
102
|
+
try:
|
|
103
|
+
with SvNumber("invalid_key") as client:
|
|
104
|
+
client.get_balance()
|
|
105
|
+
except SvNumberError as err:
|
|
106
|
+
print(f"SV Number API error: {err.code}")
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## License
|
|
112
|
+
|
|
113
|
+
[ISC](LICENSE) © api-kit contributors
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Safe verification script: checks account balance without renting numbers."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
from sv_number import SvNumber
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def main() -> None:
|
|
9
|
+
api_key = os.environ.get("SV_NUMBER_API_KEY")
|
|
10
|
+
if not api_key:
|
|
11
|
+
raise SystemExit("Please set SV_NUMBER_API_KEY environment variable")
|
|
12
|
+
|
|
13
|
+
with SvNumber(api_key) as client:
|
|
14
|
+
balance = client.get_balance()
|
|
15
|
+
services = client.get_services_and_cost(country=0)
|
|
16
|
+
print(f"Account balance: ${balance}")
|
|
17
|
+
print(f"Available services in country 0: {len(services)}")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
if __name__ == "__main__":
|
|
21
|
+
main()
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Publish trigger
|
|
2
|
+
# SV Number API client
|
|
3
|
+
[build-system]
|
|
4
|
+
requires = ["hatchling"]
|
|
5
|
+
build-backend = "hatchling.build"
|
|
6
|
+
|
|
7
|
+
[project]
|
|
8
|
+
name = "sv-number"
|
|
9
|
+
version = "0.2.0"
|
|
10
|
+
description = "Python client for the SV Number SMS verification API"
|
|
11
|
+
readme = "README.md"
|
|
12
|
+
requires-python = ">=3.10"
|
|
13
|
+
license = "ISC"
|
|
14
|
+
dependencies = [
|
|
15
|
+
"httpx>=0.27",
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
[project.urls]
|
|
19
|
+
Repository = "https://github.com/TysikGG/api-kit"
|
|
20
|
+
Documentation = "https://sms-verification-number.com/en/api-sms-activate/"
|
|
21
|
+
|
|
22
|
+
[dependency-groups]
|
|
23
|
+
dev = [
|
|
24
|
+
"pytest>=8",
|
|
25
|
+
"pytest-httpx>=0.30",
|
|
26
|
+
"ruff>=0.8",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
[tool.hatch.build.targets.wheel]
|
|
30
|
+
packages = ["src/sv_number"]
|
|
31
|
+
|
|
32
|
+
[tool.pytest.ini_options]
|
|
33
|
+
markers = [
|
|
34
|
+
"live: calls the real SV Number API and needs SV_NUMBER_API_KEY",
|
|
35
|
+
]
|
|
36
|
+
testpaths = ["tests"]
|
|
37
|
+
|
|
38
|
+
[tool.ruff]
|
|
39
|
+
target-version = "py310"
|
|
40
|
+
line-length = 100
|
|
41
|
+
src = ["src", "tests", "examples"]
|
|
42
|
+
|
|
43
|
+
[tool.ruff.lint]
|
|
44
|
+
select = ["E", "F", "I", "UP"]
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""SV Number SMS verification API client."""
|
|
2
|
+
|
|
3
|
+
from .client import REF_KEY, SvNumber
|
|
4
|
+
from .errors import SvNumberError
|
|
5
|
+
from .types import ActivationStatus, OrderedNumber, ServiceCostItem
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
"ActivationStatus",
|
|
9
|
+
"OrderedNumber",
|
|
10
|
+
"REF_KEY",
|
|
11
|
+
"ServiceCostItem",
|
|
12
|
+
"SvNumber",
|
|
13
|
+
"SvNumberError",
|
|
14
|
+
]
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
"""Client for the SV Number SMS verification API."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import time
|
|
6
|
+
from collections.abc import Mapping
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
import httpx
|
|
10
|
+
|
|
11
|
+
from .errors import SvNumberError, assert_not_api_error
|
|
12
|
+
from .parse import parse_access_number, parse_balance, parse_status
|
|
13
|
+
from .types import ActivationStatus, OrderedNumber, ServiceCostItem
|
|
14
|
+
|
|
15
|
+
_DEFAULT_BASE_URL = "https://sms-verification-number.com"
|
|
16
|
+
_DEFAULT_TIMEOUT = 30.0
|
|
17
|
+
|
|
18
|
+
REF_KEY = "226"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class SvNumber:
|
|
22
|
+
"""Client for the SV Number SMS verification service.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
api_key: SV Number API key.
|
|
26
|
+
base_url: Custom API base URL (defaults to `https://sms-verification-number.com`).
|
|
27
|
+
timeout: Request timeout in seconds (defaults to 30.0).
|
|
28
|
+
lang: Language preference (e.g. `en`, `ru`).
|
|
29
|
+
|
|
30
|
+
Examples:
|
|
31
|
+
>>> from sv_number import SvNumber
|
|
32
|
+
>>> with SvNumber("your_api_key") as client:
|
|
33
|
+
... balance = client.get_balance()
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
def __init__(
|
|
37
|
+
self,
|
|
38
|
+
api_key: str,
|
|
39
|
+
*,
|
|
40
|
+
base_url: str = _DEFAULT_BASE_URL,
|
|
41
|
+
timeout: float = _DEFAULT_TIMEOUT,
|
|
42
|
+
lang: str = "en",
|
|
43
|
+
) -> None:
|
|
44
|
+
if not api_key or not api_key.strip():
|
|
45
|
+
raise SvNumberError("BAD_KEY", "API key is required")
|
|
46
|
+
|
|
47
|
+
self._api_key = api_key.strip()
|
|
48
|
+
self._lang = lang
|
|
49
|
+
self._http = httpx.Client(
|
|
50
|
+
base_url=base_url.rstrip("/"),
|
|
51
|
+
timeout=timeout,
|
|
52
|
+
headers={
|
|
53
|
+
"Accept": "application/json, text/plain",
|
|
54
|
+
},
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
def close(self) -> None:
|
|
58
|
+
"""Close the underlying HTTP client."""
|
|
59
|
+
self._http.close()
|
|
60
|
+
|
|
61
|
+
def __enter__(self) -> SvNumber:
|
|
62
|
+
return self
|
|
63
|
+
|
|
64
|
+
def __exit__(self, *exc: object) -> None:
|
|
65
|
+
self.close()
|
|
66
|
+
|
|
67
|
+
def call(self, action: str, params: Mapping[str, Any] | None = None) -> Any:
|
|
68
|
+
"""Execute a low-level call to /stubs/handler_api.
|
|
69
|
+
|
|
70
|
+
Automatically attaches ``api_key``, ``ref_key``, and ``lang``.
|
|
71
|
+
"""
|
|
72
|
+
query: dict[str, str] = {
|
|
73
|
+
"api_key": self._api_key,
|
|
74
|
+
"ref_key": REF_KEY,
|
|
75
|
+
"lang": self._lang,
|
|
76
|
+
"action": action,
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if params:
|
|
80
|
+
for key, val in params.items():
|
|
81
|
+
if val is not None and val != "":
|
|
82
|
+
query[key] = str(val)
|
|
83
|
+
|
|
84
|
+
try:
|
|
85
|
+
res = self._http.get("/stubs/handler_api", params=query)
|
|
86
|
+
except httpx.HTTPError as err:
|
|
87
|
+
raise SvNumberError("NETWORK", str(err)) from err
|
|
88
|
+
|
|
89
|
+
if res.is_error:
|
|
90
|
+
raise SvNumberError(f"HTTP_{res.status_code}", res.text)
|
|
91
|
+
|
|
92
|
+
# Attempt to parse json, otherwise return text
|
|
93
|
+
try:
|
|
94
|
+
data = res.json()
|
|
95
|
+
except ValueError:
|
|
96
|
+
data = res.text
|
|
97
|
+
|
|
98
|
+
assert_not_api_error(data)
|
|
99
|
+
return data
|
|
100
|
+
|
|
101
|
+
def get_balance(self) -> float:
|
|
102
|
+
"""Retrieve current balance in USD.
|
|
103
|
+
|
|
104
|
+
Returns:
|
|
105
|
+
Balance amount.
|
|
106
|
+
|
|
107
|
+
Examples:
|
|
108
|
+
>>> with SvNumber("key") as client:
|
|
109
|
+
... print(client.get_balance())
|
|
110
|
+
"""
|
|
111
|
+
data = self.call("getBalance")
|
|
112
|
+
return parse_balance(data)
|
|
113
|
+
|
|
114
|
+
def get_number(
|
|
115
|
+
self,
|
|
116
|
+
service: str,
|
|
117
|
+
*,
|
|
118
|
+
country: str | int = 0,
|
|
119
|
+
operator: str | None = None,
|
|
120
|
+
) -> OrderedNumber:
|
|
121
|
+
"""Rent a temporary phone number.
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
service: Service identifier (e.g. ``wa``, ``tg``).
|
|
125
|
+
country: Country code or ID (defaults to 0).
|
|
126
|
+
operator: Specific mobile operator name.
|
|
127
|
+
|
|
128
|
+
Returns:
|
|
129
|
+
Dictionary with ``activation_id`` and ``phone_number``.
|
|
130
|
+
|
|
131
|
+
Examples:
|
|
132
|
+
>>> with SvNumber("key") as client:
|
|
133
|
+
... order = client.get_number("wa", country=0)
|
|
134
|
+
... print(order["phone_number"])
|
|
135
|
+
"""
|
|
136
|
+
params: dict[str, Any] = {"service": service, "country": country}
|
|
137
|
+
if operator:
|
|
138
|
+
params["operator"] = operator
|
|
139
|
+
|
|
140
|
+
data = self.call("getNumber", params)
|
|
141
|
+
return parse_access_number(str(data))
|
|
142
|
+
|
|
143
|
+
def get_status(self, activation_id: str | int) -> ActivationStatus:
|
|
144
|
+
"""Check current status of an activation.
|
|
145
|
+
|
|
146
|
+
Args:
|
|
147
|
+
activation_id: Activation ID.
|
|
148
|
+
|
|
149
|
+
Returns:
|
|
150
|
+
Dictionary with ``status`` (and optional ``code``).
|
|
151
|
+
|
|
152
|
+
Examples:
|
|
153
|
+
>>> with SvNumber("key") as client:
|
|
154
|
+
... status = client.get_status(activation_id)
|
|
155
|
+
"""
|
|
156
|
+
data = self.call("getStatus", {"id": activation_id})
|
|
157
|
+
return parse_status(str(data))
|
|
158
|
+
|
|
159
|
+
def set_status(self, activation_id: str | int, status: int) -> str:
|
|
160
|
+
"""Update activation status.
|
|
161
|
+
|
|
162
|
+
Args:
|
|
163
|
+
activation_id: Activation ID.
|
|
164
|
+
status: Status integer (1 = ready, 6 = complete, 8 = cancel).
|
|
165
|
+
"""
|
|
166
|
+
data = self.call("setStatus", {"id": activation_id, "status": status})
|
|
167
|
+
return str(data)
|
|
168
|
+
|
|
169
|
+
def ready(self, activation_id: str | int) -> str:
|
|
170
|
+
"""Signal that the SMS has been requested (status=1)."""
|
|
171
|
+
return self.set_status(activation_id, 1)
|
|
172
|
+
|
|
173
|
+
def complete(self, activation_id: str | int) -> str:
|
|
174
|
+
"""Finish the activation successfully (status=6)."""
|
|
175
|
+
return self.set_status(activation_id, 6)
|
|
176
|
+
|
|
177
|
+
def cancel(self, activation_id: str | int) -> str:
|
|
178
|
+
"""Cancel the activation (status=8)."""
|
|
179
|
+
return self.set_status(activation_id, 8)
|
|
180
|
+
|
|
181
|
+
def wait_for_code(
|
|
182
|
+
self,
|
|
183
|
+
activation_id: str | int,
|
|
184
|
+
*,
|
|
185
|
+
timeout: float = 120.0,
|
|
186
|
+
interval: float = 3.0,
|
|
187
|
+
) -> str:
|
|
188
|
+
"""Poll get_status until an SMS code arrives or timeout expires.
|
|
189
|
+
|
|
190
|
+
Args:
|
|
191
|
+
activation_id: Activation ID.
|
|
192
|
+
timeout: Maximum wait time in seconds (defaults to 120.0).
|
|
193
|
+
interval: Delay between checks in seconds (defaults to 3.0).
|
|
194
|
+
|
|
195
|
+
Returns:
|
|
196
|
+
Extracted verification code string.
|
|
197
|
+
"""
|
|
198
|
+
start_time = time.monotonic()
|
|
199
|
+
|
|
200
|
+
while True:
|
|
201
|
+
res = self.get_status(activation_id)
|
|
202
|
+
if res.get("status") == "STATUS_OK" and res.get("code"):
|
|
203
|
+
return res["code"]
|
|
204
|
+
|
|
205
|
+
if res.get("status") == "STATUS_CANCEL":
|
|
206
|
+
raise SvNumberError("STATUS_CANCEL", "Activation cancelled")
|
|
207
|
+
|
|
208
|
+
if time.monotonic() - start_time >= timeout:
|
|
209
|
+
raise SvNumberError("TIMEOUT", "Timed out waiting for SMS code")
|
|
210
|
+
|
|
211
|
+
time.sleep(interval)
|
|
212
|
+
|
|
213
|
+
def get_prices(self, country: str | int | None = None) -> dict[str, Any]:
|
|
214
|
+
"""Fetch price matrix grouped by country and service."""
|
|
215
|
+
params = {"country": country} if country is not None else {}
|
|
216
|
+
data = self.call("getPrices", params)
|
|
217
|
+
return data if isinstance(data, dict) else {}
|
|
218
|
+
|
|
219
|
+
def get_services_and_cost(
|
|
220
|
+
self,
|
|
221
|
+
*,
|
|
222
|
+
country: str | int = 0,
|
|
223
|
+
operator: str | None = None,
|
|
224
|
+
service: str | None = None,
|
|
225
|
+
) -> list[ServiceCostItem]:
|
|
226
|
+
"""Get services with price and quantity for a country."""
|
|
227
|
+
params: dict[str, Any] = {"country": country}
|
|
228
|
+
if operator:
|
|
229
|
+
params["operator"] = operator
|
|
230
|
+
if service:
|
|
231
|
+
params["service"] = service
|
|
232
|
+
|
|
233
|
+
data = self.call("getServicesAndCost", params)
|
|
234
|
+
return data if isinstance(data, list) else []
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""Error types for the SV Number API client."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
KNOWN_ERROR_CODES = {
|
|
8
|
+
"BAD_KEY",
|
|
9
|
+
"BAD_ACTION",
|
|
10
|
+
"BAD_SERVICE",
|
|
11
|
+
"BAD_STATUS",
|
|
12
|
+
"NO_NUMBERS",
|
|
13
|
+
"NO_BALANCE",
|
|
14
|
+
"WRONG_ACTIVATION_ID",
|
|
15
|
+
"STATUS_CANCEL",
|
|
16
|
+
"ERROR_SQL",
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class SvNumberError(Exception):
|
|
21
|
+
"""Exception raised for SV Number API errors.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
code: Error code string (e.g. `BAD_KEY`, `NO_NUMBERS`).
|
|
25
|
+
raw: Raw response body, if available.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(self, code: str, raw: Any = None) -> None:
|
|
29
|
+
super().__init__(raw if isinstance(raw, str) and raw.strip() else code)
|
|
30
|
+
self.code = code
|
|
31
|
+
self.raw = raw
|
|
32
|
+
|
|
33
|
+
def __repr__(self) -> str:
|
|
34
|
+
return f"SvNumberError(code={self.code!r}, raw={self.raw!r})"
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def assert_not_api_error(data: Any) -> None:
|
|
38
|
+
"""Check text data for known error codes."""
|
|
39
|
+
if not isinstance(data, str):
|
|
40
|
+
return
|
|
41
|
+
|
|
42
|
+
text = data.strip()
|
|
43
|
+
if not text:
|
|
44
|
+
raise SvNumberError("EMPTY_RESPONSE", data)
|
|
45
|
+
|
|
46
|
+
code = text.split(":", 1)[0].strip() if ":" in text else text
|
|
47
|
+
if text.startswith("ACCESS_") or text.startswith("STATUS_"):
|
|
48
|
+
return
|
|
49
|
+
|
|
50
|
+
if text in KNOWN_ERROR_CODES or code in KNOWN_ERROR_CODES:
|
|
51
|
+
raise SvNumberError(text if text in KNOWN_ERROR_CODES else code, text)
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""Response parsers for SV Number."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from .errors import SvNumberError
|
|
8
|
+
from .types import ActivationStatus, OrderedNumber
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def parse_balance(raw: Any) -> float:
|
|
12
|
+
"""Parse balance from raw number or string."""
|
|
13
|
+
if isinstance(raw, (int, float)):
|
|
14
|
+
return float(raw)
|
|
15
|
+
|
|
16
|
+
if isinstance(raw, str):
|
|
17
|
+
text = raw.strip()
|
|
18
|
+
if text.startswith("ACCESS_BALANCE:"):
|
|
19
|
+
try:
|
|
20
|
+
return float(text.split(":", 1)[1])
|
|
21
|
+
except ValueError:
|
|
22
|
+
pass
|
|
23
|
+
try:
|
|
24
|
+
return float(text)
|
|
25
|
+
except ValueError:
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
raise SvNumberError("UNEXPECTED_RESPONSE", raw)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def parse_access_number(raw: str) -> OrderedNumber:
|
|
32
|
+
"""Parse ACCESS_NUMBER response."""
|
|
33
|
+
parts = str(raw).strip().split(":")
|
|
34
|
+
if len(parts) < 3 or parts[0] != "ACCESS_NUMBER":
|
|
35
|
+
raise SvNumberError("UNEXPECTED_RESPONSE", raw)
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
"activation_id": parts[1],
|
|
39
|
+
"phone_number": ":".join(parts[2:]),
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def parse_status(raw: str) -> ActivationStatus:
|
|
44
|
+
"""Parse STATUS_ response."""
|
|
45
|
+
parts = str(raw).strip().split(":", 1)
|
|
46
|
+
status = parts[0]
|
|
47
|
+
if not status.startswith("STATUS_"):
|
|
48
|
+
raise SvNumberError("UNEXPECTED_RESPONSE", raw)
|
|
49
|
+
|
|
50
|
+
res: ActivationStatus = {"status": status}
|
|
51
|
+
if len(parts) > 1:
|
|
52
|
+
res["code"] = parts[1]
|
|
53
|
+
return res
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""Type definitions for the SV Number API client."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TypedDict
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class OrderedNumber(TypedDict):
|
|
9
|
+
"""Details of an ordered virtual number."""
|
|
10
|
+
|
|
11
|
+
activation_id: str
|
|
12
|
+
phone_number: str
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class ActivationStatus(TypedDict, total=False):
|
|
16
|
+
"""Status of an activation."""
|
|
17
|
+
|
|
18
|
+
status: str
|
|
19
|
+
code: str
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ServiceCostItem(TypedDict):
|
|
23
|
+
"""Service pricing and availability item."""
|
|
24
|
+
|
|
25
|
+
id: str
|
|
26
|
+
name: str
|
|
27
|
+
price: float
|
|
28
|
+
quantity: int
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"""Unit tests for the SV Number Python client."""
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
from pytest_httpx import HTTPXMock
|
|
7
|
+
|
|
8
|
+
from sv_number import REF_KEY, SvNumber, SvNumberError
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def test_missing_api_key() -> None:
|
|
12
|
+
with pytest.raises(SvNumberError, match="API key is required"):
|
|
13
|
+
SvNumber("")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def test_get_balance_decimal(httpx_mock: HTTPXMock) -> None:
|
|
17
|
+
def callback(request: Any) -> Any:
|
|
18
|
+
assert request.url.params.get("ref_key") == REF_KEY
|
|
19
|
+
assert request.url.params.get("action") == "getBalance"
|
|
20
|
+
return httpx_mock.Response(status_code=200, text="18.25")
|
|
21
|
+
|
|
22
|
+
httpx_mock.add_response(
|
|
23
|
+
url="https://sms-verification-number.com/stubs/handler_api?api_key=test_key&ref_key=226&lang=en&action=getBalance",
|
|
24
|
+
method="GET",
|
|
25
|
+
text="18.25",
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
with SvNumber("test_key") as client:
|
|
29
|
+
balance = client.get_balance()
|
|
30
|
+
assert balance == 18.25
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def test_get_balance_access_prefix(httpx_mock: HTTPXMock) -> None:
|
|
34
|
+
httpx_mock.add_response(
|
|
35
|
+
url="https://sms-verification-number.com/stubs/handler_api?api_key=test_key&ref_key=226&lang=en&action=getBalance",
|
|
36
|
+
method="GET",
|
|
37
|
+
text="ACCESS_BALANCE:25.50",
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
with SvNumber("test_key") as client:
|
|
41
|
+
balance = client.get_balance()
|
|
42
|
+
assert balance == 25.50
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def test_get_number_embeds_ref_key(httpx_mock: HTTPXMock) -> None:
|
|
46
|
+
def callback(request: Any) -> Any:
|
|
47
|
+
assert request.url.params.get("ref_key") == REF_KEY
|
|
48
|
+
assert request.url.params.get("service") == "wa"
|
|
49
|
+
assert request.url.params.get("country") == "0"
|
|
50
|
+
return httpx_mock.Response(status_code=200, text="ACCESS_NUMBER:9988:1234567890")
|
|
51
|
+
|
|
52
|
+
httpx_mock.add_response(
|
|
53
|
+
url="https://sms-verification-number.com/stubs/handler_api?api_key=test_key&ref_key=226&lang=en&action=getNumber&service=wa&country=0",
|
|
54
|
+
method="GET",
|
|
55
|
+
text="ACCESS_NUMBER:9988:1234567890",
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
with SvNumber("test_key") as client:
|
|
59
|
+
order = client.get_number("wa", country=0)
|
|
60
|
+
assert order["activation_id"] == "9988"
|
|
61
|
+
assert order["phone_number"] == "1234567890"
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def test_get_status(httpx_mock: HTTPXMock) -> None:
|
|
65
|
+
httpx_mock.add_response(
|
|
66
|
+
url="https://sms-verification-number.com/stubs/handler_api?api_key=test_key&ref_key=226&lang=en&action=getStatus&id=9988",
|
|
67
|
+
method="GET",
|
|
68
|
+
text="STATUS_OK:445566",
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
with SvNumber("test_key") as client:
|
|
72
|
+
status = client.get_status("9988")
|
|
73
|
+
assert status["status"] == "STATUS_OK"
|
|
74
|
+
assert status["code"] == "445566"
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def test_wait_for_code(httpx_mock: HTTPXMock) -> None:
|
|
78
|
+
httpx_mock.add_response(
|
|
79
|
+
url="https://sms-verification-number.com/stubs/handler_api?api_key=test_key&ref_key=226&lang=en&action=getStatus&id=9988",
|
|
80
|
+
method="GET",
|
|
81
|
+
text="STATUS_WAIT_CODE",
|
|
82
|
+
)
|
|
83
|
+
httpx_mock.add_response(
|
|
84
|
+
url="https://sms-verification-number.com/stubs/handler_api?api_key=test_key&ref_key=226&lang=en&action=getStatus&id=9988",
|
|
85
|
+
method="GET",
|
|
86
|
+
text="STATUS_OK:778899",
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
with SvNumber("test_key") as client:
|
|
90
|
+
code = client.wait_for_code("9988", timeout=5.0, interval=0.01)
|
|
91
|
+
assert code == "778899"
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def test_api_error_raised(httpx_mock: HTTPXMock) -> None:
|
|
95
|
+
httpx_mock.add_response(
|
|
96
|
+
url="https://sms-verification-number.com/stubs/handler_api?api_key=test_key&ref_key=226&lang=en&action=getNumber&service=tg&country=0",
|
|
97
|
+
method="GET",
|
|
98
|
+
text="NO_NUMBERS",
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
with SvNumber("test_key") as client:
|
|
102
|
+
with pytest.raises(SvNumberError) as exc_info:
|
|
103
|
+
client.get_number("tg")
|
|
104
|
+
assert exc_info.value.code == "NO_NUMBERS"
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""Live API tests for SV Number."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
from sv_number import SvNumber
|
|
8
|
+
|
|
9
|
+
api_key = os.environ.get("SV_NUMBER_API_KEY")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@pytest.mark.live
|
|
13
|
+
@pytest.mark.skipif(
|
|
14
|
+
not api_key,
|
|
15
|
+
reason="SV_NUMBER_API_KEY environment variable not set",
|
|
16
|
+
)
|
|
17
|
+
def test_live_balance() -> None:
|
|
18
|
+
with SvNumber(api_key) as client:
|
|
19
|
+
balance = client.get_balance()
|
|
20
|
+
assert isinstance(balance, float)
|
sv_number-0.2.0/uv.lock
ADDED
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
version = 1
|
|
2
|
+
revision = 3
|
|
3
|
+
requires-python = ">=3.10"
|
|
4
|
+
resolution-markers = [
|
|
5
|
+
"python_full_version >= '3.11'",
|
|
6
|
+
"python_full_version < '3.11'",
|
|
7
|
+
]
|
|
8
|
+
|
|
9
|
+
[[package]]
|
|
10
|
+
name = "anyio"
|
|
11
|
+
version = "4.15.1"
|
|
12
|
+
source = { registry = "https://pypi.org/simple" }
|
|
13
|
+
dependencies = [
|
|
14
|
+
{ name = "exceptiongroup", marker = "python_full_version < '3.11'" },
|
|
15
|
+
{ name = "idna" },
|
|
16
|
+
{ name = "typing-extensions", marker = "python_full_version < '3.15'" },
|
|
17
|
+
]
|
|
18
|
+
sdist = { url = "https://files.pythonhosted.org/packages/a9/d2/f4d173e22df740bc37b1db102b386ba719b66e95b0f0d751f556b387e6d2/anyio-4.15.1.tar.gz", hash = "sha256:9f28306018cbd6d329e64a36d58256edff76dd996fe423bc957326e578b82a94", size = 276966, upload-time = "2026-09-05T10:42:39.44Z" }
|
|
19
|
+
wheels = [
|
|
20
|
+
{ url = "https://files.pythonhosted.org/packages/12/b8/4bd346e22b28902df4d651910f5242c28d84e4a5c2435ca5c3f797ed7e2e/anyio-4.15.1-py3-none-any.whl", hash = "sha256:6152fdbbf9a77fdec97731721bebf7c4c44f7c29b424b0065826173efc7ed101", size = 132079, upload-time = "2026-09-05T10:42:37.923Z" },
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
[[package]]
|
|
24
|
+
name = "certifi"
|
|
25
|
+
version = "2026.10.23"
|
|
26
|
+
source = { registry = "https://pypi.org/simple" }
|
|
27
|
+
sdist = { url = "https://files.pythonhosted.org/packages/fd/11/b524cbd9bbdaca58608e4cf4053fd463417549e1959fa8d3aa18319f9555/certifi-2026.10.23.tar.gz", hash = "sha256:a9895e6e2758b371e0545e321a3a8fd1fcfd9829ada8824a936dfb16aaaf36cd", size = 136225, upload-time = "2026-10-23T11:36:16.478Z" }
|
|
28
|
+
wheels = [
|
|
29
|
+
{ url = "https://files.pythonhosted.org/packages/32/d1/a3652fe2c19134d0d15922177821d863cbd7e842d53a21bbe7e8e3a1b5ac/certifi-2026.10.23-py3-none-any.whl", hash = "sha256:e9b54de76e530bb6cf0ccd036787103acb58fd42ba930ea8bf948ddbaa2f61d1", size = 135082, upload-time = "2026-10-23T11:36:14.763Z" },
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[[package]]
|
|
33
|
+
name = "colorama"
|
|
34
|
+
version = "0.4.6"
|
|
35
|
+
source = { registry = "https://pypi.org/simple" }
|
|
36
|
+
sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
|
|
37
|
+
wheels = [
|
|
38
|
+
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
[[package]]
|
|
42
|
+
name = "exceptiongroup"
|
|
43
|
+
version = "1.3.1"
|
|
44
|
+
source = { registry = "https://pypi.org/simple" }
|
|
45
|
+
dependencies = [
|
|
46
|
+
{ name = "typing-extensions" },
|
|
47
|
+
]
|
|
48
|
+
sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" }
|
|
49
|
+
wheels = [
|
|
50
|
+
{ url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" },
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
[[package]]
|
|
54
|
+
name = "h11"
|
|
55
|
+
version = "0.16.0"
|
|
56
|
+
source = { registry = "https://pypi.org/simple" }
|
|
57
|
+
sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" }
|
|
58
|
+
wheels = [
|
|
59
|
+
{ url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" },
|
|
60
|
+
]
|
|
61
|
+
|
|
62
|
+
[[package]]
|
|
63
|
+
name = "httpcore"
|
|
64
|
+
version = "1.0.9"
|
|
65
|
+
source = { registry = "https://pypi.org/simple" }
|
|
66
|
+
dependencies = [
|
|
67
|
+
{ name = "certifi" },
|
|
68
|
+
{ name = "h11" },
|
|
69
|
+
]
|
|
70
|
+
sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" }
|
|
71
|
+
wheels = [
|
|
72
|
+
{ url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" },
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
[[package]]
|
|
76
|
+
name = "httpx"
|
|
77
|
+
version = "0.28.1"
|
|
78
|
+
source = { registry = "https://pypi.org/simple" }
|
|
79
|
+
dependencies = [
|
|
80
|
+
{ name = "anyio" },
|
|
81
|
+
{ name = "certifi" },
|
|
82
|
+
{ name = "httpcore" },
|
|
83
|
+
{ name = "idna" },
|
|
84
|
+
]
|
|
85
|
+
sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" }
|
|
86
|
+
wheels = [
|
|
87
|
+
{ url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" },
|
|
88
|
+
]
|
|
89
|
+
|
|
90
|
+
[[package]]
|
|
91
|
+
name = "idna"
|
|
92
|
+
version = "3.20"
|
|
93
|
+
source = { registry = "https://pypi.org/simple" }
|
|
94
|
+
sdist = { url = "https://files.pythonhosted.org/packages/f5/08/8eea9d4b8302028f3abb2c0813953f7aec26d33b7a8960ed760e65ff29fa/idna-3.20.tar.gz", hash = "sha256:a7db850025b95ded1eae8a46181a1a6c56c92c96f0e2b005d9ff8dc0210cab44", size = 216463, upload-time = "2026-09-17T14:11:04.752Z" }
|
|
95
|
+
wheels = [
|
|
96
|
+
{ url = "https://files.pythonhosted.org/packages/58/a2/bb081bab032533a855d44de1d56f8e8426114ff1ba5d1f07a438a0a654f8/idna-3.20-py3-none-any.whl", hash = "sha256:ab7ae7122974553370f0bdb919e1a960b2cd1bc1ef0276416d896db81c14582c", size = 69583, upload-time = "2026-09-17T14:11:03.168Z" },
|
|
97
|
+
]
|
|
98
|
+
|
|
99
|
+
[[package]]
|
|
100
|
+
name = "iniconfig"
|
|
101
|
+
version = "2.3.1"
|
|
102
|
+
source = { registry = "https://pypi.org/simple" }
|
|
103
|
+
sdist = { url = "https://files.pythonhosted.org/packages/01/e1/2069291243c926a2ff1cd706c7f3eeb9b62144bf60f77c9fb9ff2fb26bd3/iniconfig-2.3.1.tar.gz", hash = "sha256:67f4b9c50da0dedf52af349e7749a80a9057a5031199791b906c3bb3ae878960", size = 21209, upload-time = "2026-10-06T22:48:38.076Z" }
|
|
104
|
+
wheels = [
|
|
105
|
+
{ url = "https://files.pythonhosted.org/packages/56/43/4ca9e49d27a1fcf6bece6f6aec0ea46bb9112489b93d4b688fb415457bdb/iniconfig-2.3.1-py3-none-any.whl", hash = "sha256:9121e2c1fdb355232495be3194c8dfe87ccc2d5dee45947b78e68f499790d7a7", size = 7552, upload-time = "2026-10-06T22:48:36.959Z" },
|
|
106
|
+
]
|
|
107
|
+
|
|
108
|
+
[[package]]
|
|
109
|
+
name = "packaging"
|
|
110
|
+
version = "26.3"
|
|
111
|
+
source = { registry = "https://pypi.org/simple" }
|
|
112
|
+
sdist = { url = "https://files.pythonhosted.org/packages/7d/fa/3944b40b07da9ce895c0e6303a5ab7d53da063554f534556b134a54d6093/packaging-26.3.tar.gz", hash = "sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79", size = 313412, upload-time = "2026-08-04T18:15:28.737Z" }
|
|
113
|
+
wheels = [
|
|
114
|
+
{ url = "https://files.pythonhosted.org/packages/63/34/ba1c580383c9eada3711951fef0795c80b829a078d72188184bcab9dd527/packaging-26.3-py3-none-any.whl", hash = "sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c", size = 129956, upload-time = "2026-08-04T18:15:27.159Z" },
|
|
115
|
+
]
|
|
116
|
+
|
|
117
|
+
[[package]]
|
|
118
|
+
name = "pluggy"
|
|
119
|
+
version = "1.7.0"
|
|
120
|
+
source = { registry = "https://pypi.org/simple" }
|
|
121
|
+
sdist = { url = "https://files.pythonhosted.org/packages/bf/db/7fc19e6f2dc92a966727031389fc2e08b558f0f25eb7403c1119ad4713cd/pluggy-1.7.0.tar.gz", hash = "sha256:d1eaa46ebb595891b860ab086b4d09c8588af65ebd4361b8e8f4bb8920b90ba8", size = 123304, upload-time = "2026-10-15T09:50:58.343Z" }
|
|
122
|
+
wheels = [
|
|
123
|
+
{ url = "https://files.pythonhosted.org/packages/40/9e/2b38731e0fc536806f16490e1a12d7f0dc2a1235aa8cc07bcc75416a7daa/pluggy-1.7.0-py3-none-any.whl", hash = "sha256:7dd7b0d8832ba3cb632c306926ded123429211b83641b35dc5c41ad2d34f9bec", size = 27082, upload-time = "2026-10-15T09:50:56.808Z" },
|
|
124
|
+
]
|
|
125
|
+
|
|
126
|
+
[[package]]
|
|
127
|
+
name = "pygments"
|
|
128
|
+
version = "2.21.0"
|
|
129
|
+
source = { registry = "https://pypi.org/simple" }
|
|
130
|
+
sdist = { url = "https://files.pythonhosted.org/packages/49/2e/ced460408999b33da6b31b0021b0f37d329e202d4169aeb164493778f25b/pygments-2.21.0.tar.gz", hash = "sha256:610ca751c9bc2492b38eb9a38a7fbc93edbbb2d7182edaf34e66ae493dee5c8c", size = 5005329, upload-time = "2026-08-17T08:02:48.824Z" }
|
|
131
|
+
wheels = [
|
|
132
|
+
{ url = "https://files.pythonhosted.org/packages/71/46/17f022dd3e953bf20a04a028a21ec746d942f8d2af30fa0f124fa0e6a684/pygments-2.21.0-py3-none-any.whl", hash = "sha256:2363c69b61c4a97c838da3b130dcd6468f4848992b21a82f2a63ec34377137d9", size = 1250147, upload-time = "2026-08-17T08:02:44.912Z" },
|
|
133
|
+
]
|
|
134
|
+
|
|
135
|
+
[[package]]
|
|
136
|
+
name = "pytest"
|
|
137
|
+
version = "9.1.1"
|
|
138
|
+
source = { registry = "https://pypi.org/simple" }
|
|
139
|
+
dependencies = [
|
|
140
|
+
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
|
141
|
+
{ name = "exceptiongroup", marker = "python_full_version < '3.11'" },
|
|
142
|
+
{ name = "iniconfig" },
|
|
143
|
+
{ name = "packaging" },
|
|
144
|
+
{ name = "pluggy" },
|
|
145
|
+
{ name = "pygments" },
|
|
146
|
+
{ name = "tomli", marker = "python_full_version < '3.11'" },
|
|
147
|
+
]
|
|
148
|
+
sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" }
|
|
149
|
+
wheels = [
|
|
150
|
+
{ url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" },
|
|
151
|
+
]
|
|
152
|
+
|
|
153
|
+
[[package]]
|
|
154
|
+
name = "pytest-httpx"
|
|
155
|
+
version = "0.36.2"
|
|
156
|
+
source = { registry = "https://pypi.org/simple" }
|
|
157
|
+
dependencies = [
|
|
158
|
+
{ name = "httpx" },
|
|
159
|
+
{ name = "pytest" },
|
|
160
|
+
]
|
|
161
|
+
sdist = { url = "https://files.pythonhosted.org/packages/4e/42/f53c58570e80d503ade9dd42ce57f2915d14bcbe25f6308138143950d1d6/pytest_httpx-0.36.2.tar.gz", hash = "sha256:05a56527484f7f4e8c856419ea379b8dc359c36801c4992fdb330f294c690356", size = 57683, upload-time = "2026-04-09T13:57:19.837Z" }
|
|
162
|
+
wheels = [
|
|
163
|
+
{ url = "https://files.pythonhosted.org/packages/1e/55/1fa65f8e4fceb19dd6daa867c162ad845d547f6058cd92b4b02384a44777/pytest_httpx-0.36.2-py3-none-any.whl", hash = "sha256:d42ebd5679442dc7bfb0c48e0767b6562e9bc4534d805127b0084171886a5e22", size = 20315, upload-time = "2026-04-09T13:57:18.587Z" },
|
|
164
|
+
]
|
|
165
|
+
|
|
166
|
+
[[package]]
|
|
167
|
+
name = "ruff"
|
|
168
|
+
version = "0.17.2"
|
|
169
|
+
source = { registry = "https://pypi.org/simple" }
|
|
170
|
+
sdist = { url = "https://files.pythonhosted.org/packages/ae/58/690cf56da80c8f2c8bf12042b6017beac2c34fe961f65420bcb3fb7fac38/ruff-0.17.2.tar.gz", hash = "sha256:84d632402d14c23b488f941db23712d6736a013225162062d34558c3f3c780eb", size = 5333400, upload-time = "2026-10-22T18:38:00.181Z" }
|
|
171
|
+
wheels = [
|
|
172
|
+
{ url = "https://files.pythonhosted.org/packages/98/b8/8b6d69c57e8fe1cc6af1aa7493b72a1a5b5a8afe34694e302025441729d4/ruff-0.17.2-py3-none-linux_armv6l.whl", hash = "sha256:96a65e755d8dba094707fb23ab602111d9a31ec2835b3a6992a1914a8fcb211e", size = 10183857, upload-time = "2026-10-22T18:37:14.956Z" },
|
|
173
|
+
{ url = "https://files.pythonhosted.org/packages/e8/61/12cc2ff7b2fa90a268ce1e2162c23aaf76e601d22623f6a31b0eeaa764b0/ruff-0.17.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:39c5b55c960515cdb32be16e69efb5734c589c06a0eb38a22694524a336b889d", size = 10210904, upload-time = "2026-10-22T18:37:17.985Z" },
|
|
174
|
+
{ url = "https://files.pythonhosted.org/packages/e8/7c/b8850a8e4ad29f64a827dd6c6902db4a9aa538fb2b9eef4e26084001a3bb/ruff-0.17.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:92a80d2f44584dabb0189b3a6c393e37e525e04942838482010575cb81945be7", size = 9408439, upload-time = "2026-10-22T18:37:20.964Z" },
|
|
175
|
+
{ url = "https://files.pythonhosted.org/packages/b7/b6/6a64fae86ca5e5e29d5adc311e5481de726cedf9aee607435a16c31c442a/ruff-0.17.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7d0906677d89bbf3cf73cde64b5bbe2ab35df3ae43e49ee2627301e91265bac", size = 10047078, upload-time = "2026-10-22T18:37:23.717Z" },
|
|
176
|
+
{ url = "https://files.pythonhosted.org/packages/10/19/23d376547715175aa1bd46df48df6aacc7c6439d9daf19cac15975180aa5/ruff-0.17.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7cfd783590edf2b77317882631900f6a13ea2e8eacefe6ebf2370d2715299160", size = 9990478, upload-time = "2026-10-22T18:37:26.584Z" },
|
|
177
|
+
{ url = "https://files.pythonhosted.org/packages/93/6c/34cda32cbe13adac5c6b291a307a5570d8ebd37c0c86339f0fe628e55632/ruff-0.17.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122258f6ecde0e0dd1bb60b24263c3edde4338caf723fca711cc729f9bfd414a", size = 10673624, upload-time = "2026-10-22T18:37:29.767Z" },
|
|
178
|
+
{ url = "https://files.pythonhosted.org/packages/bf/10/5d762a4dbc851d8bb47863cf3a28a61bf31c804d393b70d891fac899f5d1/ruff-0.17.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7f8fba429d6ac4128ab29cfb8fa6240d2fa671d04adf7f84d3b22fc7b6b6bea4", size = 11351797, upload-time = "2026-10-22T18:37:32.535Z" },
|
|
179
|
+
{ url = "https://files.pythonhosted.org/packages/3f/04/a0e92a81faf5c81c1c98d4374c8401734ccf2b8cca7d0170cb0fec08c6e2/ruff-0.17.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:583bd67bb9e7061dd09bc46a0a884bae2bbd214dbcd48e509813612619683869", size = 10949414, upload-time = "2026-10-22T18:37:35.501Z" },
|
|
180
|
+
{ url = "https://files.pythonhosted.org/packages/c3/d8/59894cf630d2d86882457a2a6a0a1533410c5c805bfbac6f6eb4b5aef69d/ruff-0.17.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c60f93fec7142dba5b8f487f94bf2f6231dae24dc11e4c48648347c8b0720004", size = 10528000, upload-time = "2026-10-22T18:37:37.88Z" },
|
|
181
|
+
{ url = "https://files.pythonhosted.org/packages/ab/95/d6e30c51e851d37e10762ad91fa1e76ddaad998589b5667962a3cfbc9edd/ruff-0.17.2-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:c555a877f8f41447e318101cfefea9bf12dfa9f82eedf90c376e57e069f917d0", size = 10571779, upload-time = "2026-10-22T18:37:40.444Z" },
|
|
182
|
+
{ url = "https://files.pythonhosted.org/packages/f4/5a/a7e1d74fb464250137d3d4eca645d323536533b672004d04ee0e46e0caf3/ruff-0.17.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:ba405cbd5ec7bda1f555d5e52be1fd68d02608d4d95d24591bdac92cfacb579f", size = 10051707, upload-time = "2026-10-22T18:37:42.812Z" },
|
|
183
|
+
{ url = "https://files.pythonhosted.org/packages/6e/f2/02fca29ca7999380f0350a7212fe755c11ab9c22d61327356cce8decdbc6/ruff-0.17.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8c21b4ab24485358f17291a4f8dc5399b834e963b8efedd920fe4fdb02081bb4", size = 9998227, upload-time = "2026-10-22T18:37:45.224Z" },
|
|
184
|
+
{ url = "https://files.pythonhosted.org/packages/d1/00/55aa604a093dfdc1526e570fae0bb7d37a2221c7b4728d5f080b2add16ba/ruff-0.17.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:5875a16b0de70b43cb81eabea5ae5e8f5d1b2fd1b5e6ed07f80cfe5019d0bd5a", size = 10377692, upload-time = "2026-10-22T18:37:47.704Z" },
|
|
185
|
+
{ url = "https://files.pythonhosted.org/packages/e4/5a/a7a640f47bb906ec8fa233ea84319d503e6dee02b59e3901bd312ebd1f9b/ruff-0.17.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:2d086be452eed686aa51271ecf2cbe5037956517cc6ee39a17b4489ac12f8bbe", size = 10790587, upload-time = "2026-10-22T18:37:50.191Z" },
|
|
186
|
+
{ url = "https://files.pythonhosted.org/packages/2c/d4/c3b74e1b4808438ea7f14bb914478025e2d51261f60774a54a0fa222ec46/ruff-0.17.2-py3-none-win32.whl", hash = "sha256:6bce7d1f5165701ae18f5df85c65afe78cddfa6c5fb4b9bdb0014d60388f3edd", size = 9870537, upload-time = "2026-10-22T18:37:52.486Z" },
|
|
187
|
+
{ url = "https://files.pythonhosted.org/packages/1c/9a/c7da96c2c96d20704cf9027f7a5121da272a8c05f1d1531ba949e3b3df04/ruff-0.17.2-py3-none-win_amd64.whl", hash = "sha256:1b59d447f197bef9ef48a22ba1a6016137753c6099e9bac9c36eb566e422424c", size = 10282826, upload-time = "2026-10-22T18:37:55.2Z" },
|
|
188
|
+
{ url = "https://files.pythonhosted.org/packages/81/60/a3604c79cb02777b6cb84da894104021986f06c4bc41375102cc95049a32/ruff-0.17.2-py3-none-win_arm64.whl", hash = "sha256:195ad918027f817c119310ca89a42d347887dfc28934aaa869325e9c5dc9d962", size = 9827036, upload-time = "2026-10-22T18:37:58.031Z" },
|
|
189
|
+
]
|
|
190
|
+
|
|
191
|
+
[[package]]
|
|
192
|
+
name = "sv-number"
|
|
193
|
+
version = "0.2.0"
|
|
194
|
+
source = { editable = "." }
|
|
195
|
+
dependencies = [
|
|
196
|
+
{ name = "httpx" },
|
|
197
|
+
]
|
|
198
|
+
|
|
199
|
+
[package.dev-dependencies]
|
|
200
|
+
dev = [
|
|
201
|
+
{ name = "pytest" },
|
|
202
|
+
{ name = "pytest-httpx" },
|
|
203
|
+
{ name = "ruff" },
|
|
204
|
+
]
|
|
205
|
+
|
|
206
|
+
[package.metadata]
|
|
207
|
+
requires-dist = [{ name = "httpx", specifier = ">=0.27" }]
|
|
208
|
+
|
|
209
|
+
[package.metadata.requires-dev]
|
|
210
|
+
dev = [
|
|
211
|
+
{ name = "pytest", specifier = ">=8" },
|
|
212
|
+
{ name = "pytest-httpx", specifier = ">=0.30" },
|
|
213
|
+
{ name = "ruff", specifier = ">=0.8" },
|
|
214
|
+
]
|
|
215
|
+
|
|
216
|
+
[[package]]
|
|
217
|
+
name = "tomli"
|
|
218
|
+
version = "2.5.0"
|
|
219
|
+
source = { registry = "https://pypi.org/simple" }
|
|
220
|
+
sdist = { url = "https://files.pythonhosted.org/packages/b0/78/9ad63712633ed3ab5cc1a648d863d7e7da371e9425e209555a0fe711b695/tomli-2.5.0.tar.gz", hash = "sha256:264507556cd8b8c8e7c6ee037cdf443a463f03f4c958e57195e3d369711b8ff6", size = 17662, upload-time = "2026-10-07T12:23:37.892Z" }
|
|
221
|
+
wheels = [
|
|
222
|
+
{ url = "https://files.pythonhosted.org/packages/22/a6/ab99b60ee52acd949684febabc3005d0045d0f66bebd9cdebd67372d26dd/tomli-2.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c4dc1c1781f2f716de763d1e9a7b34c6a894e167e291c7c5d16c72f7a9538545", size = 163901, upload-time = "2026-10-07T12:22:15.601Z" },
|
|
223
|
+
{ url = "https://files.pythonhosted.org/packages/bc/00/ee01b7ed4579180fff07142d290257f25ba786f23f3ec6005f620933c2f5/tomli-2.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:eff8babca5a7999bc137acbc7482a8b7e17ffca5075ab41f5d770ab408c7bfef", size = 163756, upload-time = "2026-10-07T12:22:16.957Z" },
|
|
224
|
+
{ url = "https://files.pythonhosted.org/packages/72/c2/4efebf65372f6583185f79799312109dddb61102d47e5c33dcfd1a297aca/tomli-2.5.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:86665cee9c4835b7a7f1e8ec2c719b5258d4dc782887aded5a8ae7352a96843b", size = 268038, upload-time = "2026-10-07T12:22:18.135Z" },
|
|
225
|
+
{ url = "https://files.pythonhosted.org/packages/53/07/5850468e925d898abb36038666f9c333a94d2a223e802a8ba5b6d319d23f/tomli-2.5.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d7e369fd63331746182360977b1892bfc215476a30d61612d732425311639f56", size = 276422, upload-time = "2026-10-07T12:22:19.567Z" },
|
|
226
|
+
{ url = "https://files.pythonhosted.org/packages/b4/87/f293984cdcf83c054196d4fd3dad44fc68ae55b4b8c44bc76cef360c3150/tomli-2.5.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7ad1ea345759240d6463efa0ed1c704402752e49aa21476620738d74d72d8aa1", size = 272616, upload-time = "2026-10-07T12:22:20.794Z" },
|
|
227
|
+
{ url = "https://files.pythonhosted.org/packages/ce/ce/db582886b3c1219d3fec93ebd669332482e5aee7a91e0f7838d84f2d1759/tomli-2.5.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:96243987194634bd411066ce40c952e108f86af04db533ecd8ac3ff2a85b1885", size = 276593, upload-time = "2026-10-07T12:22:22.12Z" },
|
|
228
|
+
{ url = "https://files.pythonhosted.org/packages/bf/72/7619b87dea4261fc27dd7b54c4461c129c1f7d9bb7ba3aec89c797a431b8/tomli-2.5.0-cp311-cp311-win32.whl", hash = "sha256:610b27d99f28ec5f191c7064a48f3ddb179a1fe6ca73d571483ae859f57b605e", size = 101830, upload-time = "2026-10-07T12:22:23.651Z" },
|
|
229
|
+
{ url = "https://files.pythonhosted.org/packages/1e/74/220106da34502304b6751a2a9b8a9fbca6c3fd47e737a2e2e3da7c61c9db/tomli-2.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:c804ae44fe7b4bab5da295e4f980a1ff04670bca9d23fe0a4e887e08ebd741a8", size = 112742, upload-time = "2026-10-07T12:22:24.972Z" },
|
|
230
|
+
{ url = "https://files.pythonhosted.org/packages/27/99/7d9c8b41837a7773613e169504147375c157a290167aa59ad74a085f521f/tomli-2.5.0-cp311-cp311-win_arm64.whl", hash = "sha256:cfac177ebd6236003846ea339981f71457cb6eb748f23381eb257e45092e3980", size = 109332, upload-time = "2026-10-07T12:22:26.117Z" },
|
|
231
|
+
{ url = "https://files.pythonhosted.org/packages/52/ed/7baa86f87493646a594de388c7c1c40a39dd0461f7e9c0359cbeefc91fe8/tomli-2.5.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:1f4a40d03fb9f63424f0979855bdeaf44dd7696b8d59501822c10ed30ba532df", size = 164854, upload-time = "2026-10-07T12:22:27.444Z" },
|
|
232
|
+
{ url = "https://files.pythonhosted.org/packages/a5/b1/44c0341f2224397855723c7a8a39f718ea6fcbcc3dacc66e5aeca0f334e3/tomli-2.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9ebf8d19b17bd0daeb7b7dec81a946a439b753942fd0210d6e96c532249eea6b", size = 164074, upload-time = "2026-10-07T12:22:28.679Z" },
|
|
233
|
+
{ url = "https://files.pythonhosted.org/packages/23/04/e2d5b7d3fba47adedb23de616c16d428ea076c79a3d8e1d95d649ffe197e/tomli-2.5.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bf0b5e8e0f68ebb494356e577c06c139161efd8d3b9050f93b39b7c26cc54ff0", size = 274274, upload-time = "2026-10-07T12:22:29.804Z" },
|
|
234
|
+
{ url = "https://files.pythonhosted.org/packages/43/90/6090e706ff27a6f89f4a40578e3324b95c3cd8c4150868aabf33a8f414c3/tomli-2.5.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6cf74416bdc94ae458b14e37286c1073081850ac8459a00d0c5efef5d44294c6", size = 286435, upload-time = "2026-10-07T12:22:31.297Z" },
|
|
235
|
+
{ url = "https://files.pythonhosted.org/packages/0a/9e/a2c40768df16c408f22430afb0a73e9d7e5f79c950884954649d1146b74d/tomli-2.5.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:61ea1ebe1e55a34ea8199cc8dbff398d35027b82271c8ac4802fd3a1fd5b1bcc", size = 278119, upload-time = "2026-10-07T12:22:32.601Z" },
|
|
236
|
+
{ url = "https://files.pythonhosted.org/packages/12/25/3c0cb485b98e9cfac495629b1c93c87ccf0b72fbe9d2689fd8fe62c6d5a3/tomli-2.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ed53f7e89bb04f6d9e8e7799112360b0c4d5cbff067de0814c98c37c39b920f7", size = 286177, upload-time = "2026-10-07T12:22:33.745Z" },
|
|
237
|
+
{ url = "https://files.pythonhosted.org/packages/77/8b/0144c65f0e37e51c18d04ae15c21b19431c165002d0131fe9aa8b0b8b1e8/tomli-2.5.0-cp312-cp312-win32.whl", hash = "sha256:e7ad033e27a516a233bea839cdb77b80146facb3b4f40bf02cd0cac165cdd5c2", size = 102760, upload-time = "2026-10-07T12:22:34.887Z" },
|
|
238
|
+
{ url = "https://files.pythonhosted.org/packages/de/32/5d6d8f42fc9a05fce69354e00ff256484192f5f2fc9a2165718fa0de61ec/tomli-2.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:bd05de8c1698f8413dd7d869492693a0bf2211543b787ac78cd5e7536af1a6d7", size = 112722, upload-time = "2026-10-07T12:22:36.162Z" },
|
|
239
|
+
{ url = "https://files.pythonhosted.org/packages/30/65/df18032218db0fb9b769fb23c8039a051f15c811993995ea04c350273a32/tomli-2.5.0-cp312-cp312-win_arm64.whl", hash = "sha256:069435bd5480429b98c5e5afb02ab21c219b6f0064680671c6dc0d46817346ea", size = 109534, upload-time = "2026-10-07T12:22:37.296Z" },
|
|
240
|
+
{ url = "https://files.pythonhosted.org/packages/42/e5/51736d70da209350969e15aca5c5ab6e2ce1ea87a0a892a6c13aec172a86/tomli-2.5.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:943276cf269e0071948d9ff697159c1735e623c1151d88abb09b74659ef0cbea", size = 163328, upload-time = "2026-10-07T12:22:38.373Z" },
|
|
241
|
+
{ url = "https://files.pythonhosted.org/packages/ec/55/086f80dab4ab497602644274e6dea7ec5dd0b4e262e443a8ad3bb7edee2d/tomli-2.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:463b16086865b97facd8d0b3fb4cb7c544e3f58d2a69dc3113d6db9653fdb043", size = 162246, upload-time = "2026-10-07T12:22:39.673Z" },
|
|
242
|
+
{ url = "https://files.pythonhosted.org/packages/aa/eb/3ecc94459f3635c92321f4e7bde571323fdb2267c50e19e3188a281eae3b/tomli-2.5.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1245a6638fc4bb0a60af38a7d45413db34a13842027c77597c712c998c62fdf0", size = 272655, upload-time = "2026-10-07T12:22:41.08Z" },
|
|
243
|
+
{ url = "https://files.pythonhosted.org/packages/c0/d7/494fd1f0c37a621f1ad9975c2efadb523e8101f144ed6edb2e7fe64738f2/tomli-2.5.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5d8bac3d603c97e6854424e5b2b5b741bdbde387e09f162fb0446812b4a8362b", size = 283595, upload-time = "2026-10-07T12:22:42.222Z" },
|
|
244
|
+
{ url = "https://files.pythonhosted.org/packages/70/51/bb8d62b1317e6640866f6949b2d5855e5300f2c99d46de1cd245570bba65/tomli-2.5.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:21e4cae4114aba25aa0d4f85cdf486d290fb35c0954d7bba536248da64d43066", size = 276253, upload-time = "2026-10-07T12:22:43.625Z" },
|
|
245
|
+
{ url = "https://files.pythonhosted.org/packages/66/f4/f46bd7f0763cd47de2db697dca9257c6a4adfd1a93b018cc75c8190ed5a8/tomli-2.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bbaefc84548d754be821bba7c4141c4787dda182f9e77f2f87b71213529efa7b", size = 283582, upload-time = "2026-10-07T12:22:44.983Z" },
|
|
246
|
+
{ url = "https://files.pythonhosted.org/packages/ac/03/70f2bcb2923a6db37818d917e124270a7f4cfd38ea576f5aa753a91c0ef5/tomli-2.5.0-cp313-cp313-win32.whl", hash = "sha256:abdbf6313b8d9efe157edeb7ab6eae4de064b1300ad31abf73755154b30abe68", size = 102628, upload-time = "2026-10-07T12:22:46.508Z" },
|
|
247
|
+
{ url = "https://files.pythonhosted.org/packages/dc/98/d52024bb5b0ff68b4f0d276d867f634c84a67319a7e9f6b7708a37742333/tomli-2.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:fd4dc129784e0c5335bd4e61dfcc4487499a013419e655cf2da1d091b7e0efdc", size = 113301, upload-time = "2026-10-07T12:22:47.647Z" },
|
|
248
|
+
{ url = "https://files.pythonhosted.org/packages/6f/f2/540db3a70572a8c23a28aba3e9c358ce0ffffbafc990905c1343aa265b31/tomli-2.5.0-cp313-cp313-win_arm64.whl", hash = "sha256:69491c143d2fe063046e0301e62a810bed338fa4d1ce0fd870c27dc1e09b0d84", size = 109744, upload-time = "2026-10-07T12:22:48.925Z" },
|
|
249
|
+
{ url = "https://files.pythonhosted.org/packages/e4/49/caf6b307766eb9567664a8707e9d6be5fcc0e8903f18781c6677a60d80c7/tomli-2.5.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:d3182ee2d887e507bd67319a0a61105d1dd33facc111329559a233b772c1a105", size = 162899, upload-time = "2026-10-07T12:22:50.088Z" },
|
|
250
|
+
{ url = "https://files.pythonhosted.org/packages/d3/c8/68cfce773a2733a49c74f99d627fb461bd990756860099eac25617889585/tomli-2.5.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:521345fd1f19d45b8df87657aaa38b6f2ca3800059fadf428e7ebf479a383646", size = 162080, upload-time = "2026-10-07T12:22:51.558Z" },
|
|
251
|
+
{ url = "https://files.pythonhosted.org/packages/7e/b2/e5bb8651fdad593f670501a7d718b1a7f73f064d44dea15e04c04dfef45d/tomli-2.5.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6e95c7614e705bfe2b04b27aa124adec59752d15813df37e2156747cab3a006b", size = 273380, upload-time = "2026-10-07T12:22:52.918Z" },
|
|
252
|
+
{ url = "https://files.pythonhosted.org/packages/8d/d2/9e2d7f8b1dfe0e2b34c245986ebd55c4c553ea4ce6c47c443b332673253f/tomli-2.5.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7ac2027d37c3afbdf4bdd377f2676f6f1d2122a5be1f1137b49dced590b37e75", size = 283228, upload-time = "2026-10-07T12:22:54.173Z" },
|
|
253
|
+
{ url = "https://files.pythonhosted.org/packages/ba/df/ec7b876b7b1a2718bd74a3743c076fff565b04029ba33e8f61fac262739f/tomli-2.5.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c414be4ed9d3cac80c42e348fa5a956117d1a48227f48026e31f59cb4a7671eb", size = 277189, upload-time = "2026-10-07T12:22:55.342Z" },
|
|
254
|
+
{ url = "https://files.pythonhosted.org/packages/7d/7b/e192d9eed0b9cb80da799f4d77052297fb9a2c3cc9b19f571f56ea88add6/tomli-2.5.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:9b03d7dc168353b4132965bde20feceabaa470e570c6f59660dfae59b1f9eeb3", size = 283632, upload-time = "2026-10-07T12:22:56.735Z" },
|
|
255
|
+
{ url = "https://files.pythonhosted.org/packages/84/50/ff94454e75461d75623e47401ed323d65c10aab8fe9033242c20cd2fdf32/tomli-2.5.0-cp314-cp314-win32.whl", hash = "sha256:6f041843c4d3a37245c0c056fd955b186bf8b1fb85690cbe40b81230891dc34b", size = 103535, upload-time = "2026-10-07T12:22:58.084Z" },
|
|
256
|
+
{ url = "https://files.pythonhosted.org/packages/54/0b/bdacf05f963bd6026ebf6eeb0beda847d1d60e03e440725c64a4e08a0afd/tomli-2.5.0-cp314-cp314-win_amd64.whl", hash = "sha256:f4b653094e18f9031102d3a1da5c729c8f222d85225b18037dac621695e46e1a", size = 114621, upload-time = "2026-10-07T12:22:59.2Z" },
|
|
257
|
+
{ url = "https://files.pythonhosted.org/packages/61/99/53f438fa6ae4f9d4ed0ddde3e7242b3bdc34b48c8f9948b72b9e9b127676/tomli-2.5.0-cp314-cp314-win_arm64.whl", hash = "sha256:3f89d10c1ff6a38d992c27fc8a4816af71a909e08a40ec66934240b1e74347c3", size = 111572, upload-time = "2026-10-07T12:23:00.479Z" },
|
|
258
|
+
{ url = "https://files.pythonhosted.org/packages/b9/20/1f88f19427d380a40e90a770e087489eaafe4aeee070ae88ed2bbec00acd/tomli-2.5.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:e9e15b4a6c7dd6b85b5fbab29488a73f1f70de516942308daa266bf0e0aeb0d4", size = 171814, upload-time = "2026-10-07T12:23:01.914Z" },
|
|
259
|
+
{ url = "https://files.pythonhosted.org/packages/d0/56/cbe5079c9f9a54b9b3e27fc82f08f3cb36edee75561679f53d2380c801d6/tomli-2.5.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:e12bbcd32897272fb05929110362ae9ff4c1b9bb26bd9e971e71dcd3275b4c3d", size = 171324, upload-time = "2026-10-07T12:23:03.18Z" },
|
|
260
|
+
{ url = "https://files.pythonhosted.org/packages/2b/30/1d53fd3b0f1cb3ba542e345ec32c26aefdddc4e829e4f3429af8a4f27782/tomli-2.5.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:20aa36de8f2cf87237143bc1fa1aae8d6612c09118f4da21c6a684db5dd1f6f9", size = 297441, upload-time = "2026-10-07T12:23:04.345Z" },
|
|
261
|
+
{ url = "https://files.pythonhosted.org/packages/66/d9/0800acb6a111686f764c1b91ef15cc42a20a66a46013bb42220f1d2c61c1/tomli-2.5.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22185fad8a1e622f064e78008018a0dd3323550dcb479cb7a1d296888d74024f", size = 307476, upload-time = "2026-10-07T12:23:05.671Z" },
|
|
262
|
+
{ url = "https://files.pythonhosted.org/packages/e8/63/30a8f3cd51b5bec37f04744bad0b0dc6160df84aad4f27b0e9283d66f221/tomli-2.5.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:984012f71908165449a951de2050d52f276bfe3aa5d5f570f63ddad814370374", size = 296113, upload-time = "2026-10-07T12:23:07.202Z" },
|
|
263
|
+
{ url = "https://files.pythonhosted.org/packages/ab/18/0b9ffc597e69c5a1e20a7823cb60d54b39a9f54e91edcb8574f022186758/tomli-2.5.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f79203b3965b4000e91808aaa7c040206093f2b8bf86f455982f2274c9ccf442", size = 307725, upload-time = "2026-10-07T12:23:08.508Z" },
|
|
264
|
+
{ url = "https://files.pythonhosted.org/packages/ab/c7/18f8baae0b5607a60e8e19b4a7fedee43a8ff6458e3896dcbbadeeac9c22/tomli-2.5.0-cp314-cp314t-win32.whl", hash = "sha256:91294a9fb94a75542f6e46e4a2ae709bd8d9b51134098cae5cf3bea5478b6d03", size = 108546, upload-time = "2026-10-07T12:23:09.956Z" },
|
|
265
|
+
{ url = "https://files.pythonhosted.org/packages/72/34/4cca9739254130627bde87500b3f2b512154fe2f278efa7e2a5e10ad4bcb/tomli-2.5.0-cp314-cp314t-win_amd64.whl", hash = "sha256:f15e3e0b835a6d68b10c86bf80a3149780498d6911c93c3ffd1861d19f9200f1", size = 117814, upload-time = "2026-10-07T12:23:11.486Z" },
|
|
266
|
+
{ url = "https://files.pythonhosted.org/packages/7d/fb/afa530d47dd80a78fce43beac6bc6e00f84558eafcffbc6f37b21e80d056/tomli-2.5.0-cp314-cp314t-win_arm64.whl", hash = "sha256:6664b7ae7af7294256c53960a6103077f4914cec8ff98479c352f622c6f6b2f0", size = 115188, upload-time = "2026-10-07T12:23:12.728Z" },
|
|
267
|
+
{ url = "https://files.pythonhosted.org/packages/66/98/316fdc00f8c0939e6fe50461dd343c162d3ad51d1286eb25b7db54361d50/tomli-2.5.0-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:a525685c2f97da40762b8695eb7aa0af4c8344ca1905c73e4e29cb04d34607dc", size = 162775, upload-time = "2026-10-07T12:23:13.941Z" },
|
|
268
|
+
{ url = "https://files.pythonhosted.org/packages/c5/22/7b10fa5bb01c9539f53f69b619361b19350acc73657772ea7ac70ba309a8/tomli-2.5.0-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:9dbb18c1cfb2f6517942fc9314437f66aa06d94436ffb1f06102ef3572f35276", size = 161406, upload-time = "2026-10-07T12:23:15.215Z" },
|
|
269
|
+
{ url = "https://files.pythonhosted.org/packages/9c/e7/1a069d86dfd20f1f84f71c63faed9f83c1d890bc06c27d82dc7d888fb573/tomli-2.5.0-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:752e8b1aa6a4367ef8bf6a1a1e005540f7ed055ba36d7193796812ca5404eb52", size = 273855, upload-time = "2026-10-07T12:23:16.471Z" },
|
|
270
|
+
{ url = "https://files.pythonhosted.org/packages/ae/83/d1ef43d1687d092ab9c235455c76e6e709483b346b056f086095c7c263a5/tomli-2.5.0-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c47300f9bf791808f77d82747691c4bb09cb14bdf3060cca99b42cdc4361d5a7", size = 284910, upload-time = "2026-10-07T12:23:18.166Z" },
|
|
271
|
+
{ url = "https://files.pythonhosted.org/packages/cc/05/f4d9cf7de61822ece0c3873f30d291e324911c71a378b8bfe5ced13fd9f5/tomli-2.5.0-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:19b0dd8749f4ea2f112c5fcfb3c5248390c899d7e2e173f1d91abee1fa0ff391", size = 277723, upload-time = "2026-10-07T12:23:19.355Z" },
|
|
272
|
+
{ url = "https://files.pythonhosted.org/packages/42/28/78262493141fa543151cf005760c3cb01d09fc28a11f993c05109902cb8c/tomli-2.5.0-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:57b1c3b01fab802e2899bc3d168dca320e14165e2fd9fd584760fb4ca5826859", size = 285115, upload-time = "2026-10-07T12:23:20.698Z" },
|
|
273
|
+
{ url = "https://files.pythonhosted.org/packages/1a/b9/e1dab9a30bcb677b5cc5cee810609cfd64f24306a3055767dd3fda00b1e0/tomli-2.5.0-cp315-cp315-win32.whl", hash = "sha256:667e521b37a6c5ccaa044202c235b530f90177ffe2cd4a64ecc213c7dd535feb", size = 103475, upload-time = "2026-10-07T12:23:21.941Z" },
|
|
274
|
+
{ url = "https://files.pythonhosted.org/packages/4c/bd/31a3790c11d6ea95fcf5e6022ac0f8d0543c9b61120b730fc481bd43d3b4/tomli-2.5.0-cp315-cp315-win_amd64.whl", hash = "sha256:d747252933c8a65ef6bd8da0fbb7ce28a90eb6119d8cd00772cd528aa07b68d5", size = 114589, upload-time = "2026-10-07T12:23:23.098Z" },
|
|
275
|
+
{ url = "https://files.pythonhosted.org/packages/47/a2/4f6310fa699364f0e3af7ee3af88dddd9af066d33e716a0265bbe2b3ea84/tomli-2.5.0-cp315-cp315-win_arm64.whl", hash = "sha256:75dbcde8751b0a960aa3de173aa5e894d590755c6d7758b7e774c06f1dc3cbdd", size = 111493, upload-time = "2026-10-07T12:23:24.233Z" },
|
|
276
|
+
{ url = "https://files.pythonhosted.org/packages/68/14/00853f0b396d8971107ae1921bb5b322fdee1650d2f16bf06c20adb532e5/tomli-2.5.0-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:2419c2a189551987b59d80e63ec355671283336f41c6b9b89462df679c7d0c57", size = 171380, upload-time = "2026-10-07T12:23:25.512Z" },
|
|
277
|
+
{ url = "https://files.pythonhosted.org/packages/89/ad/fa6949321dadee46b27363974fb197b94c911c3b0f7a5fd26d7dc18fc2a0/tomli-2.5.0-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:0dc598040da8d42cf20f0be588ed7004f46db12a0ac6c32e03a59dccedaaadcd", size = 170553, upload-time = "2026-10-07T12:23:26.855Z" },
|
|
278
|
+
{ url = "https://files.pythonhosted.org/packages/53/aa/3056c919eb3e084df3752b2cf5f865dcc04af0b27dba2f66d7b28af4633a/tomli-2.5.0-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:49096930c8d886c9bbdab62d2d0d17ce823ddeea522309a190b36245d5b49e01", size = 294428, upload-time = "2026-10-07T12:23:28.132Z" },
|
|
279
|
+
{ url = "https://files.pythonhosted.org/packages/96/b2/faeeb5d8769ea3832021d73e892c8391eae7b4b4f8b55a789127bd8b18a9/tomli-2.5.0-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8ade5023067f99fe72b88accd30d0ea05a158e9e32a11f124e731ea9695313f", size = 304909, upload-time = "2026-10-07T12:23:29.381Z" },
|
|
280
|
+
{ url = "https://files.pythonhosted.org/packages/f6/52/f094c09e73fb654b621716d019acb5d29bdfd1be01df80c281d552bda48d/tomli-2.5.0-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:b69564772b5c8f22ea5f498dff08cfa825045b4d4c4400529000bdf818aa3b2a", size = 293220, upload-time = "2026-10-07T12:23:30.608Z" },
|
|
281
|
+
{ url = "https://files.pythonhosted.org/packages/86/f5/0c30541078ca4b505ce3bd76ed931facbfec524dd018535d691d1af0a6d2/tomli-2.5.0-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:8ff3a2ca028c7eee0c777f9a092038d0a594a9fa04e215f929a22c329e2cb142", size = 305705, upload-time = "2026-10-07T12:23:32.181Z" },
|
|
282
|
+
{ url = "https://files.pythonhosted.org/packages/05/74/590e7d19d6a118fc5cc5704ff358e21d95b8573f6b9443b1519f29ca8825/tomli-2.5.0-cp315-cp315t-win32.whl", hash = "sha256:62fc1bc8eb03e3a9cadfca713d65614ed8e09d974a283295ffe3a831976b4dc5", size = 108432, upload-time = "2026-10-07T12:23:33.496Z" },
|
|
283
|
+
{ url = "https://files.pythonhosted.org/packages/1c/b8/63a75cfb27a17c38550e44025d3a6e7be64516fd8608a3b75703bf37d81b/tomli-2.5.0-cp315-cp315t-win_amd64.whl", hash = "sha256:f3fcbc57b1791fa6cbe5d8434179d51de12be1a4811469529f47f6e7487a2571", size = 117281, upload-time = "2026-10-07T12:23:34.648Z" },
|
|
284
|
+
{ url = "https://files.pythonhosted.org/packages/72/01/e8c1debb2173973372934c68fc8e46170ab60ef23ed4592dff4dec6e8993/tomli-2.5.0-cp315-cp315t-win_arm64.whl", hash = "sha256:d2ba24db8a9376921b5e87b4762b9adb0f3f1deaea68f2b8b0bb2c11efb9c3e7", size = 115069, upload-time = "2026-10-07T12:23:35.77Z" },
|
|
285
|
+
{ url = "https://files.pythonhosted.org/packages/60/3f/3e3f8fd0919249b0200c80fbc4f9a1e70be19f9883da71dfb7f8b9ab8aca/tomli-2.5.0-py3-none-any.whl", hash = "sha256:32a7b79ac57a2e83670ce329ccf675798bc5a2094783a63676866b70503f2e2b", size = 14765, upload-time = "2026-10-07T12:23:36.875Z" },
|
|
286
|
+
]
|
|
287
|
+
|
|
288
|
+
[[package]]
|
|
289
|
+
name = "typing-extensions"
|
|
290
|
+
version = "4.16.0"
|
|
291
|
+
source = { registry = "https://pypi.org/simple" }
|
|
292
|
+
sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555, upload-time = "2026-07-02T08:40:05.92Z" }
|
|
293
|
+
wheels = [
|
|
294
|
+
{ url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" },
|
|
295
|
+
]
|