rockbox-ffi 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.
- rockbox_ffi-0.1.0/.gitignore +5 -0
- rockbox_ffi-0.1.0/PKG-INFO +93 -0
- rockbox_ffi-0.1.0/README.md +84 -0
- rockbox_ffi-0.1.0/examples/smoke.py +60 -0
- rockbox_ffi-0.1.0/pyproject.toml +15 -0
- rockbox_ffi-0.1.0/src/rockbox_ffi/__init__.py +35 -0
- rockbox_ffi-0.1.0/src/rockbox_ffi/_ffi.py +135 -0
- rockbox_ffi-0.1.0/src/rockbox_ffi/dsp.py +159 -0
- rockbox_ffi-0.1.0/src/rockbox_ffi/enums.py +53 -0
- rockbox_ffi-0.1.0/src/rockbox_ffi/metadata.py +29 -0
- rockbox_ffi-0.1.0/src/rockbox_ffi/player.py +134 -0
- rockbox_ffi-0.1.0/uv.lock +253 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rockbox-ffi
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python bindings for the Rockbox DSP / metadata / playback engine
|
|
5
|
+
License: GPL-2.0-or-later
|
|
6
|
+
Requires-Python: >=3.9
|
|
7
|
+
Requires-Dist: cffi>=1.16
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
|
|
10
|
+
# rockbox-ffi (Python)
|
|
11
|
+
|
|
12
|
+
[](https://pypi.org/project/rockbox-ffi/)
|
|
13
|
+

|
|
14
|
+

|
|
15
|
+

|
|
16
|
+

|
|
17
|
+
|
|
18
|
+
Python bindings for the Rockbox **DSP**, **metadata**, and **playback**
|
|
19
|
+
engine, via `cffi` (ABI mode) over the prebuilt `librockbox_ffi` shared
|
|
20
|
+
library.
|
|
21
|
+
|
|
22
|
+
## Setup
|
|
23
|
+
|
|
24
|
+
Build the shared library once (from the repo root):
|
|
25
|
+
|
|
26
|
+
```sh
|
|
27
|
+
cargo build --release -p rockbox-ffi
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Then install the Python package with [uv](https://docs.astral.sh/uv/):
|
|
31
|
+
|
|
32
|
+
```sh
|
|
33
|
+
cd bindings/python
|
|
34
|
+
uv venv
|
|
35
|
+
uv pip install -e .
|
|
36
|
+
uv run python examples/smoke.py
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The library is located automatically by walking up to
|
|
40
|
+
`target/release/librockbox_ffi.{dylib,so}`. Override with the
|
|
41
|
+
`ROCKBOX_FFI_LIB` environment variable.
|
|
42
|
+
|
|
43
|
+
## Usage
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
import rockbox_ffi as rb
|
|
47
|
+
from rockbox_ffi import Dsp, Player, metadata
|
|
48
|
+
from rockbox_ffi.enums import DspReplayGainMode, ReplayGainMode, CrossfadeMode
|
|
49
|
+
|
|
50
|
+
# --- metadata ---------------------------------------------------------
|
|
51
|
+
meta = metadata.read("song.flac")
|
|
52
|
+
print(meta["artist"], "—", meta["title"], meta["duration_ms"], "ms")
|
|
53
|
+
print(metadata.probe("track.opus")) # -> "Opus"
|
|
54
|
+
|
|
55
|
+
# --- DSP (interleaved stereo int16) -----------------------------------
|
|
56
|
+
with Dsp(44100) as dsp:
|
|
57
|
+
dsp.eq_enable(True)
|
|
58
|
+
dsp.set_eq_band(0, cutoff_hz=60, q=0.7, gain_db=3.0)
|
|
59
|
+
dsp.set_replaygain(DspReplayGainMode.TRACK, noclip=True, preamp_db=0.0)
|
|
60
|
+
dsp.set_replaygain_gains(track_gain_db=-6.02) # halves amplitude
|
|
61
|
+
processed = dsp.process(samples) # array('h')
|
|
62
|
+
|
|
63
|
+
# --- playback (needs an output device) --------------------------------
|
|
64
|
+
with Player(volume=0.8) as player:
|
|
65
|
+
player.set_replaygain(ReplayGainMode.TRACK, preamp_db=0.0, prevent_clipping=True)
|
|
66
|
+
player.set_crossfade(CrossfadeMode.ALWAYS)
|
|
67
|
+
player.set_queue(["a.flac", "b.mp3", "c.opus"])
|
|
68
|
+
player.play()
|
|
69
|
+
print(player.status()) # {'state': 'playing', 'index': 0, ...}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## API
|
|
73
|
+
|
|
74
|
+
| Module | Contents |
|
|
75
|
+
| ---------------------- | --------------------------------------------------------------------- |
|
|
76
|
+
| `rockbox_ffi.metadata` | `read(path) -> dict`, `probe(filename) -> str \| None` |
|
|
77
|
+
| `rockbox_ffi.Dsp` | EQ / tone / surround / compressor / ReplayGain, `process(samples)` |
|
|
78
|
+
| `rockbox_ffi.Player` | queue + transport + crossfade + ReplayGain, `status() -> dict` |
|
|
79
|
+
| `rockbox_ffi.enums` | `DspReplayGainMode`, `ReplayGainMode`, `CrossfadeMode`, `MixMode`, … |
|
|
80
|
+
|
|
81
|
+
### Two ReplayGain encodings
|
|
82
|
+
|
|
83
|
+
The DSP and player use *different* mode integers (a quirk of the C ABI):
|
|
84
|
+
|
|
85
|
+
- `Dsp.set_replaygain` → `DspReplayGainMode` (`TRACK=0, ALBUM=1, SHUFFLE=2, OFF=3`)
|
|
86
|
+
- `Player.set_replaygain` → `ReplayGainMode` (`OFF=0, TRACK=1, ALBUM=2`)
|
|
87
|
+
|
|
88
|
+
Use the named enums and you won't have to remember which is which.
|
|
89
|
+
|
|
90
|
+
## Memory
|
|
91
|
+
|
|
92
|
+
All heap allocations crossing the FFI boundary (JSON strings, sample
|
|
93
|
+
buffers) are freed inside the wrappers — you never call a `*_free` yourself.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# rockbox-ffi (Python)
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/rockbox-ffi/)
|
|
4
|
+

|
|
5
|
+

|
|
6
|
+

|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
Python bindings for the Rockbox **DSP**, **metadata**, and **playback**
|
|
10
|
+
engine, via `cffi` (ABI mode) over the prebuilt `librockbox_ffi` shared
|
|
11
|
+
library.
|
|
12
|
+
|
|
13
|
+
## Setup
|
|
14
|
+
|
|
15
|
+
Build the shared library once (from the repo root):
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
cargo build --release -p rockbox-ffi
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Then install the Python package with [uv](https://docs.astral.sh/uv/):
|
|
22
|
+
|
|
23
|
+
```sh
|
|
24
|
+
cd bindings/python
|
|
25
|
+
uv venv
|
|
26
|
+
uv pip install -e .
|
|
27
|
+
uv run python examples/smoke.py
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The library is located automatically by walking up to
|
|
31
|
+
`target/release/librockbox_ffi.{dylib,so}`. Override with the
|
|
32
|
+
`ROCKBOX_FFI_LIB` environment variable.
|
|
33
|
+
|
|
34
|
+
## Usage
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
import rockbox_ffi as rb
|
|
38
|
+
from rockbox_ffi import Dsp, Player, metadata
|
|
39
|
+
from rockbox_ffi.enums import DspReplayGainMode, ReplayGainMode, CrossfadeMode
|
|
40
|
+
|
|
41
|
+
# --- metadata ---------------------------------------------------------
|
|
42
|
+
meta = metadata.read("song.flac")
|
|
43
|
+
print(meta["artist"], "—", meta["title"], meta["duration_ms"], "ms")
|
|
44
|
+
print(metadata.probe("track.opus")) # -> "Opus"
|
|
45
|
+
|
|
46
|
+
# --- DSP (interleaved stereo int16) -----------------------------------
|
|
47
|
+
with Dsp(44100) as dsp:
|
|
48
|
+
dsp.eq_enable(True)
|
|
49
|
+
dsp.set_eq_band(0, cutoff_hz=60, q=0.7, gain_db=3.0)
|
|
50
|
+
dsp.set_replaygain(DspReplayGainMode.TRACK, noclip=True, preamp_db=0.0)
|
|
51
|
+
dsp.set_replaygain_gains(track_gain_db=-6.02) # halves amplitude
|
|
52
|
+
processed = dsp.process(samples) # array('h')
|
|
53
|
+
|
|
54
|
+
# --- playback (needs an output device) --------------------------------
|
|
55
|
+
with Player(volume=0.8) as player:
|
|
56
|
+
player.set_replaygain(ReplayGainMode.TRACK, preamp_db=0.0, prevent_clipping=True)
|
|
57
|
+
player.set_crossfade(CrossfadeMode.ALWAYS)
|
|
58
|
+
player.set_queue(["a.flac", "b.mp3", "c.opus"])
|
|
59
|
+
player.play()
|
|
60
|
+
print(player.status()) # {'state': 'playing', 'index': 0, ...}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## API
|
|
64
|
+
|
|
65
|
+
| Module | Contents |
|
|
66
|
+
| ---------------------- | --------------------------------------------------------------------- |
|
|
67
|
+
| `rockbox_ffi.metadata` | `read(path) -> dict`, `probe(filename) -> str \| None` |
|
|
68
|
+
| `rockbox_ffi.Dsp` | EQ / tone / surround / compressor / ReplayGain, `process(samples)` |
|
|
69
|
+
| `rockbox_ffi.Player` | queue + transport + crossfade + ReplayGain, `status() -> dict` |
|
|
70
|
+
| `rockbox_ffi.enums` | `DspReplayGainMode`, `ReplayGainMode`, `CrossfadeMode`, `MixMode`, … |
|
|
71
|
+
|
|
72
|
+
### Two ReplayGain encodings
|
|
73
|
+
|
|
74
|
+
The DSP and player use *different* mode integers (a quirk of the C ABI):
|
|
75
|
+
|
|
76
|
+
- `Dsp.set_replaygain` → `DspReplayGainMode` (`TRACK=0, ALBUM=1, SHUFFLE=2, OFF=3`)
|
|
77
|
+
- `Player.set_replaygain` → `ReplayGainMode` (`OFF=0, TRACK=1, ALBUM=2`)
|
|
78
|
+
|
|
79
|
+
Use the named enums and you won't have to remember which is which.
|
|
80
|
+
|
|
81
|
+
## Memory
|
|
82
|
+
|
|
83
|
+
All heap allocations crossing the FFI boundary (JSON strings, sample
|
|
84
|
+
buffers) are freed inside the wrappers — you never call a `*_free` yourself.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""End-to-end smoke test for the Python bindings.
|
|
2
|
+
|
|
3
|
+
Run: `uv run python examples/smoke.py`
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
import rockbox_ffi as rb
|
|
11
|
+
from rockbox_ffi import Dsp, Player, metadata
|
|
12
|
+
from rockbox_ffi.enums import DspReplayGainMode, ReplayGainMode
|
|
13
|
+
|
|
14
|
+
REPO = Path(__file__).resolve().parents[3]
|
|
15
|
+
FIXTURE = REPO / "crates" / "rocksky" / "fixtures" / "08 - Internet Money - Speak(Explicit).m4a"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def main() -> None:
|
|
19
|
+
print(f"ABI version: {rb.abi_version()}")
|
|
20
|
+
|
|
21
|
+
# -- metadata ---------------------------------------------------------
|
|
22
|
+
meta = metadata.read(str(FIXTURE))
|
|
23
|
+
print(f"codec={meta['codec']!r} title={meta['title']!r} "
|
|
24
|
+
f"artist={meta['artist']!r} duration_ms={meta['duration_ms']} "
|
|
25
|
+
f"sample_rate={meta['sample_rate']}")
|
|
26
|
+
assert meta["codec"], "codec label should not be empty"
|
|
27
|
+
|
|
28
|
+
probe = metadata.probe("song.flac")
|
|
29
|
+
print(f"probe('song.flac') = {probe!r}")
|
|
30
|
+
assert probe, "flac probe should return a label"
|
|
31
|
+
|
|
32
|
+
# -- DSP: -6.0206 dB track gain should HALVE amplitude ----------------
|
|
33
|
+
rate = 44100
|
|
34
|
+
with Dsp(rate) as dsp:
|
|
35
|
+
dsp.set_replaygain(DspReplayGainMode.TRACK, noclip=False, preamp_db=0.0)
|
|
36
|
+
dsp.set_replaygain_gains(track_gain_db=-6.0206) # x0.5
|
|
37
|
+
|
|
38
|
+
sine = rb.sine_stereo(1000.0, 1.0, rate, amplitude=16000)
|
|
39
|
+
out = dsp.process(sine)
|
|
40
|
+
peak = max(abs(s) for s in out)
|
|
41
|
+
print(f"DSP peak after -6.02 dB track gain: {peak} (expected ~8000)")
|
|
42
|
+
assert 7600 <= peak <= 8400, f"peak {peak} out of range"
|
|
43
|
+
|
|
44
|
+
# -- Player (construct only, no audible playback) ---------------------
|
|
45
|
+
with Player(volume=0.0) as player:
|
|
46
|
+
rate = player.sample_rate()
|
|
47
|
+
print(f"Player sample_rate={rate}")
|
|
48
|
+
assert rate > 0
|
|
49
|
+
player.set_volume(0.0)
|
|
50
|
+
player.set_queue([str(FIXTURE)])
|
|
51
|
+
st = player.status()
|
|
52
|
+
print(f"Player status: state={st['state']!r} queue_len={st['queue_len']}")
|
|
53
|
+
assert st["state"] == "stopped"
|
|
54
|
+
assert st["queue_len"] == 1
|
|
55
|
+
|
|
56
|
+
print("\nALL CHECKS PASSED ✔")
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
if __name__ == "__main__":
|
|
60
|
+
main()
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "rockbox-ffi"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Python bindings for the Rockbox DSP / metadata / playback engine"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.9"
|
|
7
|
+
license = { text = "GPL-2.0-or-later" }
|
|
8
|
+
dependencies = ["cffi>=1.16"]
|
|
9
|
+
|
|
10
|
+
[build-system]
|
|
11
|
+
requires = ["hatchling"]
|
|
12
|
+
build-backend = "hatchling.build"
|
|
13
|
+
|
|
14
|
+
[tool.hatch.build.targets.wheel]
|
|
15
|
+
packages = ["src/rockbox_ffi"]
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""Python bindings for the Rockbox DSP / metadata / playback engine.
|
|
2
|
+
|
|
3
|
+
Thin ``cffi`` wrappers over the ``librockbox_ffi`` C ABI. See the submodules
|
|
4
|
+
:mod:`rockbox_ffi.metadata`, :mod:`rockbox_ffi.dsp`, :mod:`rockbox_ffi.player`.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from . import metadata
|
|
8
|
+
from ._ffi import lib
|
|
9
|
+
from .dsp import Dsp, sine_stereo
|
|
10
|
+
from .enums import (
|
|
11
|
+
ChannelConfig,
|
|
12
|
+
CrossfadeMode,
|
|
13
|
+
DspReplayGainMode,
|
|
14
|
+
MixMode,
|
|
15
|
+
ReplayGainMode,
|
|
16
|
+
)
|
|
17
|
+
from .player import Player
|
|
18
|
+
|
|
19
|
+
__all__ = [
|
|
20
|
+
"metadata",
|
|
21
|
+
"Dsp",
|
|
22
|
+
"Player",
|
|
23
|
+
"sine_stereo",
|
|
24
|
+
"ChannelConfig",
|
|
25
|
+
"CrossfadeMode",
|
|
26
|
+
"DspReplayGainMode",
|
|
27
|
+
"MixMode",
|
|
28
|
+
"ReplayGainMode",
|
|
29
|
+
"abi_version",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def abi_version() -> int:
|
|
34
|
+
"""ABI major version of the loaded library (bumped on breaking changes)."""
|
|
35
|
+
return int(lib.rb_ffi_abi_version())
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"""cffi (ABI mode) loader for librockbox_ffi.
|
|
2
|
+
|
|
3
|
+
Declares exactly the functions we call and ``dlopen``s the prebuilt shared
|
|
4
|
+
library — no C is compiled here. The library is located via the
|
|
5
|
+
``ROCKBOX_FFI_LIB`` env var, then by walking up to the repo's
|
|
6
|
+
``target/release`` directory.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import os
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
from cffi import FFI
|
|
15
|
+
|
|
16
|
+
ffi = FFI()
|
|
17
|
+
|
|
18
|
+
# Mirrors include/rockbox_ffi.h — keep in sync with the C ABI.
|
|
19
|
+
ffi.cdef(
|
|
20
|
+
"""
|
|
21
|
+
typedef struct RbDsp RbDsp;
|
|
22
|
+
typedef struct RbPlayer RbPlayer;
|
|
23
|
+
|
|
24
|
+
uint32_t rb_ffi_abi_version(void);
|
|
25
|
+
|
|
26
|
+
void rb_string_free(char *p);
|
|
27
|
+
void rb_buffer_free(int16_t *p, size_t len);
|
|
28
|
+
|
|
29
|
+
RbDsp *rb_dsp_new(uint32_t sample_rate);
|
|
30
|
+
void rb_dsp_free(RbDsp *p);
|
|
31
|
+
void rb_dsp_set_input_frequency(RbDsp *p, uint32_t hz);
|
|
32
|
+
void rb_dsp_flush(RbDsp *p);
|
|
33
|
+
void rb_dsp_eq_enable(RbDsp *p, bool enable);
|
|
34
|
+
void rb_dsp_set_tone(RbDsp *p, int32_t bass_db, int32_t treble_db);
|
|
35
|
+
void rb_dsp_set_tone_cutoffs(RbDsp *p, int32_t bass_hz, int32_t treble_hz);
|
|
36
|
+
void rb_dsp_set_surround(RbDsp *p, int32_t delay_ms, int32_t balance,
|
|
37
|
+
int32_t fx1, int32_t fx2);
|
|
38
|
+
void rb_dsp_set_channel_config(RbDsp *p, int32_t mode);
|
|
39
|
+
void rb_dsp_set_stereo_width(RbDsp *p, int32_t percent);
|
|
40
|
+
void rb_dsp_set_compressor(RbDsp *p, int32_t threshold, int32_t makeup_gain,
|
|
41
|
+
int32_t ratio, int32_t knee, int32_t release_time,
|
|
42
|
+
int32_t attack_time);
|
|
43
|
+
void rb_dsp_set_replaygain(RbDsp *p, int32_t mode, bool noclip,
|
|
44
|
+
float preamp_db);
|
|
45
|
+
void rb_dsp_set_replaygain_gains(RbDsp *p, float track_gain_db,
|
|
46
|
+
float album_gain_db, float track_peak,
|
|
47
|
+
float album_peak);
|
|
48
|
+
void rb_dsp_set_replaygain_gains_raw(RbDsp *p, int64_t track_gain,
|
|
49
|
+
int64_t album_gain, int64_t track_peak,
|
|
50
|
+
int64_t album_peak);
|
|
51
|
+
void rb_dsp_set_eq_band(RbDsp *p, size_t band, int32_t cutoff_hz, float q,
|
|
52
|
+
float gain_db);
|
|
53
|
+
void rb_dsp_set_eq_precut(RbDsp *p, float db);
|
|
54
|
+
int16_t *rb_dsp_process(RbDsp *p, const int16_t *input, size_t in_len,
|
|
55
|
+
size_t *out_len);
|
|
56
|
+
|
|
57
|
+
char *rb_meta_read_json(const char *path);
|
|
58
|
+
char *rb_meta_probe(const char *filename);
|
|
59
|
+
|
|
60
|
+
RbPlayer *rb_player_new(void);
|
|
61
|
+
RbPlayer *rb_player_new_with_config(uint32_t sample_rate, float buffer_seconds,
|
|
62
|
+
float volume, int32_t rg_mode,
|
|
63
|
+
float rg_preamp_db, bool rg_prevent_clipping,
|
|
64
|
+
int32_t xfade_mode, uint32_t fo_delay_ms,
|
|
65
|
+
uint32_t fo_dur_ms, uint32_t fi_delay_ms,
|
|
66
|
+
uint32_t fi_dur_ms, int32_t mix_mode);
|
|
67
|
+
void rb_player_free(RbPlayer *p);
|
|
68
|
+
void rb_player_set_queue_json(RbPlayer *p, const char *json);
|
|
69
|
+
void rb_player_enqueue(RbPlayer *p, const char *path);
|
|
70
|
+
void rb_player_play(RbPlayer *p);
|
|
71
|
+
void rb_player_pause(RbPlayer *p);
|
|
72
|
+
void rb_player_toggle(RbPlayer *p);
|
|
73
|
+
void rb_player_stop(RbPlayer *p);
|
|
74
|
+
void rb_player_next(RbPlayer *p);
|
|
75
|
+
void rb_player_previous(RbPlayer *p);
|
|
76
|
+
void rb_player_skip_to(RbPlayer *p, size_t index);
|
|
77
|
+
void rb_player_seek_ms(RbPlayer *p, uint64_t ms);
|
|
78
|
+
void rb_player_set_volume(RbPlayer *p, float vol);
|
|
79
|
+
void rb_player_set_crossfade(RbPlayer *p, int32_t mode, uint32_t fo_delay_ms,
|
|
80
|
+
uint32_t fo_dur_ms, uint32_t fi_delay_ms,
|
|
81
|
+
uint32_t fi_dur_ms, int32_t mix_mode);
|
|
82
|
+
void rb_player_set_replaygain(RbPlayer *p, int32_t mode, float preamp_db,
|
|
83
|
+
bool prevent_clipping);
|
|
84
|
+
float rb_player_volume(RbPlayer *p);
|
|
85
|
+
uint32_t rb_player_sample_rate(RbPlayer *p);
|
|
86
|
+
char *rb_player_status_json(RbPlayer *p);
|
|
87
|
+
"""
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def _candidate_paths() -> list[Path]:
|
|
92
|
+
names = ["librockbox_ffi.dylib", "librockbox_ffi.so", "rockbox_ffi.dll"]
|
|
93
|
+
paths: list[Path] = []
|
|
94
|
+
|
|
95
|
+
env = os.environ.get("ROCKBOX_FFI_LIB")
|
|
96
|
+
if env:
|
|
97
|
+
paths.append(Path(env))
|
|
98
|
+
|
|
99
|
+
# Walk up from this file looking for target/release (repo checkout).
|
|
100
|
+
here = Path(__file__).resolve()
|
|
101
|
+
for parent in here.parents:
|
|
102
|
+
rel = parent / "target" / "release"
|
|
103
|
+
if rel.is_dir():
|
|
104
|
+
for name in names:
|
|
105
|
+
paths.append(rel / name)
|
|
106
|
+
return paths
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def _load():
|
|
110
|
+
tried: list[str] = []
|
|
111
|
+
for path in _candidate_paths():
|
|
112
|
+
tried.append(str(path))
|
|
113
|
+
if path.exists():
|
|
114
|
+
return ffi.dlopen(str(path))
|
|
115
|
+
raise OSError(
|
|
116
|
+
"could not locate librockbox_ffi shared library. Set ROCKBOX_FFI_LIB "
|
|
117
|
+
"or run `cargo build --release -p rockbox-ffi`. Tried:\n "
|
|
118
|
+
+ "\n ".join(tried)
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
lib = _load()
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def take_string(ptr) -> str | None:
|
|
126
|
+
"""Copy a heap C string returned by the ABI into a str, then free it.
|
|
127
|
+
|
|
128
|
+
Returns ``None`` for a NULL pointer (the ABI's error/absent signal).
|
|
129
|
+
"""
|
|
130
|
+
if ptr == ffi.NULL:
|
|
131
|
+
return None
|
|
132
|
+
try:
|
|
133
|
+
return ffi.string(ptr).decode("utf-8", "replace")
|
|
134
|
+
finally:
|
|
135
|
+
lib.rb_string_free(ptr)
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"""The DSP pipeline: EQ, tone, surround, compressor, ReplayGain, resampler."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import array
|
|
6
|
+
import math
|
|
7
|
+
from typing import Iterable, Optional
|
|
8
|
+
|
|
9
|
+
from ._ffi import ffi, lib
|
|
10
|
+
|
|
11
|
+
_NAN = float("nan")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _opt(v: Optional[float]) -> float:
|
|
15
|
+
"""None -> NaN, the ABI's 'tag absent' sentinel."""
|
|
16
|
+
return _NAN if v is None else float(v)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class Dsp:
|
|
20
|
+
"""Interleaved-S16LE-stereo DSP instance.
|
|
21
|
+
|
|
22
|
+
The underlying ``dsp_config`` is a process-wide singleton, so only one
|
|
23
|
+
:class:`Dsp` may exist at a time and it must be used from one thread.
|
|
24
|
+
Use as a context manager, or call :meth:`close` when done.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self, sample_rate: int):
|
|
28
|
+
self._p = lib.rb_dsp_new(int(sample_rate))
|
|
29
|
+
if self._p == ffi.NULL:
|
|
30
|
+
raise RuntimeError("rb_dsp_new returned NULL")
|
|
31
|
+
|
|
32
|
+
# -- lifecycle --------------------------------------------------------
|
|
33
|
+
def close(self) -> None:
|
|
34
|
+
if getattr(self, "_p", ffi.NULL) != ffi.NULL:
|
|
35
|
+
lib.rb_dsp_free(self._p)
|
|
36
|
+
self._p = ffi.NULL
|
|
37
|
+
|
|
38
|
+
def __del__(self):
|
|
39
|
+
self.close()
|
|
40
|
+
|
|
41
|
+
def __enter__(self) -> "Dsp":
|
|
42
|
+
return self
|
|
43
|
+
|
|
44
|
+
def __exit__(self, *exc) -> None:
|
|
45
|
+
self.close()
|
|
46
|
+
|
|
47
|
+
# -- configuration ----------------------------------------------------
|
|
48
|
+
def set_input_frequency(self, hz: int) -> None:
|
|
49
|
+
lib.rb_dsp_set_input_frequency(self._p, int(hz))
|
|
50
|
+
|
|
51
|
+
def flush(self) -> None:
|
|
52
|
+
lib.rb_dsp_flush(self._p)
|
|
53
|
+
|
|
54
|
+
def eq_enable(self, enable: bool) -> None:
|
|
55
|
+
lib.rb_dsp_eq_enable(self._p, bool(enable))
|
|
56
|
+
|
|
57
|
+
def set_eq_band(self, band: int, cutoff_hz: int, q: float, gain_db: float) -> None:
|
|
58
|
+
"""Configure one EQ band (0..=9). Band 0 low shelf, 9 high shelf."""
|
|
59
|
+
lib.rb_dsp_set_eq_band(self._p, int(band), int(cutoff_hz), float(q), float(gain_db))
|
|
60
|
+
|
|
61
|
+
def set_eq_precut(self, db: float) -> None:
|
|
62
|
+
lib.rb_dsp_set_eq_precut(self._p, float(db))
|
|
63
|
+
|
|
64
|
+
def set_tone(self, bass_db: int, treble_db: int) -> None:
|
|
65
|
+
lib.rb_dsp_set_tone(self._p, int(bass_db), int(treble_db))
|
|
66
|
+
|
|
67
|
+
def set_tone_cutoffs(self, bass_hz: int, treble_hz: int) -> None:
|
|
68
|
+
lib.rb_dsp_set_tone_cutoffs(self._p, int(bass_hz), int(treble_hz))
|
|
69
|
+
|
|
70
|
+
def set_surround(self, delay_ms: int, balance: int, fx1: int, fx2: int) -> None:
|
|
71
|
+
lib.rb_dsp_set_surround(self._p, int(delay_ms), int(balance), int(fx1), int(fx2))
|
|
72
|
+
|
|
73
|
+
def set_channel_config(self, mode: int) -> None:
|
|
74
|
+
lib.rb_dsp_set_channel_config(self._p, int(mode))
|
|
75
|
+
|
|
76
|
+
def set_stereo_width(self, percent: int) -> None:
|
|
77
|
+
lib.rb_dsp_set_stereo_width(self._p, int(percent))
|
|
78
|
+
|
|
79
|
+
def set_compressor(
|
|
80
|
+
self,
|
|
81
|
+
threshold: int,
|
|
82
|
+
makeup_gain: int,
|
|
83
|
+
ratio: int,
|
|
84
|
+
knee: int,
|
|
85
|
+
release_time: int,
|
|
86
|
+
attack_time: int,
|
|
87
|
+
) -> None:
|
|
88
|
+
lib.rb_dsp_set_compressor(
|
|
89
|
+
self._p, int(threshold), int(makeup_gain), int(ratio),
|
|
90
|
+
int(knee), int(release_time), int(attack_time),
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
def set_replaygain(self, mode: int, noclip: bool, preamp_db: float) -> None:
|
|
94
|
+
"""mode: see :class:`rockbox_ffi.enums.DspReplayGainMode`
|
|
95
|
+
(TRACK=0, ALBUM=1, SHUFFLE=2, OFF=3)."""
|
|
96
|
+
lib.rb_dsp_set_replaygain(self._p, int(mode), bool(noclip), float(preamp_db))
|
|
97
|
+
|
|
98
|
+
def set_replaygain_gains(
|
|
99
|
+
self,
|
|
100
|
+
track_gain_db: Optional[float] = None,
|
|
101
|
+
album_gain_db: Optional[float] = None,
|
|
102
|
+
track_peak: Optional[float] = None,
|
|
103
|
+
album_peak: Optional[float] = None,
|
|
104
|
+
) -> None:
|
|
105
|
+
"""Per-track gains in plain dB / peaks as linear amplitude
|
|
106
|
+
(1.0 = full scale). None for any absent tag."""
|
|
107
|
+
lib.rb_dsp_set_replaygain_gains(
|
|
108
|
+
self._p, _opt(track_gain_db), _opt(album_gain_db),
|
|
109
|
+
_opt(track_peak), _opt(album_peak),
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
def set_replaygain_gains_raw(
|
|
113
|
+
self, track_gain: int, album_gain: int, track_peak: int, album_peak: int
|
|
114
|
+
) -> None:
|
|
115
|
+
"""Native Q7.24 linear factors (the ``raw_*`` fields from
|
|
116
|
+
:func:`rockbox_ffi.metadata.read`), 0 = not tagged."""
|
|
117
|
+
lib.rb_dsp_set_replaygain_gains_raw(
|
|
118
|
+
self._p, int(track_gain), int(album_gain), int(track_peak), int(album_peak)
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
# -- processing -------------------------------------------------------
|
|
122
|
+
def process(self, samples: Iterable[int]) -> array.array:
|
|
123
|
+
"""Run interleaved stereo S16 ``samples`` through the pipeline.
|
|
124
|
+
|
|
125
|
+
Accepts any int16 sequence (list, ``array('h')``, bytes-like via
|
|
126
|
+
``array``). Returns a new ``array('h')`` of processed samples
|
|
127
|
+
(length may differ from the input — the resampler buffers).
|
|
128
|
+
"""
|
|
129
|
+
buf = samples if isinstance(samples, array.array) and samples.typecode == "h" \
|
|
130
|
+
else array.array("h", samples)
|
|
131
|
+
n = len(buf)
|
|
132
|
+
if n % 2 != 0:
|
|
133
|
+
raise ValueError("input must be interleaved stereo (even length)")
|
|
134
|
+
|
|
135
|
+
cin = ffi.cast("const int16_t *", ffi.from_buffer(buf))
|
|
136
|
+
out_len = ffi.new("size_t *")
|
|
137
|
+
out_ptr = lib.rb_dsp_process(self._p, cin, n, out_len)
|
|
138
|
+
|
|
139
|
+
produced = int(out_len[0])
|
|
140
|
+
if out_ptr == ffi.NULL or produced == 0:
|
|
141
|
+
return array.array("h")
|
|
142
|
+
try:
|
|
143
|
+
result = array.array("h")
|
|
144
|
+
result.frombytes(ffi.buffer(out_ptr, produced * 2)[:])
|
|
145
|
+
return result
|
|
146
|
+
finally:
|
|
147
|
+
lib.rb_buffer_free(out_ptr, produced)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def sine_stereo(freq_hz: float, seconds: float, rate: int, amplitude: int = 16000) -> array.array:
|
|
151
|
+
"""Helper: generate ``seconds`` of a sine as interleaved stereo int16."""
|
|
152
|
+
n = int(seconds * rate)
|
|
153
|
+
buf = array.array("h")
|
|
154
|
+
for i in range(n):
|
|
155
|
+
s = int(math.sin(i * 2.0 * math.pi * freq_hz / rate) * amplitude)
|
|
156
|
+
s = max(-32768, min(32767, s))
|
|
157
|
+
buf.append(s)
|
|
158
|
+
buf.append(s)
|
|
159
|
+
return buf
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""Enum constants for the Rockbox FFI.
|
|
2
|
+
|
|
3
|
+
Note the two *different* ReplayGain encodings in the C ABI:
|
|
4
|
+
|
|
5
|
+
* The **DSP-level** call ``rb_dsp_set_replaygain`` (exposed via
|
|
6
|
+
:meth:`rockbox_ffi.dsp.Dsp.set_replaygain`) uses the Rockbox-native values:
|
|
7
|
+
``TRACK=0, ALBUM=1, SHUFFLE=2, OFF=3`` — see :class:`DspReplayGainMode`.
|
|
8
|
+
* The **player-level** call ``rb_player_set_replaygain`` uses a simpler
|
|
9
|
+
encoding: ``OFF=0, TRACK=1, ALBUM=2`` — see :class:`ReplayGainMode`.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from enum import IntEnum
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class DspReplayGainMode(IntEnum):
|
|
16
|
+
"""Values for :meth:`rockbox_ffi.dsp.Dsp.set_replaygain` (native Rockbox)."""
|
|
17
|
+
|
|
18
|
+
TRACK = 0
|
|
19
|
+
ALBUM = 1
|
|
20
|
+
SHUFFLE = 2
|
|
21
|
+
OFF = 3
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class ReplayGainMode(IntEnum):
|
|
25
|
+
"""Values for :meth:`rockbox_ffi.player.Player.set_replaygain`."""
|
|
26
|
+
|
|
27
|
+
OFF = 0
|
|
28
|
+
TRACK = 1
|
|
29
|
+
ALBUM = 2
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class CrossfadeMode(IntEnum):
|
|
33
|
+
OFF = 0
|
|
34
|
+
AUTO_SKIP = 1
|
|
35
|
+
MANUAL_SKIP = 2
|
|
36
|
+
SHUFFLE = 3
|
|
37
|
+
SHUFFLE_OR_MANUAL = 4
|
|
38
|
+
ALWAYS = 5
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class MixMode(IntEnum):
|
|
42
|
+
CROSSFADE = 0
|
|
43
|
+
MIX = 1
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class ChannelConfig(IntEnum):
|
|
47
|
+
STEREO = 0
|
|
48
|
+
MONO = 1
|
|
49
|
+
CUSTOM = 2
|
|
50
|
+
MONO_LEFT = 3
|
|
51
|
+
MONO_RIGHT = 4
|
|
52
|
+
KARAOKE = 5
|
|
53
|
+
SWAP = 6
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""Audio file metadata parsing."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
from typing import Optional
|
|
7
|
+
|
|
8
|
+
from ._ffi import ffi, lib, take_string
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def read(path: str) -> dict:
|
|
12
|
+
"""Parse the metadata of the audio file at ``path``.
|
|
13
|
+
|
|
14
|
+
Returns a dict with tag strings, ``duration_ms``, ``bitrate``,
|
|
15
|
+
``sample_rate``, a nested ``replaygain`` dict (including the raw Q7.24
|
|
16
|
+
``raw_*`` fields), and optional ``album_art`` / ``cuesheet`` locations.
|
|
17
|
+
|
|
18
|
+
Raises ``FileNotFoundError`` / ``ValueError`` on failure.
|
|
19
|
+
"""
|
|
20
|
+
s = take_string(lib.rb_meta_read_json(path.encode("utf-8")))
|
|
21
|
+
if s is None:
|
|
22
|
+
raise ValueError(f"could not read metadata from {path!r}")
|
|
23
|
+
return json.loads(s)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def probe(filename: str) -> Optional[str]:
|
|
27
|
+
"""Guess the codec label (e.g. ``"FLAC"``) from a filename's extension
|
|
28
|
+
without opening the file. Returns ``None`` for an unknown extension."""
|
|
29
|
+
return take_string(lib.rb_meta_probe(filename.encode("utf-8")))
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"""Queue-based player with native ReplayGain and Rockbox crossfade.
|
|
2
|
+
|
|
3
|
+
A :class:`Player` owns a live audio output device and a background engine
|
|
4
|
+
thread — construct it only where an output device exists.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import json
|
|
10
|
+
from typing import List, Optional
|
|
11
|
+
|
|
12
|
+
from ._ffi import ffi, lib, take_string
|
|
13
|
+
from .enums import CrossfadeMode, MixMode, ReplayGainMode
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class Player:
|
|
17
|
+
def __init__(
|
|
18
|
+
self,
|
|
19
|
+
*,
|
|
20
|
+
sample_rate: int = 0,
|
|
21
|
+
buffer_seconds: float = 4.0,
|
|
22
|
+
volume: float = 1.0,
|
|
23
|
+
replaygain_mode: int = ReplayGainMode.OFF,
|
|
24
|
+
replaygain_preamp_db: float = 0.0,
|
|
25
|
+
replaygain_prevent_clipping: bool = True,
|
|
26
|
+
crossfade_mode: int = CrossfadeMode.OFF,
|
|
27
|
+
fade_out_delay_ms: int = 0,
|
|
28
|
+
fade_out_duration_ms: int = 2000,
|
|
29
|
+
fade_in_delay_ms: int = 0,
|
|
30
|
+
fade_in_duration_ms: int = 2000,
|
|
31
|
+
mix_mode: int = MixMode.CROSSFADE,
|
|
32
|
+
_default: bool = False,
|
|
33
|
+
):
|
|
34
|
+
"""Create a player. With no args, uses the device default sample rate
|
|
35
|
+
and Rockbox default settings. ``sample_rate=0`` means device default."""
|
|
36
|
+
if _default:
|
|
37
|
+
self._p = lib.rb_player_new()
|
|
38
|
+
else:
|
|
39
|
+
self._p = lib.rb_player_new_with_config(
|
|
40
|
+
int(sample_rate), float(buffer_seconds), float(volume),
|
|
41
|
+
int(replaygain_mode), float(replaygain_preamp_db),
|
|
42
|
+
bool(replaygain_prevent_clipping), int(crossfade_mode),
|
|
43
|
+
int(fade_out_delay_ms), int(fade_out_duration_ms),
|
|
44
|
+
int(fade_in_delay_ms), int(fade_in_duration_ms), int(mix_mode),
|
|
45
|
+
)
|
|
46
|
+
if self._p == ffi.NULL:
|
|
47
|
+
raise RuntimeError("failed to create Player (no output device?)")
|
|
48
|
+
|
|
49
|
+
@classmethod
|
|
50
|
+
def default(cls) -> "Player":
|
|
51
|
+
"""Player on the default device with default settings."""
|
|
52
|
+
return cls(_default=True)
|
|
53
|
+
|
|
54
|
+
# -- lifecycle --------------------------------------------------------
|
|
55
|
+
def close(self) -> None:
|
|
56
|
+
if getattr(self, "_p", ffi.NULL) != ffi.NULL:
|
|
57
|
+
lib.rb_player_free(self._p)
|
|
58
|
+
self._p = ffi.NULL
|
|
59
|
+
|
|
60
|
+
def __del__(self):
|
|
61
|
+
self.close()
|
|
62
|
+
|
|
63
|
+
def __enter__(self) -> "Player":
|
|
64
|
+
return self
|
|
65
|
+
|
|
66
|
+
def __exit__(self, *exc) -> None:
|
|
67
|
+
self.close()
|
|
68
|
+
|
|
69
|
+
# -- queue ------------------------------------------------------------
|
|
70
|
+
def set_queue(self, paths: List[str]) -> None:
|
|
71
|
+
lib.rb_player_set_queue_json(self._p, json.dumps(list(paths)).encode("utf-8"))
|
|
72
|
+
|
|
73
|
+
def enqueue(self, path: str) -> None:
|
|
74
|
+
lib.rb_player_enqueue(self._p, path.encode("utf-8"))
|
|
75
|
+
|
|
76
|
+
# -- transport --------------------------------------------------------
|
|
77
|
+
def play(self) -> None:
|
|
78
|
+
lib.rb_player_play(self._p)
|
|
79
|
+
|
|
80
|
+
def pause(self) -> None:
|
|
81
|
+
lib.rb_player_pause(self._p)
|
|
82
|
+
|
|
83
|
+
def toggle(self) -> None:
|
|
84
|
+
lib.rb_player_toggle(self._p)
|
|
85
|
+
|
|
86
|
+
def stop(self) -> None:
|
|
87
|
+
lib.rb_player_stop(self._p)
|
|
88
|
+
|
|
89
|
+
def next(self) -> None:
|
|
90
|
+
lib.rb_player_next(self._p)
|
|
91
|
+
|
|
92
|
+
def previous(self) -> None:
|
|
93
|
+
lib.rb_player_previous(self._p)
|
|
94
|
+
|
|
95
|
+
def skip_to(self, index: int) -> None:
|
|
96
|
+
lib.rb_player_skip_to(self._p, int(index))
|
|
97
|
+
|
|
98
|
+
def seek_ms(self, ms: int) -> None:
|
|
99
|
+
lib.rb_player_seek_ms(self._p, int(ms))
|
|
100
|
+
|
|
101
|
+
# -- settings ---------------------------------------------------------
|
|
102
|
+
def set_volume(self, vol: float) -> None:
|
|
103
|
+
lib.rb_player_set_volume(self._p, float(vol))
|
|
104
|
+
|
|
105
|
+
def volume(self) -> float:
|
|
106
|
+
return float(lib.rb_player_volume(self._p))
|
|
107
|
+
|
|
108
|
+
def sample_rate(self) -> int:
|
|
109
|
+
return int(lib.rb_player_sample_rate(self._p))
|
|
110
|
+
|
|
111
|
+
def set_crossfade(
|
|
112
|
+
self,
|
|
113
|
+
mode: int,
|
|
114
|
+
fade_out_delay_ms: int = 0,
|
|
115
|
+
fade_out_duration_ms: int = 2000,
|
|
116
|
+
fade_in_delay_ms: int = 0,
|
|
117
|
+
fade_in_duration_ms: int = 2000,
|
|
118
|
+
mix_mode: int = MixMode.CROSSFADE,
|
|
119
|
+
) -> None:
|
|
120
|
+
lib.rb_player_set_crossfade(
|
|
121
|
+
self._p, int(mode), int(fade_out_delay_ms), int(fade_out_duration_ms),
|
|
122
|
+
int(fade_in_delay_ms), int(fade_in_duration_ms), int(mix_mode),
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
def set_replaygain(self, mode: int, preamp_db: float, prevent_clipping: bool) -> None:
|
|
126
|
+
"""mode: :class:`rockbox_ffi.enums.ReplayGainMode` (OFF=0, TRACK=1, ALBUM=2)."""
|
|
127
|
+
lib.rb_player_set_replaygain(self._p, int(mode), float(preamp_db), bool(prevent_clipping))
|
|
128
|
+
|
|
129
|
+
# -- status -----------------------------------------------------------
|
|
130
|
+
def status(self) -> dict:
|
|
131
|
+
s = take_string(lib.rb_player_status_json(self._p))
|
|
132
|
+
if s is None:
|
|
133
|
+
raise RuntimeError("rb_player_status_json returned NULL")
|
|
134
|
+
return json.loads(s)
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
version = 1
|
|
2
|
+
revision = 3
|
|
3
|
+
requires-python = ">=3.9"
|
|
4
|
+
resolution-markers = [
|
|
5
|
+
"python_full_version >= '3.10'",
|
|
6
|
+
"python_full_version < '3.10'",
|
|
7
|
+
]
|
|
8
|
+
|
|
9
|
+
[[package]]
|
|
10
|
+
name = "cffi"
|
|
11
|
+
version = "2.0.0"
|
|
12
|
+
source = { registry = "https://pypi.org/simple" }
|
|
13
|
+
resolution-markers = [
|
|
14
|
+
"python_full_version < '3.10'",
|
|
15
|
+
]
|
|
16
|
+
dependencies = [
|
|
17
|
+
{ name = "pycparser", version = "2.23", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' and implementation_name != 'PyPy'" },
|
|
18
|
+
]
|
|
19
|
+
sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" }
|
|
20
|
+
wheels = [
|
|
21
|
+
{ url = "https://files.pythonhosted.org/packages/93/d7/516d984057745a6cd96575eea814fe1edd6646ee6efd552fb7b0921dec83/cffi-2.0.0-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:0cf2d91ecc3fcc0625c2c530fe004f82c110405f101548512cce44322fa8ac44", size = 184283, upload-time = "2025-09-08T23:22:08.01Z" },
|
|
22
|
+
{ url = "https://files.pythonhosted.org/packages/9e/84/ad6a0b408daa859246f57c03efd28e5dd1b33c21737c2db84cae8c237aa5/cffi-2.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f73b96c41e3b2adedc34a7356e64c8eb96e03a3782b535e043a986276ce12a49", size = 180504, upload-time = "2025-09-08T23:22:10.637Z" },
|
|
23
|
+
{ url = "https://files.pythonhosted.org/packages/50/bd/b1a6362b80628111e6653c961f987faa55262b4002fcec42308cad1db680/cffi-2.0.0-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:53f77cbe57044e88bbd5ed26ac1d0514d2acf0591dd6bb02a3ae37f76811b80c", size = 208811, upload-time = "2025-09-08T23:22:12.267Z" },
|
|
24
|
+
{ url = "https://files.pythonhosted.org/packages/4f/27/6933a8b2562d7bd1fb595074cf99cc81fc3789f6a6c05cdabb46284a3188/cffi-2.0.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3e837e369566884707ddaf85fc1744b47575005c0a229de3327f8f9a20f4efeb", size = 216402, upload-time = "2025-09-08T23:22:13.455Z" },
|
|
25
|
+
{ url = "https://files.pythonhosted.org/packages/05/eb/b86f2a2645b62adcfff53b0dd97e8dfafb5c8aa864bd0d9a2c2049a0d551/cffi-2.0.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:5eda85d6d1879e692d546a078b44251cdd08dd1cfb98dfb77b670c97cee49ea0", size = 203217, upload-time = "2025-09-08T23:22:14.596Z" },
|
|
26
|
+
{ url = "https://files.pythonhosted.org/packages/9f/e0/6cbe77a53acf5acc7c08cc186c9928864bd7c005f9efd0d126884858a5fe/cffi-2.0.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9332088d75dc3241c702d852d4671613136d90fa6881da7d770a483fd05248b4", size = 203079, upload-time = "2025-09-08T23:22:15.769Z" },
|
|
27
|
+
{ url = "https://files.pythonhosted.org/packages/98/29/9b366e70e243eb3d14a5cb488dfd3a0b6b2f1fb001a203f653b93ccfac88/cffi-2.0.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fc7de24befaeae77ba923797c7c87834c73648a05a4bde34b3b7e5588973a453", size = 216475, upload-time = "2025-09-08T23:22:17.427Z" },
|
|
28
|
+
{ url = "https://files.pythonhosted.org/packages/21/7a/13b24e70d2f90a322f2900c5d8e1f14fa7e2a6b3332b7309ba7b2ba51a5a/cffi-2.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cf364028c016c03078a23b503f02058f1814320a56ad535686f90565636a9495", size = 218829, upload-time = "2025-09-08T23:22:19.069Z" },
|
|
29
|
+
{ url = "https://files.pythonhosted.org/packages/60/99/c9dc110974c59cc981b1f5b66e1d8af8af764e00f0293266824d9c4254bc/cffi-2.0.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e11e82b744887154b182fd3e7e8512418446501191994dbf9c9fc1f32cc8efd5", size = 211211, upload-time = "2025-09-08T23:22:20.588Z" },
|
|
30
|
+
{ url = "https://files.pythonhosted.org/packages/49/72/ff2d12dbf21aca1b32a40ed792ee6b40f6dc3a9cf1644bd7ef6e95e0ac5e/cffi-2.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8ea985900c5c95ce9db1745f7933eeef5d314f0565b27625d9a10ec9881e1bfb", size = 218036, upload-time = "2025-09-08T23:22:22.143Z" },
|
|
31
|
+
{ url = "https://files.pythonhosted.org/packages/e2/cc/027d7fb82e58c48ea717149b03bcadcbdc293553edb283af792bd4bcbb3f/cffi-2.0.0-cp310-cp310-win32.whl", hash = "sha256:1f72fb8906754ac8a2cc3f9f5aaa298070652a0ffae577e0ea9bd480dc3c931a", size = 172184, upload-time = "2025-09-08T23:22:23.328Z" },
|
|
32
|
+
{ url = "https://files.pythonhosted.org/packages/33/fa/072dd15ae27fbb4e06b437eb6e944e75b068deb09e2a2826039e49ee2045/cffi-2.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:b18a3ed7d5b3bd8d9ef7a8cb226502c6bf8308df1525e1cc676c3680e7176739", size = 182790, upload-time = "2025-09-08T23:22:24.752Z" },
|
|
33
|
+
{ url = "https://files.pythonhosted.org/packages/12/4a/3dfd5f7850cbf0d06dc84ba9aa00db766b52ca38d8b86e3a38314d52498c/cffi-2.0.0-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:b4c854ef3adc177950a8dfc81a86f5115d2abd545751a304c5bcf2c2c7283cfe", size = 184344, upload-time = "2025-09-08T23:22:26.456Z" },
|
|
34
|
+
{ url = "https://files.pythonhosted.org/packages/4f/8b/f0e4c441227ba756aafbe78f117485b25bb26b1c059d01f137fa6d14896b/cffi-2.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2de9a304e27f7596cd03d16f1b7c72219bd944e99cc52b84d0145aefb07cbd3c", size = 180560, upload-time = "2025-09-08T23:22:28.197Z" },
|
|
35
|
+
{ url = "https://files.pythonhosted.org/packages/b1/b7/1200d354378ef52ec227395d95c2576330fd22a869f7a70e88e1447eb234/cffi-2.0.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:baf5215e0ab74c16e2dd324e8ec067ef59e41125d3eade2b863d294fd5035c92", size = 209613, upload-time = "2025-09-08T23:22:29.475Z" },
|
|
36
|
+
{ url = "https://files.pythonhosted.org/packages/b8/56/6033f5e86e8cc9bb629f0077ba71679508bdf54a9a5e112a3c0b91870332/cffi-2.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:730cacb21e1bdff3ce90babf007d0a0917cc3e6492f336c2f0134101e0944f93", size = 216476, upload-time = "2025-09-08T23:22:31.063Z" },
|
|
37
|
+
{ url = "https://files.pythonhosted.org/packages/dc/7f/55fecd70f7ece178db2f26128ec41430d8720f2d12ca97bf8f0a628207d5/cffi-2.0.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:6824f87845e3396029f3820c206e459ccc91760e8fa24422f8b0c3d1731cbec5", size = 203374, upload-time = "2025-09-08T23:22:32.507Z" },
|
|
38
|
+
{ url = "https://files.pythonhosted.org/packages/84/ef/a7b77c8bdc0f77adc3b46888f1ad54be8f3b7821697a7b89126e829e676a/cffi-2.0.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9de40a7b0323d889cf8d23d1ef214f565ab154443c42737dfe52ff82cf857664", size = 202597, upload-time = "2025-09-08T23:22:34.132Z" },
|
|
39
|
+
{ url = "https://files.pythonhosted.org/packages/d7/91/500d892b2bf36529a75b77958edfcd5ad8e2ce4064ce2ecfeab2125d72d1/cffi-2.0.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8941aaadaf67246224cee8c3803777eed332a19d909b47e29c9842ef1e79ac26", size = 215574, upload-time = "2025-09-08T23:22:35.443Z" },
|
|
40
|
+
{ url = "https://files.pythonhosted.org/packages/44/64/58f6255b62b101093d5df22dcb752596066c7e89dd725e0afaed242a61be/cffi-2.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a05d0c237b3349096d3981b727493e22147f934b20f6f125a3eba8f994bec4a9", size = 218971, upload-time = "2025-09-08T23:22:36.805Z" },
|
|
41
|
+
{ url = "https://files.pythonhosted.org/packages/ab/49/fa72cebe2fd8a55fbe14956f9970fe8eb1ac59e5df042f603ef7c8ba0adc/cffi-2.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:94698a9c5f91f9d138526b48fe26a199609544591f859c870d477351dc7b2414", size = 211972, upload-time = "2025-09-08T23:22:38.436Z" },
|
|
42
|
+
{ url = "https://files.pythonhosted.org/packages/0b/28/dd0967a76aab36731b6ebfe64dec4e981aff7e0608f60c2d46b46982607d/cffi-2.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5fed36fccc0612a53f1d4d9a816b50a36702c28a2aa880cb8a122b3466638743", size = 217078, upload-time = "2025-09-08T23:22:39.776Z" },
|
|
43
|
+
{ url = "https://files.pythonhosted.org/packages/2b/c0/015b25184413d7ab0a410775fdb4a50fca20f5589b5dab1dbbfa3baad8ce/cffi-2.0.0-cp311-cp311-win32.whl", hash = "sha256:c649e3a33450ec82378822b3dad03cc228b8f5963c0c12fc3b1e0ab940f768a5", size = 172076, upload-time = "2025-09-08T23:22:40.95Z" },
|
|
44
|
+
{ url = "https://files.pythonhosted.org/packages/ae/8f/dc5531155e7070361eb1b7e4c1a9d896d0cb21c49f807a6c03fd63fc877e/cffi-2.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:66f011380d0e49ed280c789fbd08ff0d40968ee7b665575489afa95c98196ab5", size = 182820, upload-time = "2025-09-08T23:22:42.463Z" },
|
|
45
|
+
{ url = "https://files.pythonhosted.org/packages/95/5c/1b493356429f9aecfd56bc171285a4c4ac8697f76e9bbbbb105e537853a1/cffi-2.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:c6638687455baf640e37344fe26d37c404db8b80d037c3d29f58fe8d1c3b194d", size = 177635, upload-time = "2025-09-08T23:22:43.623Z" },
|
|
46
|
+
{ url = "https://files.pythonhosted.org/packages/ea/47/4f61023ea636104d4f16ab488e268b93008c3d0bb76893b1b31db1f96802/cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d", size = 185271, upload-time = "2025-09-08T23:22:44.795Z" },
|
|
47
|
+
{ url = "https://files.pythonhosted.org/packages/df/a2/781b623f57358e360d62cdd7a8c681f074a71d445418a776eef0aadb4ab4/cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c", size = 181048, upload-time = "2025-09-08T23:22:45.938Z" },
|
|
48
|
+
{ url = "https://files.pythonhosted.org/packages/ff/df/a4f0fbd47331ceeba3d37c2e51e9dfc9722498becbeec2bd8bc856c9538a/cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe", size = 212529, upload-time = "2025-09-08T23:22:47.349Z" },
|
|
49
|
+
{ url = "https://files.pythonhosted.org/packages/d5/72/12b5f8d3865bf0f87cf1404d8c374e7487dcf097a1c91c436e72e6badd83/cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062", size = 220097, upload-time = "2025-09-08T23:22:48.677Z" },
|
|
50
|
+
{ url = "https://files.pythonhosted.org/packages/c2/95/7a135d52a50dfa7c882ab0ac17e8dc11cec9d55d2c18dda414c051c5e69e/cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e", size = 207983, upload-time = "2025-09-08T23:22:50.06Z" },
|
|
51
|
+
{ url = "https://files.pythonhosted.org/packages/3a/c8/15cb9ada8895957ea171c62dc78ff3e99159ee7adb13c0123c001a2546c1/cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037", size = 206519, upload-time = "2025-09-08T23:22:51.364Z" },
|
|
52
|
+
{ url = "https://files.pythonhosted.org/packages/78/2d/7fa73dfa841b5ac06c7b8855cfc18622132e365f5b81d02230333ff26e9e/cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba", size = 219572, upload-time = "2025-09-08T23:22:52.902Z" },
|
|
53
|
+
{ url = "https://files.pythonhosted.org/packages/07/e0/267e57e387b4ca276b90f0434ff88b2c2241ad72b16d31836adddfd6031b/cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94", size = 222963, upload-time = "2025-09-08T23:22:54.518Z" },
|
|
54
|
+
{ url = "https://files.pythonhosted.org/packages/b6/75/1f2747525e06f53efbd878f4d03bac5b859cbc11c633d0fb81432d98a795/cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187", size = 221361, upload-time = "2025-09-08T23:22:55.867Z" },
|
|
55
|
+
{ url = "https://files.pythonhosted.org/packages/7b/2b/2b6435f76bfeb6bbf055596976da087377ede68df465419d192acf00c437/cffi-2.0.0-cp312-cp312-win32.whl", hash = "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18", size = 172932, upload-time = "2025-09-08T23:22:57.188Z" },
|
|
56
|
+
{ url = "https://files.pythonhosted.org/packages/f8/ed/13bd4418627013bec4ed6e54283b1959cf6db888048c7cf4b4c3b5b36002/cffi-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5", size = 183557, upload-time = "2025-09-08T23:22:58.351Z" },
|
|
57
|
+
{ url = "https://files.pythonhosted.org/packages/95/31/9f7f93ad2f8eff1dbc1c3656d7ca5bfd8fb52c9d786b4dcf19b2d02217fa/cffi-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6", size = 177762, upload-time = "2025-09-08T23:22:59.668Z" },
|
|
58
|
+
{ url = "https://files.pythonhosted.org/packages/4b/8d/a0a47a0c9e413a658623d014e91e74a50cdd2c423f7ccfd44086ef767f90/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb", size = 185230, upload-time = "2025-09-08T23:23:00.879Z" },
|
|
59
|
+
{ url = "https://files.pythonhosted.org/packages/4a/d2/a6c0296814556c68ee32009d9c2ad4f85f2707cdecfd7727951ec228005d/cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca", size = 181043, upload-time = "2025-09-08T23:23:02.231Z" },
|
|
60
|
+
{ url = "https://files.pythonhosted.org/packages/b0/1e/d22cc63332bd59b06481ceaac49d6c507598642e2230f201649058a7e704/cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b", size = 212446, upload-time = "2025-09-08T23:23:03.472Z" },
|
|
61
|
+
{ url = "https://files.pythonhosted.org/packages/a9/f5/a2c23eb03b61a0b8747f211eb716446c826ad66818ddc7810cc2cc19b3f2/cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b", size = 220101, upload-time = "2025-09-08T23:23:04.792Z" },
|
|
62
|
+
{ url = "https://files.pythonhosted.org/packages/f2/7f/e6647792fc5850d634695bc0e6ab4111ae88e89981d35ac269956605feba/cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2", size = 207948, upload-time = "2025-09-08T23:23:06.127Z" },
|
|
63
|
+
{ url = "https://files.pythonhosted.org/packages/cb/1e/a5a1bd6f1fb30f22573f76533de12a00bf274abcdc55c8edab639078abb6/cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3", size = 206422, upload-time = "2025-09-08T23:23:07.753Z" },
|
|
64
|
+
{ url = "https://files.pythonhosted.org/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26", size = 219499, upload-time = "2025-09-08T23:23:09.648Z" },
|
|
65
|
+
{ url = "https://files.pythonhosted.org/packages/50/e1/a969e687fcf9ea58e6e2a928ad5e2dd88cc12f6f0ab477e9971f2309b57c/cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c", size = 222928, upload-time = "2025-09-08T23:23:10.928Z" },
|
|
66
|
+
{ url = "https://files.pythonhosted.org/packages/36/54/0362578dd2c9e557a28ac77698ed67323ed5b9775ca9d3fe73fe191bb5d8/cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b", size = 221302, upload-time = "2025-09-08T23:23:12.42Z" },
|
|
67
|
+
{ url = "https://files.pythonhosted.org/packages/eb/6d/bf9bda840d5f1dfdbf0feca87fbdb64a918a69bca42cfa0ba7b137c48cb8/cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27", size = 172909, upload-time = "2025-09-08T23:23:14.32Z" },
|
|
68
|
+
{ url = "https://files.pythonhosted.org/packages/37/18/6519e1ee6f5a1e579e04b9ddb6f1676c17368a7aba48299c3759bbc3c8b3/cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75", size = 183402, upload-time = "2025-09-08T23:23:15.535Z" },
|
|
69
|
+
{ url = "https://files.pythonhosted.org/packages/cb/0e/02ceeec9a7d6ee63bb596121c2c8e9b3a9e150936f4fbef6ca1943e6137c/cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91", size = 177780, upload-time = "2025-09-08T23:23:16.761Z" },
|
|
70
|
+
{ url = "https://files.pythonhosted.org/packages/92/c4/3ce07396253a83250ee98564f8d7e9789fab8e58858f35d07a9a2c78de9f/cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5", size = 185320, upload-time = "2025-09-08T23:23:18.087Z" },
|
|
71
|
+
{ url = "https://files.pythonhosted.org/packages/59/dd/27e9fa567a23931c838c6b02d0764611c62290062a6d4e8ff7863daf9730/cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13", size = 181487, upload-time = "2025-09-08T23:23:19.622Z" },
|
|
72
|
+
{ url = "https://files.pythonhosted.org/packages/d6/43/0e822876f87ea8a4ef95442c3d766a06a51fc5298823f884ef87aaad168c/cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b", size = 220049, upload-time = "2025-09-08T23:23:20.853Z" },
|
|
73
|
+
{ url = "https://files.pythonhosted.org/packages/b4/89/76799151d9c2d2d1ead63c2429da9ea9d7aac304603de0c6e8764e6e8e70/cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c", size = 207793, upload-time = "2025-09-08T23:23:22.08Z" },
|
|
74
|
+
{ url = "https://files.pythonhosted.org/packages/bb/dd/3465b14bb9e24ee24cb88c9e3730f6de63111fffe513492bf8c808a3547e/cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef", size = 206300, upload-time = "2025-09-08T23:23:23.314Z" },
|
|
75
|
+
{ url = "https://files.pythonhosted.org/packages/47/d9/d83e293854571c877a92da46fdec39158f8d7e68da75bf73581225d28e90/cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775", size = 219244, upload-time = "2025-09-08T23:23:24.541Z" },
|
|
76
|
+
{ url = "https://files.pythonhosted.org/packages/2b/0f/1f177e3683aead2bb00f7679a16451d302c436b5cbf2505f0ea8146ef59e/cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205", size = 222828, upload-time = "2025-09-08T23:23:26.143Z" },
|
|
77
|
+
{ url = "https://files.pythonhosted.org/packages/c6/0f/cafacebd4b040e3119dcb32fed8bdef8dfe94da653155f9d0b9dc660166e/cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1", size = 220926, upload-time = "2025-09-08T23:23:27.873Z" },
|
|
78
|
+
{ url = "https://files.pythonhosted.org/packages/3e/aa/df335faa45b395396fcbc03de2dfcab242cd61a9900e914fe682a59170b1/cffi-2.0.0-cp314-cp314-win32.whl", hash = "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f", size = 175328, upload-time = "2025-09-08T23:23:44.61Z" },
|
|
79
|
+
{ url = "https://files.pythonhosted.org/packages/bb/92/882c2d30831744296ce713f0feb4c1cd30f346ef747b530b5318715cc367/cffi-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25", size = 185650, upload-time = "2025-09-08T23:23:45.848Z" },
|
|
80
|
+
{ url = "https://files.pythonhosted.org/packages/9f/2c/98ece204b9d35a7366b5b2c6539c350313ca13932143e79dc133ba757104/cffi-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad", size = 180687, upload-time = "2025-09-08T23:23:47.105Z" },
|
|
81
|
+
{ url = "https://files.pythonhosted.org/packages/3e/61/c768e4d548bfa607abcda77423448df8c471f25dbe64fb2ef6d555eae006/cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9", size = 188773, upload-time = "2025-09-08T23:23:29.347Z" },
|
|
82
|
+
{ url = "https://files.pythonhosted.org/packages/2c/ea/5f76bce7cf6fcd0ab1a1058b5af899bfbef198bea4d5686da88471ea0336/cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d", size = 185013, upload-time = "2025-09-08T23:23:30.63Z" },
|
|
83
|
+
{ url = "https://files.pythonhosted.org/packages/be/b4/c56878d0d1755cf9caa54ba71e5d049479c52f9e4afc230f06822162ab2f/cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c", size = 221593, upload-time = "2025-09-08T23:23:31.91Z" },
|
|
84
|
+
{ url = "https://files.pythonhosted.org/packages/e0/0d/eb704606dfe8033e7128df5e90fee946bbcb64a04fcdaa97321309004000/cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8", size = 209354, upload-time = "2025-09-08T23:23:33.214Z" },
|
|
85
|
+
{ url = "https://files.pythonhosted.org/packages/d8/19/3c435d727b368ca475fb8742ab97c9cb13a0de600ce86f62eab7fa3eea60/cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc", size = 208480, upload-time = "2025-09-08T23:23:34.495Z" },
|
|
86
|
+
{ url = "https://files.pythonhosted.org/packages/d0/44/681604464ed9541673e486521497406fadcc15b5217c3e326b061696899a/cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592", size = 221584, upload-time = "2025-09-08T23:23:36.096Z" },
|
|
87
|
+
{ url = "https://files.pythonhosted.org/packages/25/8e/342a504ff018a2825d395d44d63a767dd8ebc927ebda557fecdaca3ac33a/cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512", size = 224443, upload-time = "2025-09-08T23:23:37.328Z" },
|
|
88
|
+
{ url = "https://files.pythonhosted.org/packages/e1/5e/b666bacbbc60fbf415ba9988324a132c9a7a0448a9a8f125074671c0f2c3/cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4", size = 223437, upload-time = "2025-09-08T23:23:38.945Z" },
|
|
89
|
+
{ url = "https://files.pythonhosted.org/packages/a0/1d/ec1a60bd1a10daa292d3cd6bb0b359a81607154fb8165f3ec95fe003b85c/cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e", size = 180487, upload-time = "2025-09-08T23:23:40.423Z" },
|
|
90
|
+
{ url = "https://files.pythonhosted.org/packages/bf/41/4c1168c74fac325c0c8156f04b6749c8b6a8f405bbf91413ba088359f60d/cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6", size = 191726, upload-time = "2025-09-08T23:23:41.742Z" },
|
|
91
|
+
{ url = "https://files.pythonhosted.org/packages/ae/3a/dbeec9d1ee0844c679f6bb5d6ad4e9f198b1224f4e7a32825f47f6192b0c/cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9", size = 184195, upload-time = "2025-09-08T23:23:43.004Z" },
|
|
92
|
+
{ url = "https://files.pythonhosted.org/packages/c0/cc/08ed5a43f2996a16b462f64a7055c6e962803534924b9b2f1371d8c00b7b/cffi-2.0.0-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:fe562eb1a64e67dd297ccc4f5addea2501664954f2692b69a76449ec7913ecbf", size = 184288, upload-time = "2025-09-08T23:23:48.404Z" },
|
|
93
|
+
{ url = "https://files.pythonhosted.org/packages/3d/de/38d9726324e127f727b4ecc376bc85e505bfe61ef130eaf3f290c6847dd4/cffi-2.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:de8dad4425a6ca6e4e5e297b27b5c824ecc7581910bf9aee86cb6835e6812aa7", size = 180509, upload-time = "2025-09-08T23:23:49.73Z" },
|
|
94
|
+
{ url = "https://files.pythonhosted.org/packages/9b/13/c92e36358fbcc39cf0962e83223c9522154ee8630e1df7c0b3a39a8124e2/cffi-2.0.0-cp39-cp39-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:4647afc2f90d1ddd33441e5b0e85b16b12ddec4fca55f0d9671fef036ecca27c", size = 208813, upload-time = "2025-09-08T23:23:51.263Z" },
|
|
95
|
+
{ url = "https://files.pythonhosted.org/packages/15/12/a7a79bd0df4c3bff744b2d7e52cc1b68d5e7e427b384252c42366dc1ecbc/cffi-2.0.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3f4d46d8b35698056ec29bca21546e1551a205058ae1a181d871e278b0b28165", size = 216498, upload-time = "2025-09-08T23:23:52.494Z" },
|
|
96
|
+
{ url = "https://files.pythonhosted.org/packages/a3/ad/5c51c1c7600bdd7ed9a24a203ec255dccdd0ebf4527f7b922a0bde2fb6ed/cffi-2.0.0-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:e6e73b9e02893c764e7e8d5bb5ce277f1a009cd5243f8228f75f842bf937c534", size = 203243, upload-time = "2025-09-08T23:23:53.836Z" },
|
|
97
|
+
{ url = "https://files.pythonhosted.org/packages/32/f2/81b63e288295928739d715d00952c8c6034cb6c6a516b17d37e0c8be5600/cffi-2.0.0-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:cb527a79772e5ef98fb1d700678fe031e353e765d1ca2d409c92263c6d43e09f", size = 203158, upload-time = "2025-09-08T23:23:55.169Z" },
|
|
98
|
+
{ url = "https://files.pythonhosted.org/packages/1f/74/cc4096ce66f5939042ae094e2e96f53426a979864aa1f96a621ad128be27/cffi-2.0.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:61d028e90346df14fedc3d1e5441df818d095f3b87d286825dfcbd6459b7ef63", size = 216548, upload-time = "2025-09-08T23:23:56.506Z" },
|
|
99
|
+
{ url = "https://files.pythonhosted.org/packages/e8/be/f6424d1dc46b1091ffcc8964fa7c0ab0cd36839dd2761b49c90481a6ba1b/cffi-2.0.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0f6084a0ea23d05d20c3edcda20c3d006f9b6f3fefeac38f59262e10cef47ee2", size = 218897, upload-time = "2025-09-08T23:23:57.825Z" },
|
|
100
|
+
{ url = "https://files.pythonhosted.org/packages/f7/e0/dda537c2309817edf60109e39265f24f24aa7f050767e22c98c53fe7f48b/cffi-2.0.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1cd13c99ce269b3ed80b417dcd591415d3372bcac067009b6e0f59c7d4015e65", size = 211249, upload-time = "2025-09-08T23:23:59.139Z" },
|
|
101
|
+
{ url = "https://files.pythonhosted.org/packages/2b/e7/7c769804eb75e4c4b35e658dba01de1640a351a9653c3d49ca89d16ccc91/cffi-2.0.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:89472c9762729b5ae1ad974b777416bfda4ac5642423fa93bd57a09204712322", size = 218041, upload-time = "2025-09-08T23:24:00.496Z" },
|
|
102
|
+
{ url = "https://files.pythonhosted.org/packages/aa/d9/6218d78f920dcd7507fc16a766b5ef8f3b913cc7aa938e7fc80b9978d089/cffi-2.0.0-cp39-cp39-win32.whl", hash = "sha256:2081580ebb843f759b9f617314a24ed5738c51d2aee65d31e02f6f7a2b97707a", size = 172138, upload-time = "2025-09-08T23:24:01.7Z" },
|
|
103
|
+
{ url = "https://files.pythonhosted.org/packages/54/8f/a1e836f82d8e32a97e6b29cc8f641779181ac7363734f12df27db803ebda/cffi-2.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:b882b3df248017dba09d6b16defe9b5c407fe32fc7c65a9c69798e6175601be9", size = 182794, upload-time = "2025-09-08T23:24:02.943Z" },
|
|
104
|
+
]
|
|
105
|
+
|
|
106
|
+
[[package]]
|
|
107
|
+
name = "cffi"
|
|
108
|
+
version = "2.1.0"
|
|
109
|
+
source = { registry = "https://pypi.org/simple" }
|
|
110
|
+
resolution-markers = [
|
|
111
|
+
"python_full_version >= '3.10'",
|
|
112
|
+
]
|
|
113
|
+
dependencies = [
|
|
114
|
+
{ name = "pycparser", version = "3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' and implementation_name != 'PyPy'" },
|
|
115
|
+
]
|
|
116
|
+
sdist = { url = "https://files.pythonhosted.org/packages/57/5f/ff100cae70ebe9d8df1c01a00e510e45d9adb5c1fdda84791b199141de97/cffi-2.1.0.tar.gz", hash = "sha256:efc1cdd798b1aaf39b4610bba7aad28c9bea9b910f25c784ccf9ec1fa719d1f9", size = 531036, upload-time = "2026-07-06T21:34:30.382Z" }
|
|
117
|
+
wheels = [
|
|
118
|
+
{ url = "https://files.pythonhosted.org/packages/c0/e9/6d7724983b3d5a0908dbf74f64038ade77c18646ff6636ec7894fd392ce1/cffi-2.1.0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:b65f590ef2a44640f9a05dbb548a429b4ade77913ce683ac8b1480777658a6c0", size = 183837, upload-time = "2026-07-06T21:32:09.655Z" },
|
|
119
|
+
{ url = "https://files.pythonhosted.org/packages/69/aa/24580a278de21fd7322635556334d9b535f1cbc00b0a3919447cdf464c65/cffi-2.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:164bff1657b2a74f0b6d54e11c9b375bc97b931f2ca9c43fcf875838da1570dd", size = 184226, upload-time = "2026-07-06T21:32:11.196Z" },
|
|
120
|
+
{ url = "https://files.pythonhosted.org/packages/88/a9/02cae418ec4beb282ace11958d9d4737793439d561fadc7e6d56f2e2b354/cffi-2.1.0-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:c941bb58d5a6e1c3892d86e42927ed6c180302f07e6d395d08c416e594b98b46", size = 211107, upload-time = "2026-07-06T21:32:12.328Z" },
|
|
121
|
+
{ url = "https://files.pythonhosted.org/packages/3b/30/c806937ed5e4c2c7ac30d9d6b76b5dc57ff8b75d83800d9bb11a8253cf2a/cffi-2.1.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a016194dbe13d14ee9556e734b772d8d67b947092b268d757fd4290e3ba2dfc2", size = 218733, upload-time = "2026-07-06T21:32:13.67Z" },
|
|
122
|
+
{ url = "https://files.pythonhosted.org/packages/f9/cf/398272b8bbfd58aa314fda5a7f1cdbb26d1d78ae324a11211521315dd1f0/cffi-2.1.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:03e9810d18c646077e501f661b682fbf5dee4676048527ca3cffe66faa9960dd", size = 205543, upload-time = "2026-07-06T21:32:15.148Z" },
|
|
123
|
+
{ url = "https://files.pythonhosted.org/packages/45/ca/f91641185cdd90c36d317a9dc7f85e88ef8682d8b300977baff5e23c35d8/cffi-2.1.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:19c54ac121cad98450b4896fa9a43ee0180d57bc4bc911a33db6cab1efab6cd3", size = 205460, upload-time = "2026-07-06T21:32:16.479Z" },
|
|
124
|
+
{ url = "https://files.pythonhosted.org/packages/38/66/04781a77b411f0bb5b234d62c1814754ab75ebe455ccff1b08e8d7aae98f/cffi-2.1.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4d433a51f1870e43a13b6732f92aaf540ff77c2015097c78556f75a2d6c030e0", size = 218760, upload-time = "2026-07-06T21:32:17.98Z" },
|
|
125
|
+
{ url = "https://files.pythonhosted.org/packages/d0/9a/bb1d5ed9c3fcae158e9f6391bf309c95d98c2ac37ed56573228471d0af5e/cffi-2.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3d7f118b5adbfdfead90c25822690b02bc8074fba949bb7858bec4ebd55adb43", size = 221230, upload-time = "2026-07-06T21:32:19.407Z" },
|
|
126
|
+
{ url = "https://files.pythonhosted.org/packages/41/aa/3c1409cdd26094efacd1c36c66e0a6eb9d4296e4fd4f9901b8b2042f4323/cffi-2.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:c5f5df567f6eb216de69be06ce55c8b714090fae02b18a3b40da8163b8c5fa9c", size = 213524, upload-time = "2026-07-06T21:32:20.828Z" },
|
|
127
|
+
{ url = "https://files.pythonhosted.org/packages/fa/75/74dfb7c3fc6ebbd408038476bd4c1d7e925c62614e7b9c534ecc34218288/cffi-2.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:11b3fb55f4f8ad92274ed26705f65d8f91457de71f5380061eb6d125a768fecd", size = 220341, upload-time = "2026-07-06T21:32:21.9Z" },
|
|
128
|
+
{ url = "https://files.pythonhosted.org/packages/70/b6/9003c33a3e7d2c1306f5962e646457dcfe5a8cd8fce6bbe02d7af25db783/cffi-2.1.0-cp310-cp310-win32.whl", hash = "sha256:9d72af0cf10a76a600a9690078fe31c63b9588c8e86bf9fd353f713c84b5db0f", size = 174578, upload-time = "2026-07-06T21:32:23.073Z" },
|
|
129
|
+
{ url = "https://files.pythonhosted.org/packages/8a/26/710688310447531c7a22f857c7f79d9855ec18b03e04494ced723fb37e2f/cffi-2.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:fb62edb5bb52cca65fab91a63afa7561607120d26090a7e8fda6fb9f064726da", size = 185071, upload-time = "2026-07-06T21:32:24.671Z" },
|
|
130
|
+
{ url = "https://files.pythonhosted.org/packages/d3/67/85c89a59ba36a671e79638f44d466749f08179266a57e4f2ffdf92174072/cffi-2.1.0-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:02cb7ff33ded4f1532476731f89ede53e2e488a8e6205515a82144246ffa7dcc", size = 183845, upload-time = "2026-07-06T21:32:26.32Z" },
|
|
131
|
+
{ url = "https://files.pythonhosted.org/packages/ea/dd/e3b0baa2d3d6a857ac72b7efbf18e32e487c9cdafcc13049ad765495b15e/cffi-2.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f5bce581e6b8c235e566a14768a943b172ada3ed73537bb0c0be1edee312d4e7", size = 184186, upload-time = "2026-07-06T21:32:28.025Z" },
|
|
132
|
+
{ url = "https://files.pythonhosted.org/packages/65/68/9f3ef890cf3c6ab97bd531c5677f67613d302165d16f8142b2811782a614/cffi-2.1.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:30b65779d598c370374fefabf138d456fd6f3216bfa7bedfab1ba82025b0cd93", size = 211892, upload-time = "2026-07-06T21:32:29.565Z" },
|
|
133
|
+
{ url = "https://files.pythonhosted.org/packages/22/d7/1a74539db16d8bfd839ff1515948948efbb162e574650fd3d846896eea95/cffi-2.1.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:88023dfe18799507b73f1dbb0d14326a17465de1bc9c9c7655c22845e9ddc3a2", size = 218793, upload-time = "2026-07-06T21:32:30.951Z" },
|
|
134
|
+
{ url = "https://files.pythonhosted.org/packages/ec/d1/9a5b7169499e8e8d8e636de70b97ac7c9447104d2ff1a2cd94790cea5162/cffi-2.1.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:0a96b74cda968eebbad56d973efe5098974f0a9fb323865bf99ea1fd24e3e64c", size = 205737, upload-time = "2026-07-06T21:32:32.216Z" },
|
|
135
|
+
{ url = "https://files.pythonhosted.org/packages/ba/b0/e131a9c41f10607926278453d9596163594fe1c4ebc46efe3b5e5b34eb84/cffi-2.1.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:a5781494d4d400a3f47f8f1da94b324f6e6b440a53387774002890a2a2f4b50f", size = 204909, upload-time = "2026-07-06T21:32:33.655Z" },
|
|
136
|
+
{ url = "https://files.pythonhosted.org/packages/fb/d2/4398416cd699b35167947c6e22aca52c47e69ad5695073c9f1f2c52e04aa/cffi-2.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:aa7a1b53a2a4452ada2d1b5dade9960b2522f1e61293a811a077439e39029565", size = 217883, upload-time = "2026-07-06T21:32:35.173Z" },
|
|
137
|
+
{ url = "https://files.pythonhosted.org/packages/a2/a5/d4fe77b589e5e82d43ebc809bf2e6474afe8e48e32ea050b9357645b6471/cffi-2.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9d8272c0e483b024e1b9ad029821470ed8ec65631dbd90217469da0e7cd89f1c", size = 221251, upload-time = "2026-07-06T21:32:36.527Z" },
|
|
138
|
+
{ url = "https://files.pythonhosted.org/packages/22/f0/a2fc43084c0433caf7f461bccc013e28f848d04ee1c5ed7fce71423cf4d9/cffi-2.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7762faa47e8ff7eb80bd261d9a7d8eea2d8baa69de5e95b70c1f338bbe712f02", size = 214250, upload-time = "2026-07-06T21:32:37.852Z" },
|
|
139
|
+
{ url = "https://files.pythonhosted.org/packages/04/8c/b925975448cf20634a9fbd5efceb807219db452653648d2897c0989cab2d/cffi-2.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:89095c1968b4ba8285840e131bf2891b09ae137fe2146905acae0354fbce1b5e", size = 219441, upload-time = "2026-07-06T21:32:39.146Z" },
|
|
140
|
+
{ url = "https://files.pythonhosted.org/packages/eb/da/5c4918a2d61d86fa927d716cb3d8e4626ef8dc8f605a599d32f33897f59a/cffi-2.1.0-cp311-cp311-win32.whl", hash = "sha256:64c753a0f87a256020004f37a1c8c02c480e725f910f0b2a0f3f07debd1b2479", size = 174496, upload-time = "2026-07-06T21:32:40.467Z" },
|
|
141
|
+
{ url = "https://files.pythonhosted.org/packages/f9/c8/6c2de1d55cf35ef8b92885d5ef280790f0fb9634d87ea1cc315176aecd61/cffi-2.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:4f26194e3d95e06501b942642855aed4f953d55e95d7d01b7c4483db3ecff458", size = 185113, upload-time = "2026-07-06T21:32:41.761Z" },
|
|
142
|
+
{ url = "https://files.pythonhosted.org/packages/9e/4e/e8d7cb5783f1841a3c8fb3a7735838d7484d08ec08c9f984b14cac1ac0e9/cffi-2.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:35aaea0c7ee0e58a5cd8c2fd1a48fdf7ece0d2699b7ecdda08194e9ce5dd9b3d", size = 179927, upload-time = "2026-07-06T21:32:42.961Z" },
|
|
143
|
+
{ url = "https://files.pythonhosted.org/packages/1e/85/990925db5df586ec90beb97529c853497e7f85ba0234830447faf41c3057/cffi-2.1.0-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:df2b82571a1b30f58a87bf4e5a9e78d2b1eff6c6ce8fd3aa3757221f93f0863f", size = 184829, upload-time = "2026-07-06T21:32:44.324Z" },
|
|
144
|
+
{ url = "https://files.pythonhosted.org/packages/4b/92/e7bb136ad6b5352603732cf907ef862ca103f20f2031c1735a46300c20c9/cffi-2.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:78474632761faa0fb96f30b1c928c84ebcf68713cbb80d15bab09dfe61640fde", size = 184728, upload-time = "2026-07-06T21:32:45.683Z" },
|
|
145
|
+
{ url = "https://files.pythonhosted.org/packages/c3/c0/d1ec30ffb370f748f2fb54425972bfef9871e0132e82fb589c46b6676049/cffi-2.1.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:5972433ad71a9e46516584ef60a0fda12d9dc459938d1539c3ddecf9bdc1368d", size = 214815, upload-time = "2026-07-06T21:32:48.557Z" },
|
|
146
|
+
{ url = "https://files.pythonhosted.org/packages/1b/dc/5620cf930688be01f2d673804291de757a934c90b946dbdc3d84130c2ea4/cffi-2.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b6422532152adf4e59b110cb2808cee7a033800952f5c036b4af047ee43199e7", size = 222429, upload-time = "2026-07-06T21:32:49.848Z" },
|
|
147
|
+
{ url = "https://files.pythonhosted.org/packages/4b/a4/77b53abbf7a1e0beb9637edbef2a94d15f9c822f591e85d439ffd91519a6/cffi-2.1.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:46b1c8db8f6122420f32d02fffb924c2fe9bc772d228c7c711748fff56aabb2b", size = 210315, upload-time = "2026-07-06T21:32:51.221Z" },
|
|
148
|
+
{ url = "https://files.pythonhosted.org/packages/58/0c/f528df19cc94b675087324d4760d9e6d5bfae97d6217aa4fac43de4f5fcc/cffi-2.1.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9fafc5aa2e2a39aaf7f8cc0c1f044a9b07fca12e558dca53a3cc5c654ad67a7", size = 208859, upload-time = "2026-07-06T21:32:52.512Z" },
|
|
149
|
+
{ url = "https://files.pythonhosted.org/packages/62/f2/c9522a81c32132799a1972c39f5c5f8b4c8b9f00488a23feaa6c06f07741/cffi-2.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1e9f50d192a3e525b15a75ab5114e442d83d657b7ec29182a991bc9a88fd3a66", size = 221844, upload-time = "2026-07-06T21:32:53.704Z" },
|
|
150
|
+
{ url = "https://files.pythonhosted.org/packages/6e/28/bd53988b9833e8f8ad539d26f4c07a6b3f6bcb1e9e02e7ca038250b3428d/cffi-2.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:98fff996e983a36d3aa2eca83af40c5821202e7e6f32d13ae94e3d2286f10cfe", size = 225287, upload-time = "2026-07-06T21:32:54.907Z" },
|
|
151
|
+
{ url = "https://files.pythonhosted.org/packages/79/99/0d0fd37f055224085f42bbb2c022d002e17dde4a97972822327b07d84101/cffi-2.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:379de10ce1ba048b1448599d1b37b24caee16309d1ac98d3982fc997f768700b", size = 223681, upload-time = "2026-07-06T21:32:56.329Z" },
|
|
152
|
+
{ url = "https://files.pythonhosted.org/packages/b0/80/c138990aa2a70b1a269f6e06348729836d733d6f970867943f61d367f8cc/cffi-2.1.0-cp312-cp312-win32.whl", hash = "sha256:9b8f0f26ca4e7513c534d351eca551947d053fac438f2a04ac96d882909b0d3a", size = 175269, upload-time = "2026-07-06T21:32:57.777Z" },
|
|
153
|
+
{ url = "https://files.pythonhosted.org/packages/a8/eb/f636456ff21a83fc13c032b58cc5dde061691546ac79efa284b2989b7982/cffi-2.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:c97f080ea627e2863524c5af3836e2270b5f5dfff1f104392b959f8df0c5d384", size = 185881, upload-time = "2026-07-06T21:32:59.253Z" },
|
|
154
|
+
{ url = "https://files.pythonhosted.org/packages/dd/2c/400ea43e721727dca8a65c4521390e9196757caba4a45643acb2b63271b8/cffi-2.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:6d194185eabd279f1c05ebe3504265ddfc5ad2b58d0714f7db9f01da592e9eb6", size = 180088, upload-time = "2026-07-06T21:33:02.278Z" },
|
|
155
|
+
{ url = "https://files.pythonhosted.org/packages/96/88/a996879e2eeccb815f6e3a5967b12a308257412acec882039d386bd2aa7b/cffi-2.1.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:10537b1df4967ca26d21e5072d7d54188354483b91dc75058968d3f0cf13fbda", size = 194331, upload-time = "2026-07-06T21:33:03.697Z" },
|
|
156
|
+
{ url = "https://files.pythonhosted.org/packages/58/85/7ae00d5c8dd6266f4e944c3db630f3c5c9a98b61d469c714d848b1d8138a/cffi-2.1.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:a95b05f9baf29b91171b3a8bd2020b028835243e7b0ff6bb23e2a3c228518b1b", size = 196966, upload-time = "2026-07-06T21:33:05.353Z" },
|
|
157
|
+
{ url = "https://files.pythonhosted.org/packages/8c/e9/45c3a76ad8d43ad9261f4c95436da61128d3ca545d72b9612c0ab5be0b1c/cffi-2.1.0-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:15faec4adfff450819f3aee0e2e02c812de6edb88203aa58807955db2003472a", size = 184795, upload-time = "2026-07-06T21:33:06.699Z" },
|
|
158
|
+
{ url = "https://files.pythonhosted.org/packages/84/4c/82f132cb4418ee6d953d982b19191e87e2a6372c8a4ce36e50b69d6ade4a/cffi-2.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:716ff8ec22f20b4d988b12884086bcef0fc99737043e503f7a3935a6be99b1ea", size = 184746, upload-time = "2026-07-06T21:33:08.071Z" },
|
|
159
|
+
{ url = "https://files.pythonhosted.org/packages/a0/1c/4ed5a0e5bdca6cbc275556de3328dd1b76fd0c11cc13c88fe66d1d8715f2/cffi-2.1.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:63960549e4f8dc41e31accb97b975abaecfc44c03e396c093a6436763c2ea7db", size = 214747, upload-time = "2026-07-06T21:33:09.671Z" },
|
|
160
|
+
{ url = "https://files.pythonhosted.org/packages/3a/a6/e879bb68cc23a2bc9ba8f4b7d8019f0c2694bad2ab6c4a3701d429439f58/cffi-2.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ff067a8d8d880e7809e4ac88eb009bb848870115317b306666502ccad30b147f", size = 222392, upload-time = "2026-07-06T21:33:10.896Z" },
|
|
161
|
+
{ url = "https://files.pythonhosted.org/packages/88/f6/01890cfd63c08f8eb96a8319b0443690197d240a8bd6346048cf7bde9190/cffi-2.1.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:3b926723c13eba9f81d2ef3820d63aeceec3b2d4639906047bf675cb8a7a500d", size = 210285, upload-time = "2026-07-06T21:33:12.251Z" },
|
|
162
|
+
{ url = "https://files.pythonhosted.org/packages/a6/cf/2b684132056f438567b61e19d690dd31cd0921ace051e0a458be6074369e/cffi-2.1.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:47ff3a8bfd8cb9da1af7524b965127095055654c177fcfc7578debcb015eecd0", size = 208801, upload-time = "2026-07-06T21:33:13.617Z" },
|
|
163
|
+
{ url = "https://files.pythonhosted.org/packages/6f/08/f2e7d62c460faae0926f2d6e423694aa409ced3bc1fe2927a0a6e5f05416/cffi-2.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:799416bae98336e400981ff6e532d67d5c709cfb30afb79865a1315f94b0e224", size = 221808, upload-time = "2026-07-06T21:33:15.466Z" },
|
|
164
|
+
{ url = "https://files.pythonhosted.org/packages/38/37/04f54b8e63a02f3d908332c9effbf8c366167c6f733ed8a3d4f79b7e2a1e/cffi-2.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:961be50688f7fba2fa65f63712d3b9b341a22311f5253460ce933f52f0de1c8c", size = 225241, upload-time = "2026-07-06T21:33:16.869Z" },
|
|
165
|
+
{ url = "https://files.pythonhosted.org/packages/a9/d6/c72eecca433cd3e681c65ed313ab4835d9d4a379704d0f628a6a05f51c2e/cffi-2.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bf5c6cf48238b0eb4c086978c492ad1cbc22373fc5b2d7353b3a598ce6db887a", size = 223588, upload-time = "2026-07-06T21:33:18.239Z" },
|
|
166
|
+
{ url = "https://files.pythonhosted.org/packages/c6/4b/e706f67279140f92939da3475ad610df18bfd52d50f14953a8e5fede71d5/cffi-2.1.0-cp313-cp313-win32.whl", hash = "sha256:db3eb7d46527159a878ec3460e9d40615bc25ba337d477db681aea6e4f05c5d2", size = 175248, upload-time = "2026-07-06T21:33:19.799Z" },
|
|
167
|
+
{ url = "https://files.pythonhosted.org/packages/5a/47/59eb7975cb0e4ef0afa764ea945b29a5bb4537a9f771cb7d6c8a5dd74c95/cffi-2.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:8e74a6135550c4748af665b1b1118b6aab33b1fc6a16f9aff630af107c3b4512", size = 185717, upload-time = "2026-07-06T21:33:21.47Z" },
|
|
168
|
+
{ url = "https://files.pythonhosted.org/packages/5a/af/34fee85c48f8d94efc8597bc09470c9dd274c145f1c12e0fbc6ab6d38d74/cffi-2.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:2282cd5e38aa8accd03e99d1256af8411c84cdbee6a89d841b563fdbd1f3e50f", size = 180114, upload-time = "2026-07-06T21:33:22.515Z" },
|
|
169
|
+
{ url = "https://files.pythonhosted.org/packages/d8/f0/81478e482afa03f6d18dc8f2afb5edc45b3080853b634b5ed91961be0998/cffi-2.1.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:d2117334c3af3bdcb9a88522b844a2bdb5efdc4f71c6c822df55486ae1c3347a", size = 194142, upload-time = "2026-07-06T21:33:23.657Z" },
|
|
170
|
+
{ url = "https://files.pythonhosted.org/packages/7d/95/8de304305cd9204974b0ca051b86d307cafca13aa575a0ef1b44d92c0d8c/cffi-2.1.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:702c436735fbe99d59ada02a1f65cfc0d31c0ee8b7290912f8fbc5cd1e4b16c3", size = 196819, upload-time = "2026-07-06T21:33:25.007Z" },
|
|
171
|
+
{ url = "https://files.pythonhosted.org/packages/20/71/7c8372d30e42415602ed9f268f7cfd66f1b855fed881ecd168bcb45dbc0b/cffi-2.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:1ff3456eab0d889592d1936d6125bbfbc7ae4d3354a700f8bd80450a66445d4d", size = 184965, upload-time = "2026-07-06T21:33:26.605Z" },
|
|
172
|
+
{ url = "https://files.pythonhosted.org/packages/d6/5c/584e626835f0375c928176c04137c96927165cb8733cdb3150ec04e5ee5e/cffi-2.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c4165821e131d6d4ca444347c2b694e2311bcfa3fe5a861cc72968f28867beac", size = 184952, upload-time = "2026-07-06T21:33:27.823Z" },
|
|
173
|
+
{ url = "https://files.pythonhosted.org/packages/2e/d2/065fcae1c73979fac8e054462478d0ff8a29c40cdc2ed7ea5676a061df53/cffi-2.1.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:276f20fffd7b396e12516ba8edf9509210ac248cbbc5acbc39cd512f9f59ebe6", size = 222353, upload-time = "2026-07-06T21:33:29.178Z" },
|
|
174
|
+
{ url = "https://files.pythonhosted.org/packages/ed/a5/e8bbb1ce5b3ac2f53ad6a10bde44318a5a8d99d4f4a000d44a6e39aeb3e4/cffi-2.1.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:7d5980a3433d4b71a5e120f9dd551403d7824e31e2e67124fe2769c404c06913", size = 210051, upload-time = "2026-07-06T21:33:30.534Z" },
|
|
175
|
+
{ url = "https://files.pythonhosted.org/packages/28/ed/c127d3ac36e899c965e3361357c3befacd6578c03f40125183e41c3b219e/cffi-2.1.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:6ca4919c6e4f89aa99c42510b42cf54596892c00b3f9077f6bdd1505e24b9c8d", size = 208630, upload-time = "2026-07-06T21:33:31.753Z" },
|
|
176
|
+
{ url = "https://files.pythonhosted.org/packages/cc/d7/97d3136f81db489ec8d1d67748c110d6c994268fd7528014aa9f2b085e4e/cffi-2.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d53d10f7da99ae46f7373b9150393e9c5eab9b224909982b43832668de4779f5", size = 221593, upload-time = "2026-07-06T21:33:33.044Z" },
|
|
177
|
+
{ url = "https://files.pythonhosted.org/packages/d3/27/93195977168ee63aed233a1a0993a2178798654d1f4bddcdd321d6fd3b21/cffi-2.1.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c351efb95e832a853a29361675f33a7ce53de1a109cd73fd47af0712213aa4ce", size = 225146, upload-time = "2026-07-06T21:33:34.224Z" },
|
|
178
|
+
{ url = "https://files.pythonhosted.org/packages/b3/c1/6dbd291ee2ae5a50a034aa057207081f545923bbf15dad4511e985aafff5/cffi-2.1.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:dbf7c7a88e2bac086f06d14577332760bdeecc42bdec8ac4077f6260557d9326", size = 223240, upload-time = "2026-07-06T21:33:35.57Z" },
|
|
179
|
+
{ url = "https://files.pythonhosted.org/packages/0f/6f/ade5ce9863a57992a6ea3d0d10d7e29b8749fc127204b3d493d667b2815f/cffi-2.1.0-cp314-cp314-win32.whl", hash = "sha256:1854b724d00f6654c742097d5387569021be12d3a0f770eae1df8f8acfcc6acd", size = 177723, upload-time = "2026-07-06T21:33:51.626Z" },
|
|
180
|
+
{ url = "https://files.pythonhosted.org/packages/41/de/92b9eeed4ae4a21d6fd9b2a2c8505cbed573299902ea73981cc13f7ff62c/cffi-2.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:1b96bfe2c4bd825681b7d311ad6d9b7280a091f43e8f63da5729638083cd3bfb", size = 187937, upload-time = "2026-07-06T21:33:53.403Z" },
|
|
181
|
+
{ url = "https://files.pythonhosted.org/packages/2e/1a/cc6ae6c2913a03aab8898eee57963cf1035b8df5872ed8b9115fcc7e2be8/cffi-2.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:7d28dff1db6764108bc30788d85d61c876beff416d9a49cb9dd7c5a9f34f5804", size = 183001, upload-time = "2026-07-06T21:33:54.74Z" },
|
|
182
|
+
{ url = "https://files.pythonhosted.org/packages/14/f0/134c00ce0779ec86dea2aa1aac69339c2741a8045072676763512363a2ea/cffi-2.1.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:7ea6b3e2c4250ff1de21c630fe72d0f63eb95c2c32ffbf64a358cf4a8836d714", size = 188538, upload-time = "2026-07-06T21:33:36.792Z" },
|
|
183
|
+
{ url = "https://files.pythonhosted.org/packages/50/d8/3b86aba791cb610d24e8a3e1b2cd529e71fa15096b04e4d4e360049d4a4c/cffi-2.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6af371f3767faeffc6ac1ef57cdfd25844403e9d3f476c5537caee499de96376", size = 188230, upload-time = "2026-07-06T21:33:38.011Z" },
|
|
184
|
+
{ url = "https://files.pythonhosted.org/packages/14/d0/117dcd9209255ad8571fbc8c92ef32593a1d294dcec91ddc4e4db50606f2/cffi-2.1.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:eb4e8997a49aa2c08a3e43c9045d224448b8941d88e7ac163c7d383e560cbf98", size = 223899, upload-time = "2026-07-06T21:33:39.514Z" },
|
|
185
|
+
{ url = "https://files.pythonhosted.org/packages/b6/3d/f20f8b886b254e3ad10e15cd4186d3aed49f3e6a35ab37aab9f8f25f7c03/cffi-2.1.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:bf01d8c84cbea96b944c73b22182e6c7c432b3475632b8111dbfdc95ddad6e13", size = 211652, upload-time = "2026-07-06T21:33:40.851Z" },
|
|
186
|
+
{ url = "https://files.pythonhosted.org/packages/28/3b/fad54de07260b93ddeef4b96d0131d57ea900675df1d410ae1deee52d7a6/cffi-2.1.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:33eb1ad83ebe8f313e0df035c406227d55a79456704a863fad9842136af5ad7d", size = 210755, upload-time = "2026-07-06T21:33:42.183Z" },
|
|
187
|
+
{ url = "https://files.pythonhosted.org/packages/cc/82/3d5c705acb7abbba9bbd7d79b8e62e0f25b6120eb7ae6ac49f1b721722fe/cffi-2.1.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ac0f1a2d0cfa7eea3f2aaf006ab6e70e8feeb16b75d65b7e5939982ca2f11056", size = 223933, upload-time = "2026-07-06T21:33:43.603Z" },
|
|
188
|
+
{ url = "https://files.pythonhosted.org/packages/6c/d0/47e338384ab6b1004241002fa616301020cea4fc95f283506565d252f276/cffi-2.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c16914df9fb7f500e440e6875fa23ff5e0b31db01fa9c06af98d59a91f0dc2e4", size = 226749, upload-time = "2026-07-06T21:33:45.046Z" },
|
|
189
|
+
{ url = "https://files.pythonhosted.org/packages/70/25/65bd5b58ea4bfdfc15cde02cb5365f89ef8ab8b2adfb8fe5c4bd4233382f/cffi-2.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5ecbd0499275d57506d397eebe1981cee87b47fcd9ef5c22cab7ed7644a39a94", size = 225703, upload-time = "2026-07-06T21:33:46.374Z" },
|
|
190
|
+
{ url = "https://files.pythonhosted.org/packages/dc/78/aa01ac599a8a4322533d45a1f9bc93b338276d2d59dabbe7c6d92a775c81/cffi-2.1.0-cp314-cp314t-win32.whl", hash = "sha256:7d034dcffa09e9a46c93fa3a3be402096cb5354ac6e41ab8e5cc9cd8b642ad76", size = 182857, upload-time = "2026-07-06T21:33:47.696Z" },
|
|
191
|
+
{ url = "https://files.pythonhosted.org/packages/b9/26/d00496b22de4d4228f32dde94ad996f350c8aad676d63bcca0743c8dea4d/cffi-2.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:0582a58f3051372229ca8e7f5f589f9e5632678208d8636fea3676711fdf7fe5", size = 194065, upload-time = "2026-07-06T21:33:48.953Z" },
|
|
192
|
+
{ url = "https://files.pythonhosted.org/packages/d5/dd/0c7dbf815a579ff005008a2d815a55d6bb047c349eef536d9dc53d3f0a8d/cffi-2.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:510aeeeac94811b138077451da1fb18b308a5feab47dd2b603af55804155e1c8", size = 186404, upload-time = "2026-07-06T21:33:50.309Z" },
|
|
193
|
+
{ url = "https://files.pythonhosted.org/packages/55/c7/8c8c50cb11c6750051daf12164098a9a6f027ac4356967fd4d800a07f242/cffi-2.1.0-cp315-cp315-ios_13_0_arm64_iphoneos.whl", hash = "sha256:2e9dabb9abcb7ad15938c7196ad5c1718a4e6d33cc79b4c0209bdb64c4a54a5c", size = 194121, upload-time = "2026-07-06T21:33:56.109Z" },
|
|
194
|
+
{ url = "https://files.pythonhosted.org/packages/99/e2/67680bf19a6b60d2bb7ff83baefa2a4c3d2d7dc0f3277034b802e1fc504c/cffi-2.1.0-cp315-cp315-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:37f525a7e7e50c017fdebe58b787be310ad59357ae43a053943a6e1a6c526001", size = 196820, upload-time = "2026-07-06T21:33:57.288Z" },
|
|
195
|
+
{ url = "https://files.pythonhosted.org/packages/ed/da/4bbe583a3b3a5c8c60892124fe17f3fa3656523faf0d3484eae90f091853/cffi-2.1.0-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:95f2954c2c9473d892eca6e0409f3568b37ab62a8eedb122461f73cc273476e3", size = 184936, upload-time = "2026-07-06T21:33:58.765Z" },
|
|
196
|
+
{ url = "https://files.pythonhosted.org/packages/e5/4b/1f4c36ab273980d7aa75bb126ea4f8971f24a96108acad3a0a084028c57b/cffi-2.1.0-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:cdf2448aab5f661c9315308ec8b93f4e8a1a67a3c733f8631067a2b67d5913dc", size = 185045, upload-time = "2026-07-06T21:34:00.085Z" },
|
|
197
|
+
{ url = "https://files.pythonhosted.org/packages/ef/c3/ad299dc38f3583f8d916b299f028af418a9ec98bc695fcbebeae7420691c/cffi-2.1.0-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:90bec57cf82089383bd06a605b3eb8daebf7e5a668520beaf6e327a83a947699", size = 222342, upload-time = "2026-07-06T21:34:01.814Z" },
|
|
198
|
+
{ url = "https://files.pythonhosted.org/packages/eb/d8/df4543cc087245044ed02ef3ad8e0a26619d0075ac7a77a12dc81177851b/cffi-2.1.0-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:6274dcb2d15cef48daa73ed1be5a40d501d74dccd0cd6db364776d12cb6ba022", size = 210073, upload-time = "2026-07-06T21:34:03.255Z" },
|
|
199
|
+
{ url = "https://files.pythonhosted.org/packages/2c/0e/fac738d73728c6cea2a88a2883dca54892496cbba88a1dc1f2909cb8a6f5/cffi-2.1.0-cp315-cp315-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:2b71d409cccee78310ab5dec549aed052aaea483346e282c7b02362596e01bb0", size = 208551, upload-time = "2026-07-06T21:34:04.433Z" },
|
|
200
|
+
{ url = "https://files.pythonhosted.org/packages/e6/3f/0b04a700dd64f465c93020253a793a82c9b4dff9961f48facd0df945d9b8/cffi-2.1.0-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7d3538f9c0e50670f4deb93dbb696576e60590369cae2faf7de681e597a8a1f1", size = 221649, upload-time = "2026-07-06T21:34:06.157Z" },
|
|
201
|
+
{ url = "https://files.pythonhosted.org/packages/5d/7c/b7379a5704c79eda57ce075869ba70a0368d1c850f803b3c0d078d39dcaf/cffi-2.1.0-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:8f9ec95b8a043d3dfbc74d9abc6f7baf524dd27a8dc160b0a32ff9cdab650c28", size = 225203, upload-time = "2026-07-06T21:34:07.489Z" },
|
|
202
|
+
{ url = "https://files.pythonhosted.org/packages/5a/02/d5e6c43ea85c41bda2a184a3418f195fe7cf602967a8d2b94e085b83deef/cffi-2.1.0-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:af5e2915d41fe6c961694d7bfdc8562942638200f3ce2765dfb8b745cf997629", size = 223263, upload-time = "2026-07-06T21:34:08.712Z" },
|
|
203
|
+
{ url = "https://files.pythonhosted.org/packages/2c/d8/772b8259bf75749adffb1c546828978381fb516f60cf701f6c83daf60c85/cffi-2.1.0-cp315-cp315-win32.whl", hash = "sha256:0a42c688d19fca6e095a53c6a6e2295a5b050a8b289f109adab02a9e61a25de6", size = 177696, upload-time = "2026-07-06T21:34:26.355Z" },
|
|
204
|
+
{ url = "https://files.pythonhosted.org/packages/2f/dd/afa2191fc6d57fedd26e5844a2fe2fcc0bbfa00961bbaa5a41e4921e7cca/cffi-2.1.0-cp315-cp315-win_amd64.whl", hash = "sha256:bccbbb5ee76a61f9d99b5bf3846a51d7fca4b6a732fe46f89295610edaf41853", size = 187914, upload-time = "2026-07-06T21:34:27.58Z" },
|
|
205
|
+
{ url = "https://files.pythonhosted.org/packages/05/ef/6cd4f8c671517162379dc79cfae5aea9106bc38abb89628d5c16adf6a838/cffi-2.1.0-cp315-cp315-win_arm64.whl", hash = "sha256:8d35c139744adb3e727cd51b1a18324bbe44b8bd41bf8322bca4d41289f48eda", size = 183004, upload-time = "2026-07-06T21:34:28.905Z" },
|
|
206
|
+
{ url = "https://files.pythonhosted.org/packages/11/b6/12fc55092817a5faa26fb8c40c7f9d662e11a46ee248c137aafc42517d92/cffi-2.1.0-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:f9912624a0c0b834b7520d7769b3644453aabc0a7e1c839da7359f050750e9bc", size = 188378, upload-time = "2026-07-06T21:34:09.926Z" },
|
|
207
|
+
{ url = "https://files.pythonhosted.org/packages/8d/2e/cdac88979f295fde5daa69622c7d2111e56e7ceb94f211357fbe452339e4/cffi-2.1.0-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:df92f2aba50eb4d96718b68ef76f2e57a57b54f2fa62333496d16c6d585a85ca", size = 188319, upload-time = "2026-07-06T21:34:11.101Z" },
|
|
208
|
+
{ url = "https://files.pythonhosted.org/packages/e0/27/1d0b408497e41a74795af122d7b603c418c5fed0171450f899afd04e594f/cffi-2.1.0-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0520e1f4c35f44e209cbbb421b67eec42e6a157f59444dfb6058874ff3610e5d", size = 223904, upload-time = "2026-07-06T21:34:12.606Z" },
|
|
209
|
+
{ url = "https://files.pythonhosted.org/packages/8b/31/e115c985105dd7ffb32444505f18ceb874bb42d992af05d5dced7ecf1980/cffi-2.1.0-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:3681e031db29958a7502f5c0c9d6bbc4c36cb20f7b104086fa642d1799631ff8", size = 211554, upload-time = "2026-07-06T21:34:13.987Z" },
|
|
210
|
+
{ url = "https://files.pythonhosted.org/packages/5a/67/9e6e09409336d9e515c58367e7cfcf4f89df06ad25252675595a58eb59d5/cffi-2.1.0-cp315-cp315t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:762f99479dcb369f60ab9017ad4ab97a36a1dd7c1ee5a3b15db0f4b8659120cd", size = 210795, upload-time = "2026-07-06T21:34:15.972Z" },
|
|
211
|
+
{ url = "https://files.pythonhosted.org/packages/19/e5/d3cc82a4a0be7902af279c04181ad038449c096734464a5ae1de3e1401bd/cffi-2.1.0-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0611e7ebf90573a535ebdc33ae9da222d037853983e13359f580fab781ca017f", size = 223843, upload-time = "2026-07-06T21:34:17.509Z" },
|
|
212
|
+
{ url = "https://files.pythonhosted.org/packages/b9/65/b434abc97ce7cecc2c640fde160507c0ecc7e21544b483ba3325d2e2ea17/cffi-2.1.0-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:86cf8755a791f72c85dc287128cc62d4f24d392e3f1e15837245623f4a33cccc", size = 226773, upload-time = "2026-07-06T21:34:19.05Z" },
|
|
213
|
+
{ url = "https://files.pythonhosted.org/packages/b5/9f/d4dc66ca651eb1145a133314cda721abf13cfac3d28c4a0402263ae6ad75/cffi-2.1.0-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:ba00f661f8ba35d075c937174e27c2c421cec3942fd2e0ea3e66996757c0fdd9", size = 225719, upload-time = "2026-07-06T21:34:20.576Z" },
|
|
214
|
+
{ url = "https://files.pythonhosted.org/packages/68/5a/e536c528bc8057496c360c0978559a2dc45653f89dd6151078aa7d8fca1a/cffi-2.1.0-cp315-cp315t-win32.whl", hash = "sha256:cb96698e3c7413d906ce83f8ffd245ec1bd94707541f299d0ce4d6b0193e982b", size = 182760, upload-time = "2026-07-06T21:34:22.059Z" },
|
|
215
|
+
{ url = "https://files.pythonhosted.org/packages/d3/0b/0ffe8b82d3875bced5fa1e7986a7a46b748262a40ab7f60b475eb9fb1bb3/cffi-2.1.0-cp315-cp315t-win_amd64.whl", hash = "sha256:f146d154428a2523f9cc7936c02353c2459b8f6cf07d3cd1ee1c0a611109c5d5", size = 193769, upload-time = "2026-07-06T21:34:23.589Z" },
|
|
216
|
+
{ url = "https://files.pythonhosted.org/packages/a0/17/1073b53b68c9b5ca6914adf5f8bf55aacc2d3be102418c90700160ea8605/cffi-2.1.0-cp315-cp315t-win_arm64.whl", hash = "sha256:cbb7640ce37159548d2147b5b8c241f962143d4c71231431820783f4dc78f210", size = 186405, upload-time = "2026-07-06T21:34:24.857Z" },
|
|
217
|
+
]
|
|
218
|
+
|
|
219
|
+
[[package]]
|
|
220
|
+
name = "pycparser"
|
|
221
|
+
version = "2.23"
|
|
222
|
+
source = { registry = "https://pypi.org/simple" }
|
|
223
|
+
resolution-markers = [
|
|
224
|
+
"python_full_version < '3.10'",
|
|
225
|
+
]
|
|
226
|
+
sdist = { url = "https://files.pythonhosted.org/packages/fe/cf/d2d3b9f5699fb1e4615c8e32ff220203e43b248e1dfcc6736ad9057731ca/pycparser-2.23.tar.gz", hash = "sha256:78816d4f24add8f10a06d6f05b4d424ad9e96cfebf68a4ddc99c65c0720d00c2", size = 173734, upload-time = "2025-09-09T13:23:47.91Z" }
|
|
227
|
+
wheels = [
|
|
228
|
+
{ url = "https://files.pythonhosted.org/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl", hash = "sha256:e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934", size = 118140, upload-time = "2025-09-09T13:23:46.651Z" },
|
|
229
|
+
]
|
|
230
|
+
|
|
231
|
+
[[package]]
|
|
232
|
+
name = "pycparser"
|
|
233
|
+
version = "3.0"
|
|
234
|
+
source = { registry = "https://pypi.org/simple" }
|
|
235
|
+
resolution-markers = [
|
|
236
|
+
"python_full_version >= '3.10'",
|
|
237
|
+
]
|
|
238
|
+
sdist = { url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z" }
|
|
239
|
+
wheels = [
|
|
240
|
+
{ url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" },
|
|
241
|
+
]
|
|
242
|
+
|
|
243
|
+
[[package]]
|
|
244
|
+
name = "rockbox-ffi"
|
|
245
|
+
version = "0.1.0"
|
|
246
|
+
source = { editable = "." }
|
|
247
|
+
dependencies = [
|
|
248
|
+
{ name = "cffi", version = "2.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" },
|
|
249
|
+
{ name = "cffi", version = "2.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" },
|
|
250
|
+
]
|
|
251
|
+
|
|
252
|
+
[package.metadata]
|
|
253
|
+
requires-dist = [{ name = "cffi", specifier = ">=1.16" }]
|