From 758e41c3d155375875d4a16301dd3df936bb9a53 Mon Sep 17 00:00:00 2001 From: Craig Chan <46288912+rachthree@users.noreply.github.com> Date: Wed, 26 Feb 2025 04:18:09 -0500 Subject: [PATCH 01/37] Add safestructures to project list (#570) --- docs/source/index.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/index.mdx b/docs/source/index.mdx index 2cd11805..52bbdd01 100644 --- a/docs/source/index.mdx +++ b/docs/source/index.mdx @@ -92,3 +92,4 @@ Safetensors is being used widely at leading AI enterprises, such as [Hugging Fac * [LianjiaTech/BELLE](https://github.com/LianjiaTech/BELLE) * [alvarobartt/safejax](https://github.com/alvarobartt/safejax) * [MaartenGr/BERTopic](https://github.com/MaartenGr/BERTopic) +* [rachthree/safestructures](https://github.com/rachthree/safestructures) From 543243c3017e413584f27ebd4b99c844f62deb34 Mon Sep 17 00:00:00 2001 From: Nicolas Patry Date: Wed, 26 Feb 2025 12:18:23 +0100 Subject: [PATCH 02/37] Fixing benchmarks. (#580) * Fixing benchmarks. * Fix test line. --- .github/workflows/python-bench.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/python-bench.yml b/.github/workflows/python-bench.yml index fafeddbe..0662e8fc 100644 --- a/.github/workflows/python-bench.yml +++ b/.github/workflows/python-bench.yml @@ -3,6 +3,7 @@ on: push: branches: - main + pull_request: permissions: @@ -15,6 +16,8 @@ jobs: benchmark: name: Performance regression check runs-on: ubuntu-latest + env: + MATURIN_PEP517_ARGS: "--features py311,pyo3/extension-module" steps: - uses: actions/checkout@v3 - name: Install Rust @@ -26,7 +29,7 @@ jobs: - name: Install Python uses: actions/setup-python@v2 with: - python-version: "3.10" + python-version: "3.11" architecture: "x64" - name: Install @@ -38,7 +41,7 @@ jobs: - name: Run tests working-directory: ./bindings/python run: | - cargo test + cargo test --features py311 pytest --benchmark-json output.json benches/ # Download previous benchmark result from cache (if exists) - name: Download previous benchmark data From 467a605bcb0f8ce3a324b9e1dd93c309bd6661aa Mon Sep 17 00:00:00 2001 From: Yousong Zhou Date: Thu, 6 Mar 2025 00:23:12 +0800 Subject: [PATCH 03/37] load_file: load tensors ordered by their offsets (#571) --- bindings/python/py_src/safetensors/flax.py | 2 +- bindings/python/py_src/safetensors/mlx.py | 2 +- bindings/python/py_src/safetensors/numpy.py | 2 +- .../python/py_src/safetensors/tensorflow.py | 2 +- bindings/python/py_src/safetensors/torch.py | 2 +- bindings/python/src/lib.rs | 19 +++++++++++++++++++ safetensors/src/tensor.rs | 7 +++++++ 7 files changed, 31 insertions(+), 5 deletions(-) diff --git a/bindings/python/py_src/safetensors/flax.py b/bindings/python/py_src/safetensors/flax.py index d0b8375e..a6471507 100644 --- a/bindings/python/py_src/safetensors/flax.py +++ b/bindings/python/py_src/safetensors/flax.py @@ -121,7 +121,7 @@ def load_file(filename: Union[str, os.PathLike]) -> Dict[str, Array]: """ result = {} with safe_open(filename, framework="flax") as f: - for k in f.keys(): + for k in f.offset_keys(): result[k] = f.get_tensor(k) return result diff --git a/bindings/python/py_src/safetensors/mlx.py b/bindings/python/py_src/safetensors/mlx.py index cf9fe375..df04e710 100644 --- a/bindings/python/py_src/safetensors/mlx.py +++ b/bindings/python/py_src/safetensors/mlx.py @@ -120,7 +120,7 @@ def load_file(filename: Union[str, os.PathLike]) -> Dict[str, mx.array]: """ result = {} with safe_open(filename, framework="mlx") as f: - for k in f.keys(): + for k in f.offset_keys(): result[k] = f.get_tensor(k) return result diff --git a/bindings/python/py_src/safetensors/numpy.py b/bindings/python/py_src/safetensors/numpy.py index 0b245f12..89e00e11 100644 --- a/bindings/python/py_src/safetensors/numpy.py +++ b/bindings/python/py_src/safetensors/numpy.py @@ -126,7 +126,7 @@ def load_file(filename: Union[str, os.PathLike]) -> Dict[str, np.ndarray]: """ result = {} with safe_open(filename, framework="np") as f: - for k in f.keys(): + for k in f.offset_keys(): result[k] = f.get_tensor(k) return result diff --git a/bindings/python/py_src/safetensors/tensorflow.py b/bindings/python/py_src/safetensors/tensorflow.py index e2d74b05..8513f803 100644 --- a/bindings/python/py_src/safetensors/tensorflow.py +++ b/bindings/python/py_src/safetensors/tensorflow.py @@ -120,7 +120,7 @@ def load_file(filename: Union[str, os.PathLike]) -> Dict[str, tf.Tensor]: """ result = {} with safe_open(filename, framework="tf") as f: - for k in f.keys(): + for k in f.offset_keys(): result[k] = f.get_tensor(k) return result diff --git a/bindings/python/py_src/safetensors/torch.py b/bindings/python/py_src/safetensors/torch.py index 4476e754..f3591ade 100644 --- a/bindings/python/py_src/safetensors/torch.py +++ b/bindings/python/py_src/safetensors/torch.py @@ -317,7 +317,7 @@ def load_file(filename: Union[str, os.PathLike], device: Union[str, int] = "cpu" """ result = {} with safe_open(filename, framework="pt", device=device) as f: - for k in f.keys(): + for k in f.offset_keys(): result[k] = f.get_tensor(k) return result diff --git a/bindings/python/src/lib.rs b/bindings/python/src/lib.rs index 1e6ba853..4d1d5f82 100644 --- a/bindings/python/src/lib.rs +++ b/bindings/python/src/lib.rs @@ -443,6 +443,16 @@ impl Open { Ok(keys) } + /// Returns the names of the tensors in the file, ordered by offset. + /// + /// Returns: + /// (`List[str]`): + /// The name of the tensors contained in that file + pub fn offset_keys(&self) -> PyResult> { + let keys: Vec = self.metadata.offset_keys(); + Ok(keys) + } + /// Returns a full tensor /// /// Args: @@ -651,6 +661,15 @@ impl safe_open { self.inner()?.keys() } + /// Returns the names of the tensors in the file, ordered by offset. + /// + /// Returns: + /// (`List[str]`): + /// The name of the tensors contained in that file + pub fn offset_keys(&self) -> PyResult> { + self.inner()?.offset_keys() + } + /// Returns a full tensor /// /// Args: diff --git a/safetensors/src/tensor.rs b/safetensors/src/tensor.rs index 42d59e04..1da1278c 100644 --- a/safetensors/src/tensor.rs +++ b/safetensors/src/tensor.rs @@ -554,6 +554,13 @@ impl Metadata { .collect() } + /// Gives back the tensor names ordered by offset + pub fn offset_keys(&self) -> Vec { + let mut index_vec: Vec<_> = self.index_map.iter().collect(); + index_vec.sort_by_key(|a| a.1); + index_vec.into_iter().map(|a| a.0.clone()).collect() + } + /// Gives back the tensor metadata pub fn metadata(&self) -> &Option> { &self.metadata From 53fe06c3efd40ff62520f74818819590b2bc25de Mon Sep 17 00:00:00 2001 From: Nicolas Patry Date: Wed, 5 Mar 2025 17:46:19 +0100 Subject: [PATCH 04/37] Updating python bench ? (#587) * Updating python bench ? * Cache v4?? --- .github/workflows/python-bench.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/python-bench.yml b/.github/workflows/python-bench.yml index 0662e8fc..7bd81ec1 100644 --- a/.github/workflows/python-bench.yml +++ b/.github/workflows/python-bench.yml @@ -19,7 +19,7 @@ jobs: env: MATURIN_PEP517_ARGS: "--features py311,pyo3/extension-module" steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Rust uses: actions-rs/toolchain@v1 with: @@ -45,7 +45,7 @@ jobs: pytest --benchmark-json output.json benches/ # Download previous benchmark result from cache (if exists) - name: Download previous benchmark data - uses: actions/cache@v1 + uses: actions/cache@v4 with: path: ./cache key: ${{ runner.os }}-benchmark From b44ac87d42640d5b1c587304883739f6e5a89125 Mon Sep 17 00:00:00 2001 From: Marco-Christiani Date: Thu, 13 Mar 2025 08:26:55 -0400 Subject: [PATCH 05/37] fix(benchmark.rs): "serialize" and "deserialize" (#585) --- safetensors/benches/benchmark.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/safetensors/benches/benchmark.rs b/safetensors/benches/benchmark.rs index 8f9dd3fb..8bb490a4 100644 --- a/safetensors/benches/benchmark.rs +++ b/safetensors/benches/benchmark.rs @@ -23,7 +23,7 @@ pub fn bench_serialize(c: &mut Criterion) { metadata.insert(format!("weight{i}"), tensor); } - c.bench_function("Serlialize 10_MB", |b| { + c.bench_function("Serialize 10_MB", |b| { b.iter(|| { let _serialized = serialize(black_box(&metadata), black_box(&None)); }) @@ -43,7 +43,7 @@ pub fn bench_deserialize(c: &mut Criterion) { let out = serialize(&metadata, &None).unwrap(); - c.bench_function("Deserlialize 10_MB", |b| { + c.bench_function("Deserialize 10_MB", |b| { b.iter(|| { let _deserialized = SafeTensors::deserialize(black_box(&out)).unwrap(); }) From fb97e66912f7edcd13a4b3dff506bf83b5207f18 Mon Sep 17 00:00:00 2001 From: Justin Chu Date: Thu, 13 Mar 2025 05:27:20 -0700 Subject: [PATCH 06/37] Add onnx-safetensors to the projects list (#581) onnx-safetensors enables onnx files to use safetensors as external data for the ONNX model natively. --- docs/source/index.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/index.mdx b/docs/source/index.mdx index 52bbdd01..7a1ecb3b 100644 --- a/docs/source/index.mdx +++ b/docs/source/index.mdx @@ -93,3 +93,4 @@ Safetensors is being used widely at leading AI enterprises, such as [Hugging Fac * [alvarobartt/safejax](https://github.com/alvarobartt/safejax) * [MaartenGr/BERTopic](https://github.com/MaartenGr/BERTopic) * [rachthree/safestructures](https://github.com/rachthree/safestructures) +* [justinchuby/onnx-safetensors](https://github.com/justinchuby/onnx-safetensors) From 62155a5f6c8b0400afb74964e3a244f6ed017bc4 Mon Sep 17 00:00:00 2001 From: Mick van Gelderen Date: Mon, 17 Mar 2025 02:14:17 -0700 Subject: [PATCH 07/37] Pass device to torch.asarray in get_tensor (#588) * Pass device to torch.asarray in get_tensor * Fixing default device. --------- Co-authored-by: Nicolas Patry --- bindings/python/src/lib.rs | 13 ++++++------- bindings/python/tests/test_pt_comparison.py | 12 +++++++++++- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/bindings/python/src/lib.rs b/bindings/python/src/lib.rs index 4d1d5f82..b6a0f49c 100644 --- a/bindings/python/src/lib.rs +++ b/bindings/python/src/lib.rs @@ -500,7 +500,12 @@ impl Open { let torch = get_module(py, &TORCH_MODULE)?; let dtype: PyObject = get_pydtype(torch, info.dtype, false)?; let torch_uint8: PyObject = get_pydtype(torch, Dtype::U8, false)?; - let kwargs = [(intern!(py, "dtype"), torch_uint8)].into_py_dict(py)?; + let device: PyObject = self.device.clone().into_pyobject(py)?.into(); + let kwargs = [ + (intern!(py, "dtype"), torch_uint8), + (intern!(py, "device"), device), + ] + .into_py_dict(py)?; let view_kwargs = [(intern!(py, "dtype"), dtype)].into_py_dict(py)?; let shape = info.shape.to_vec(); let shape: PyObject = shape.into_pyobject(py)?.into(); @@ -560,13 +565,7 @@ impl Open { } tensor = tensor.getattr(intern!(py, "reshape"))?.call1((shape,))?; - if self.device != Device::Cpu { - let device: PyObject = self.device.clone().into_pyobject(py)?.into(); - let kwargs = PyDict::new(py); - tensor = tensor.call_method("to", (device,), Some(&kwargs))?; - } Ok(tensor.into_pyobject(py)?.into()) - // torch.asarray(storage[start + n : stop + n], dtype=torch.uint8).view(dtype=dtype).reshape(shape) }) } } diff --git a/bindings/python/tests/test_pt_comparison.py b/bindings/python/tests/test_pt_comparison.py index fc616445..10e8cc05 100644 --- a/bindings/python/tests/test_pt_comparison.py +++ b/bindings/python/tests/test_pt_comparison.py @@ -173,7 +173,7 @@ def test_npu(self): def test_hpu(self): # must be run to load torch with Intel Gaudi bindings try: - import habana_frameworks.torch.core as htcore + import habana_frameworks.torch.core as htcore # noqa: F401 except ImportError: self.skipTest("HPU is not available") @@ -255,6 +255,16 @@ def test_deserialization_safe(self): self.assertTrue(torch.allclose(v, tv)) self.assertEqual(v.device, torch.device("cpu")) + @unittest.skipIf(not torch.cuda.is_available(), "Cuda is not available") + def test_deserialization_device(self): + with torch.device("cuda:0"): + weights = load_file(self.sf_filename) + self.assertEqual(weights["test"].device, torch.device("cpu")) + + torch.set_default_device(torch.device("cuda:0")) + weights = load_file(self.sf_filename) + self.assertEqual(weights["test"].device, torch.device("cpu")) + @unittest.skipIf(not torch.cuda.is_available(), "Cuda is not available") def test_deserialization_safe_gpu(self): # First time to hit disk From 80d9a1219c2dd36e70e833683fc6f2eb335a8f87 Mon Sep 17 00:00:00 2001 From: Nicolas Patry Date: Mon, 17 Mar 2025 10:26:58 +0100 Subject: [PATCH 08/37] Making py311 the default. (#589) * Making py311 the default. * Fixing release script. * No default features everywhere. --- .github/workflows/python-bench.yml | 2 -- .github/workflows/python-release.yml | 8 ++++---- .github/workflows/python.yml | 6 +++--- .pre-commit-config.yaml | 2 -- bindings/python/Cargo.toml | 1 + bindings/python/src/lib.rs | 6 ++---- flake.nix | 2 +- 7 files changed, 11 insertions(+), 16 deletions(-) diff --git a/.github/workflows/python-bench.yml b/.github/workflows/python-bench.yml index 7bd81ec1..cbfd62de 100644 --- a/.github/workflows/python-bench.yml +++ b/.github/workflows/python-bench.yml @@ -16,8 +16,6 @@ jobs: benchmark: name: Performance regression check runs-on: ubuntu-latest - env: - MATURIN_PEP517_ARGS: "--features py311,pyo3/extension-module" steps: - uses: actions/checkout@v4 - name: Install Rust diff --git a/.github/workflows/python-release.yml b/.github/workflows/python-release.yml index 9399909b..58c8efca 100644 --- a/.github/workflows/python-release.yml +++ b/.github/workflows/python-release.yml @@ -46,7 +46,7 @@ jobs: uses: PyO3/maturin-action@v1 with: target: ${{ matrix.platform.target }} - args: --release --out dist --manifest-path bindings/python/Cargo.toml --features pyo3/extension-module,${{ matrix.pyfeature }} + args: --release --out dist --manifest-path bindings/python/Cargo.toml --features pyo3/extension-module,${{ matrix.pyfeature }} --no-default-features sccache: 'true' manylinux: auto - name: Upload wheels @@ -78,7 +78,7 @@ jobs: uses: PyO3/maturin-action@v1 with: target: ${{ matrix.platform.target }} - args: --release --out dist --manifest-path bindings/python/Cargo.toml --features pyo3/extension-module,${{ matrix.pyfeature }} + args: --release --out dist --manifest-path bindings/python/Cargo.toml --features pyo3/extension-module,${{ matrix.pyfeature }} --no-default-features sccache: 'true' manylinux: musllinux_1_2 - name: Upload wheels @@ -107,7 +107,7 @@ jobs: uses: PyO3/maturin-action@v1 with: target: ${{ matrix.platform.target }} - args: --release --out dist --manifest-path bindings/python/Cargo.toml --features pyo3/extension-module,${{ matrix.pyfeature }} + args: --release --out dist --manifest-path bindings/python/Cargo.toml --features pyo3/extension-module,${{ matrix.pyfeature }} --no-default-features sccache: 'true' - name: Upload wheels uses: actions/upload-artifact@v4 @@ -134,7 +134,7 @@ jobs: uses: PyO3/maturin-action@v1 with: target: ${{ matrix.platform.target }} - args: --release --out dist --manifest-path bindings/python/Cargo.toml --features pyo3/extension-module,${{ matrix.pyfeature }} + args: --release --out dist --manifest-path bindings/python/Cargo.toml --features pyo3/extension-module,${{ matrix.pyfeature }} --no-default-features sccache: 'true' - name: Upload wheels uses: actions/upload-artifact@v4 diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index 0c5437c7..0b9dd32f 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -8,7 +8,7 @@ jobs: name: Check everything builds & tests runs-on: ${{ matrix.os }} env: - MATURIN_PEP517_ARGS: "--features ${{ matrix.version.pyfeature }},pyo3/extension-module" + MATURIN_PEP517_ARGS: "--no-default-features --features ${{ matrix.version.pyfeature }},pyo3/extension-module" strategy: matrix: os: [ubuntu-latest, macos-13, windows-latest] @@ -55,7 +55,7 @@ jobs: - name: Lint with Clippy run: | - cargo clippy --features ${{ matrix.version.pyfeature }} -- -D warnings + cargo clippy --features ${{ matrix.version.pyfeature }} --no-default-features -- -D warnings - name: Run Audit run: cargo audit -D warnings @@ -84,7 +84,7 @@ jobs: - name: Run tests run: | - cargo test --features ${{ matrix.version.pyfeature }} + cargo test --features ${{ matrix.version.pyfeature }} --no-default-features pip install .[testing] pytest -sv tests/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a323e52c..1a28594b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -27,8 +27,6 @@ repos: [ "--manifest-path", "bindings/python/Cargo.toml", - "--features", - "py311", "--all-targets", "--", "-Dwarnings", diff --git a/bindings/python/Cargo.toml b/bindings/python/Cargo.toml index fe8bbf44..4052b9d4 100644 --- a/bindings/python/Cargo.toml +++ b/bindings/python/Cargo.toml @@ -12,6 +12,7 @@ crate-type = ["cdylib"] [features] py38 = ["pyo3/abi3-py38"] py311 = ["pyo3/abi3-py311"] +default = ["py311"] [dependencies] pyo3 = { version = "0.23", features = ["abi3"] } diff --git a/bindings/python/src/lib.rs b/bindings/python/src/lib.rs index b6a0f49c..6a654ada 100644 --- a/bindings/python/src/lib.rs +++ b/bindings/python/src/lib.rs @@ -28,11 +28,9 @@ static FLAX_MODULE: GILOnceCell> = GILOnceCell::new(); static MLX_MODULE: GILOnceCell> = GILOnceCell::new(); #[cfg(not(any(feature = "py38", feature = "py311")))] -compile_error!( - "At least one python version must be enabled, use `maturin develop --features py311,pyo3/extension-module`" -); +compile_error!("At least one python version must be enabled, use `maturin develop` for python 3.11, `maturin develop --features py38,pyo3/extension-module --no-default-features` for python 3.8"); #[cfg(all(feature = "py38", feature = "py311"))] -compile_error!("Only one python version must be enabled"); +compile_error!("Only one python version must be enabled, make sure to deactivate default features for python <3.11"); /// Serializes raw data. /// diff --git a/flake.nix b/flake.nix index a0cba1b7..106f129a 100644 --- a/flake.nix +++ b/flake.nix @@ -32,7 +32,7 @@ postShellHook = '' unset SOURCE_DATE_EPOCH ''; - LD_LIBRARY_PATH = "$LD_LIBRARY_PATH:${pkgs.stdenv.cc.cc.lib}/lib:${pkgs.zlib}/lib"; + LD_LIBRARY_PATH = "$LD_LIBRARY_PATH:${pkgs.stdenv.cc.cc.lib}/lib:${pkgs.zlib}/lib:/run/opengl-driver/lib"; }; } From cdb5e86cec5d9512f50dc3a8f4bb50f4d67f3016 Mon Sep 17 00:00:00 2001 From: Nicolas Patry Date: Mon, 17 Mar 2025 11:58:03 +0100 Subject: [PATCH 09/37] Fix test (#590) * Revert "Demoing zero-copy save. (#567)" This reverts commit 4b3864c802d727be3cd67e5107a0f873d047ae69. * Fixing the test and removing the PyBuffer thing. * Remove features from bench. --- .github/workflows/build_documentation.yml | 2 - .github/workflows/build_pr_documentation.yml | 2 - .github/workflows/python-bench.yml | 2 +- .github/workflows/python-release.yml | 20 ++- .github/workflows/python.yml | 10 +- Dockerfile.s390x.test | 1 - bindings/python/Cargo.toml | 7 +- bindings/python/py_src/safetensors/torch.py | 19 +-- bindings/python/src/lib.rs | 83 +++++++++-- bindings/python/src/view.rs | 137 ------------------- bindings/python/tests/test_pt_comparison.py | 1 + 11 files changed, 95 insertions(+), 189 deletions(-) delete mode 100644 bindings/python/src/view.rs diff --git a/.github/workflows/build_documentation.yml b/.github/workflows/build_documentation.yml index a491bc15..8b501942 100644 --- a/.github/workflows/build_documentation.yml +++ b/.github/workflows/build_documentation.yml @@ -11,8 +11,6 @@ on: jobs: build: uses: huggingface/doc-builder/.github/workflows/build_main_documentation.yml@main - env: - MATURIN_PEP517_ARGS: "--features py311,pyo3/extension-module" with: commit_sha: ${{ github.sha }} package: safetensors diff --git a/.github/workflows/build_pr_documentation.yml b/.github/workflows/build_pr_documentation.yml index 81214464..efafcd48 100644 --- a/.github/workflows/build_pr_documentation.yml +++ b/.github/workflows/build_pr_documentation.yml @@ -14,8 +14,6 @@ concurrency: jobs: build: uses: huggingface/doc-builder/.github/workflows/build_pr_documentation.yml@main - env: - MATURIN_PEP517_ARGS: "--features py311,pyo3/extension-module" with: commit_sha: ${{ github.event.pull_request.head.sha }} pr_number: ${{ github.event.number }} diff --git a/.github/workflows/python-bench.yml b/.github/workflows/python-bench.yml index cbfd62de..862d8e03 100644 --- a/.github/workflows/python-bench.yml +++ b/.github/workflows/python-bench.yml @@ -39,7 +39,7 @@ jobs: - name: Run tests working-directory: ./bindings/python run: | - cargo test --features py311 + cargo test pytest --benchmark-json output.json benches/ # Download previous benchmark result from cache (if exists) - name: Download previous benchmark data diff --git a/.github/workflows/python-release.yml b/.github/workflows/python-release.yml index 58c8efca..2cc96438 100644 --- a/.github/workflows/python-release.yml +++ b/.github/workflows/python-release.yml @@ -23,7 +23,6 @@ jobs: runs-on: ${{ matrix.platform.runner }} strategy: matrix: - pyfeature: ["py38", "py311"] platform: - runner: ubuntu-latest target: x86_64 @@ -46,20 +45,19 @@ jobs: uses: PyO3/maturin-action@v1 with: target: ${{ matrix.platform.target }} - args: --release --out dist --manifest-path bindings/python/Cargo.toml --features pyo3/extension-module,${{ matrix.pyfeature }} --no-default-features + args: --release --out dist --manifest-path bindings/python/Cargo.toml sccache: 'true' manylinux: auto - name: Upload wheels uses: actions/upload-artifact@v4 with: - name: wheels-linux-${{ matrix.platform.target }}-${{ matrix.pyfeature }} + name: wheels-linux-${{ matrix.platform.target }} path: dist musllinux: runs-on: ${{ matrix.platform.runner }} strategy: matrix: - pyfeature: ["py38", "py311"] platform: - runner: ubuntu-latest target: x86_64 @@ -78,20 +76,19 @@ jobs: uses: PyO3/maturin-action@v1 with: target: ${{ matrix.platform.target }} - args: --release --out dist --manifest-path bindings/python/Cargo.toml --features pyo3/extension-module,${{ matrix.pyfeature }} --no-default-features + args: --release --out dist --manifest-path bindings/python/Cargo.toml sccache: 'true' manylinux: musllinux_1_2 - name: Upload wheels uses: actions/upload-artifact@v4 with: - name: wheels-musllinux-${{ matrix.platform.target }}-${{ matrix.pyfeature }} + name: wheels-musllinux-${{ matrix.platform.target }} path: dist windows: runs-on: ${{ matrix.platform.runner }} strategy: matrix: - pyfeature: ["py38", "py311"] platform: - runner: windows-latest target: x64 @@ -107,19 +104,18 @@ jobs: uses: PyO3/maturin-action@v1 with: target: ${{ matrix.platform.target }} - args: --release --out dist --manifest-path bindings/python/Cargo.toml --features pyo3/extension-module,${{ matrix.pyfeature }} --no-default-features + args: --release --out dist --manifest-path bindings/python/Cargo.toml sccache: 'true' - name: Upload wheels uses: actions/upload-artifact@v4 with: - name: wheels-windows-${{ matrix.platform.target }}-${{ matrix.pyfeature }} + name: wheels-windows-${{ matrix.platform.target }} path: dist macos: runs-on: ${{ matrix.platform.runner }} strategy: matrix: - pyfeature: ["py38", "py311"] platform: - runner: macos-13 target: x86_64 @@ -134,12 +130,12 @@ jobs: uses: PyO3/maturin-action@v1 with: target: ${{ matrix.platform.target }} - args: --release --out dist --manifest-path bindings/python/Cargo.toml --features pyo3/extension-module,${{ matrix.pyfeature }} --no-default-features + args: --release --out dist --manifest-path bindings/python/Cargo.toml sccache: 'true' - name: Upload wheels uses: actions/upload-artifact@v4 with: - name: wheels-macos-${{ matrix.platform.target }}-${{ matrix.pyfeature }} + name: wheels-macos-${{ matrix.platform.target }} path: dist sdist: diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index 0b9dd32f..9fbbf2a7 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -7,14 +7,12 @@ jobs: build_and_test: name: Check everything builds & tests runs-on: ${{ matrix.os }} - env: - MATURIN_PEP517_ARGS: "--no-default-features --features ${{ matrix.version.pyfeature }},pyo3/extension-module" strategy: matrix: os: [ubuntu-latest, macos-13, windows-latest] # Lowest and highest, no version specified so that # new releases get automatically tested against - version: [{torch: torch==1.10, python: "3.8", pyfeature: "py38"}, {torch: torch, python: "3.12", pyfeature: "py311"}] + version: [{torch: torch==1.10, python: "3.8"}, {torch: torch, python: "3.12"}] # TODO this would include macos ARM target. # however jax has an illegal instruction issue # that exists only in CI (probably difference in instruction support). @@ -54,14 +52,14 @@ jobs: run: cargo fmt -- --check - name: Lint with Clippy - run: | - cargo clippy --features ${{ matrix.version.pyfeature }} --no-default-features -- -D warnings + run: cargo clippy --all-targets --all-features -- -D warnings - name: Run Audit run: cargo audit -D warnings - name: Install run: | + pip install -U pip pip install .[numpy,tensorflow] pip install ${{ matrix.version.torch }} @@ -84,7 +82,7 @@ jobs: - name: Run tests run: | - cargo test --features ${{ matrix.version.pyfeature }} --no-default-features + cargo test pip install .[testing] pytest -sv tests/ diff --git a/Dockerfile.s390x.test b/Dockerfile.s390x.test index cb5bdba7..d1dc7583 100644 --- a/Dockerfile.s390x.test +++ b/Dockerfile.s390x.test @@ -11,7 +11,6 @@ RUN /root/miniconda3/bin/pip install -U pip pytest COPY . . SHELL ["/bin/bash", "-c"] WORKDIR /safetensors/bindings/python/ -ENV MATURIN_PEP517_ARGS="--features py311,pyo3/extension-module" RUN source /root/.cargo/env && /root/miniconda3/bin/pip install -e . RUN /root/miniconda3/bin/pytest -sv tests/test_pt_* tests/test_simple.py # RUN /root/miniconda3/bin/python -c 'from huggingface_hub import hf_hub_download; filename = hf_hub_download("roberta-base", "model.safetensors"); from safetensors.torch import load_file; weights = load_file(filename); assert weights["roberta.embeddings.position_embeddings.weight"][0][0].abs().item() > 1e-10' diff --git a/bindings/python/Cargo.toml b/bindings/python/Cargo.toml index 4052b9d4..de7692bc 100644 --- a/bindings/python/Cargo.toml +++ b/bindings/python/Cargo.toml @@ -9,13 +9,8 @@ rust-version = "1.74" name = "safetensors_rust" crate-type = ["cdylib"] -[features] -py38 = ["pyo3/abi3-py38"] -py311 = ["pyo3/abi3-py311"] -default = ["py311"] - [dependencies] -pyo3 = { version = "0.23", features = ["abi3"] } +pyo3 = { version = "0.23", features = ["abi3", "abi3-py38"] } memmap2 = "0.9" serde_json = "1.0" diff --git a/bindings/python/py_src/safetensors/torch.py b/bindings/python/py_src/safetensors/torch.py index f3591ade..c3477aad 100644 --- a/bindings/python/py_src/safetensors/torch.py +++ b/bindings/python/py_src/safetensors/torch.py @@ -128,10 +128,7 @@ def _remove_duplicate_names( def save_model( - model: torch.nn.Module, - filename: str, - metadata: Optional[Dict[str, str]] = None, - force_contiguous: bool = True, + model: torch.nn.Module, filename: str, metadata: Optional[Dict[str, str]] = None, force_contiguous: bool = True ): """ Saves a given torch model to specified filename. @@ -177,10 +174,7 @@ def save_model( def load_model( - model: torch.nn.Module, - filename: Union[str, os.PathLike], - strict: bool = True, - device: Union[str, int] = "cpu", + model: torch.nn.Module, filename: Union[str, os.PathLike], strict: bool = True, device: Union[str, int] = "cpu" ) -> Tuple[List[str], List[str]]: """ Loads a given filename onto a torch model. @@ -408,7 +402,7 @@ def _view2torch(safeview) -> Dict[str, torch.Tensor]: return result -def _tobytes(tensor: torch.Tensor, name: str) -> Union[memoryview, bytes]: +def _tobytes(tensor: torch.Tensor, name: str) -> bytes: if tensor.layout != torch.strided: raise ValueError( f"You are trying to save a sparse tensor: `{name}` which this library does not support." @@ -462,11 +456,8 @@ def _tobytes(tensor: torch.Tensor, name: str) -> Union[memoryview, bytes]: } npdtype = NPDTYPES[tensor.dtype] # Not in place as that would potentially modify a live running model - data = data.view(npdtype).byteswap(inplace=False).view(np.uint8) - if sys.version_info >= (3, 11): - return data.data - else: - return data.tobytes() + data = data.view(npdtype).byteswap(inplace=False) + return data.tobytes() def _flatten(tensors: Dict[str, torch.Tensor]) -> Dict[str, Dict[str, Any]]: diff --git a/bindings/python/src/lib.rs b/bindings/python/src/lib.rs index 6a654ada..a65b1aab 100644 --- a/bindings/python/src/lib.rs +++ b/bindings/python/src/lib.rs @@ -1,7 +1,5 @@ #![deny(missing_docs)] //! Dummy doc -#[cfg(any(feature = "py38", feature = "py311"))] -mod view; use memmap2::{Mmap, MmapOptions}; use pyo3::exceptions::{PyException, PyFileNotFoundError}; use pyo3::prelude::*; @@ -12,14 +10,14 @@ use pyo3::Bound as PyBound; use pyo3::{intern, PyErr}; use safetensors::slice::TensorIndexer; use safetensors::tensor::{Dtype, Metadata, SafeTensors, TensorInfo, TensorView}; +use safetensors::View; +use std::borrow::Cow; use std::collections::HashMap; use std::fs::File; use std::iter::FromIterator; use std::ops::Bound; use std::path::PathBuf; use std::sync::Arc; -#[cfg(any(feature = "py38", feature = "py311"))] -use view::prepare; static TORCH_MODULE: GILOnceCell> = GILOnceCell::new(); static NUMPY_MODULE: GILOnceCell> = GILOnceCell::new(); @@ -27,10 +25,79 @@ static TENSORFLOW_MODULE: GILOnceCell> = GILOnceCell::new(); static FLAX_MODULE: GILOnceCell> = GILOnceCell::new(); static MLX_MODULE: GILOnceCell> = GILOnceCell::new(); -#[cfg(not(any(feature = "py38", feature = "py311")))] -compile_error!("At least one python version must be enabled, use `maturin develop` for python 3.11, `maturin develop --features py38,pyo3/extension-module --no-default-features` for python 3.8"); -#[cfg(all(feature = "py38", feature = "py311"))] -compile_error!("Only one python version must be enabled, make sure to deactivate default features for python <3.11"); +struct PyView<'a> { + shape: Vec, + dtype: Dtype, + data: PyBound<'a, PyBytes>, + data_len: usize, +} + +impl View for &PyView<'_> { + fn data(&self) -> std::borrow::Cow<[u8]> { + Cow::Borrowed(self.data.as_bytes()) + } + fn shape(&self) -> &[usize] { + &self.shape + } + fn dtype(&self) -> Dtype { + self.dtype + } + fn data_len(&self) -> usize { + self.data_len + } +} + +fn prepare(tensor_dict: HashMap>) -> PyResult> { + let mut tensors = HashMap::with_capacity(tensor_dict.len()); + for (tensor_name, tensor_desc) in &tensor_dict { + let shape: Vec = tensor_desc + .get_item("shape")? + .ok_or_else(|| SafetensorError::new_err(format!("Missing `shape` in {tensor_desc:?}")))? + .extract()?; + let pydata: PyBound = tensor_desc.get_item("data")?.ok_or_else(|| { + SafetensorError::new_err(format!("Missing `data` in {tensor_desc:?}")) + })?; + // Make sure it's extractable first. + let data: &[u8] = pydata.extract()?; + let data_len = data.len(); + let data: PyBound = pydata.extract()?; + let pydtype = tensor_desc.get_item("dtype")?.ok_or_else(|| { + SafetensorError::new_err(format!("Missing `dtype` in {tensor_desc:?}")) + })?; + let dtype: String = pydtype.extract()?; + let dtype = match dtype.as_ref() { + "bool" => Dtype::BOOL, + "int8" => Dtype::I8, + "uint8" => Dtype::U8, + "int16" => Dtype::I16, + "uint16" => Dtype::U16, + "int32" => Dtype::I32, + "uint32" => Dtype::U32, + "int64" => Dtype::I64, + "uint64" => Dtype::U64, + "float16" => Dtype::F16, + "float32" => Dtype::F32, + "float64" => Dtype::F64, + "bfloat16" => Dtype::BF16, + "float8_e4m3fn" => Dtype::F8_E4M3, + "float8_e5m2" => Dtype::F8_E5M2, + dtype_str => { + return Err(SafetensorError::new_err(format!( + "dtype {dtype_str} is not covered", + ))); + } + }; + + let tensor = PyView { + shape, + dtype, + data, + data_len, + }; + tensors.insert(tensor_name.to_string(), tensor); + } + Ok(tensors) +} /// Serializes raw data. /// diff --git a/bindings/python/src/view.rs b/bindings/python/src/view.rs deleted file mode 100644 index 1ce22ca7..00000000 --- a/bindings/python/src/view.rs +++ /dev/null @@ -1,137 +0,0 @@ -use crate::SafetensorError; -#[cfg(feature = "py311")] -use pyo3::buffer::PyBuffer; -use pyo3::prelude::*; -#[cfg(feature = "py38")] -use pyo3::types::PyBytes; -use pyo3::types::PyDict; -use pyo3::Bound as PyBound; -use safetensors::{Dtype, View}; -use std::borrow::Cow; -use std::collections::HashMap; - -#[cfg(feature = "py38")] -pub struct PyView<'a> { - shape: Vec, - dtype: Dtype, - data: PyBound<'a, PyBytes>, - data_len: usize, -} - -#[cfg(feature = "py311")] -pub struct PyView<'a> { - shape: Vec, - dtype: Dtype, - data: PyBuffer, - data_len: usize, - // Kept to keep the GIL open while we hold the buffer - _py: Python<'a>, -} - -impl View for &PyView<'_> { - #[cfg(feature = "py38")] - fn data(&self) -> std::borrow::Cow<[u8]> { - Cow::Borrowed(self.data.as_bytes()) - } - #[cfg(feature = "py311")] - fn data(&self) -> std::borrow::Cow<[u8]> { - // We already checked this in the Python side. - assert!(self.data.is_c_contiguous()); - // XXX: Ideally we could have at least readonly tensors - // assert!(self.data.readonly()); - // SAFETY: - // This is actually totally unsafe, PyBuffer is not immutable and could be changed from - // under us. - // This is made safer because we're still hanging to the GIL while treating - // this structure - Cow::Borrowed(unsafe { - std::slice::from_raw_parts(self.data.buf_ptr() as *const u8, self.data.item_count()) - }) - } - fn shape(&self) -> &[usize] { - &self.shape - } - fn dtype(&self) -> Dtype { - self.dtype - } - fn data_len(&self) -> usize { - self.data_len - } -} - -pub fn prepare(tensor_dict: HashMap>) -> PyResult> { - let mut tensors = HashMap::with_capacity(tensor_dict.len()); - for (tensor_name, tensor_desc) in &tensor_dict { - let shape: Vec = tensor_desc - .get_item("shape")? - .ok_or_else(|| SafetensorError::new_err(format!("Missing `shape` in {tensor_desc:?}")))? - .extract()?; - let pydata: PyBound = tensor_desc.get_item("data")?.ok_or_else(|| { - SafetensorError::new_err(format!("Missing `data` in {tensor_desc:?}")) - })?; - - let pydtype = tensor_desc.get_item("dtype")?.ok_or_else(|| { - SafetensorError::new_err(format!("Missing `dtype` in {tensor_desc:?}")) - })?; - let dtype: String = pydtype.extract()?; - let dtype = match dtype.as_ref() { - "bool" => Dtype::BOOL, - "int8" => Dtype::I8, - "uint8" => Dtype::U8, - "int16" => Dtype::I16, - "uint16" => Dtype::U16, - "int32" => Dtype::I32, - "uint32" => Dtype::U32, - "int64" => Dtype::I64, - "uint64" => Dtype::U64, - "float16" => Dtype::F16, - "float32" => Dtype::F32, - "float64" => Dtype::F64, - "bfloat16" => Dtype::BF16, - "float8_e4m3fn" => Dtype::F8_E4M3, - "float8_e5m2" => Dtype::F8_E5M2, - dtype_str => { - return Err(SafetensorError::new_err(format!( - "dtype {dtype_str} is not covered", - ))); - } - }; - - #[cfg(feature = "py311")] - let tensor = { - let data: PyBuffer = pydata.extract()?; - if !data.is_c_contiguous() { - return Err(SafetensorError::new_err("Python buffer is not contiguous")); - } - // XXX Ideally this would be true. - // if !data.readonly() { - // return Err(SafetensorError::new_err("Python buffer is not readonly")); - // } - let data_len = data.item_count(); - let py = pydata.py(); - PyView { - shape, - dtype, - data, - data_len, - _py: py, - } - }; - - #[cfg(feature = "py38")] - let tensor = { - let data: &[u8] = pydata.extract()?; - let data_len = data.len(); - let data: PyBound = pydata.extract()?; - PyView { - shape, - dtype, - data, - data_len, - } - }; - - tensors.insert(tensor_name.to_string(), tensor); - } - Ok(tensors) -} diff --git a/bindings/python/tests/test_pt_comparison.py b/bindings/python/tests/test_pt_comparison.py index 10e8cc05..36529295 100644 --- a/bindings/python/tests/test_pt_comparison.py +++ b/bindings/python/tests/test_pt_comparison.py @@ -264,6 +264,7 @@ def test_deserialization_device(self): torch.set_default_device(torch.device("cuda:0")) weights = load_file(self.sf_filename) self.assertEqual(weights["test"].device, torch.device("cpu")) + torch.set_default_device(torch.device("cpu")) @unittest.skipIf(not torch.cuda.is_available(), "Cuda is not available") def test_deserialization_safe_gpu(self): From a14d35fda0a4423257dfcfb87b982e38b5f3cae9 Mon Sep 17 00:00:00 2001 From: Nicolas Patry Date: Mon, 17 Mar 2025 14:59:51 +0100 Subject: [PATCH 10/37] Fix test (#591) * Revert "Demoing zero-copy save. (#567)" This reverts commit 4b3864c802d727be3cd67e5107a0f873d047ae69. * Fixing the test and removing the PyBuffer thing. * Remove features from bench. From 7d5af853631628137a79341ddc5611d18a17f3fe Mon Sep 17 00:00:00 2001 From: Nicolas Patry Date: Tue, 18 Mar 2025 10:00:47 +0100 Subject: [PATCH 11/37] [WIP] Enabling free-threaded python (without warning). + pyo3 0.24 (#592) * [WIP] Enabling free-threaded python (without warning). + pyo3 0.24 * Adding free threaded ? * Make simple tests thread resistant + Fix 3.13t tests ?. * ? * Yaml insanity. * Names. * Last attempt. * Split tensorflow * Using index for freethreaded build. * So tiring. * names everywhere. * Fixing the workflow jax + freethreaded doesn't work. --- .github/workflows/python.yml | 33 +++++++++++++++--- bindings/python/Cargo.toml | 2 +- bindings/python/src/lib.rs | 51 ++++++++++++++++------------ bindings/python/tests/test_simple.py | 33 ++++++++++-------- 4 files changed, 77 insertions(+), 42 deletions(-) diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index 9fbbf2a7..f132901f 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -12,7 +12,7 @@ jobs: os: [ubuntu-latest, macos-13, windows-latest] # Lowest and highest, no version specified so that # new releases get automatically tested against - version: [{torch: torch==1.10, python: "3.8"}, {torch: torch, python: "3.12"}] + version: [{torch: torch==1.10, python: "3.8", arch: "x64"}, {torch: torch, python: "3.12", arch: "x64"}] # TODO this would include macos ARM target. # however jax has an illegal instruction issue # that exists only in CI (probably difference in instruction support). @@ -21,6 +21,12 @@ jobs: # version: # torch: torch # python: "3.11" + include: + - os: ubuntu-latest + version: + torch: torch + python: "3.13" + arch: "x64-freethreaded" defaults: run: working-directory: ./bindings/python @@ -46,7 +52,7 @@ jobs: uses: actions/setup-python@v5 with: python-version: ${{ matrix.version.python }} - architecture: "x64" + architecture: ${{ matrix.version.arch }} - name: Lint with RustFmt run: cargo fmt -- --check @@ -60,12 +66,29 @@ jobs: - name: Install run: | pip install -U pip - pip install .[numpy,tensorflow] + pip install .[numpy] + + - name: Install (torch) + if: matrix.version.arch != 'x64-freethreaded' + run: | pip install ${{ matrix.version.torch }} + shell: bash - - name: Install (jax, flax) - if: matrix.os != 'windows-latest' + - name: Install (torch freethreaded) + if: matrix.version.arch == 'x64-freethreaded' + run: | + pip install ${{ matrix.version.torch }} --index-url https://download.pytorch.org/whl/cu126 + shell: bash + + - name: Install (tensorflow) + if: matrix.version.arch != 'x64-freethreaded' run: | + pip install .[tensorflow] + shell: bash + + - name: Install (jax, flax) + if: matrix.os != 'windows-latest' && matrix.version.arch != "x64-freethreaded" + run: pip install .[jax] shell: bash diff --git a/bindings/python/Cargo.toml b/bindings/python/Cargo.toml index de7692bc..301cc9e7 100644 --- a/bindings/python/Cargo.toml +++ b/bindings/python/Cargo.toml @@ -10,7 +10,7 @@ name = "safetensors_rust" crate-type = ["cdylib"] [dependencies] -pyo3 = { version = "0.23", features = ["abi3", "abi3-py38"] } +pyo3 = { version = "0.24", features = ["abi3", "abi3-py38"] } memmap2 = "0.9" serde_json = "1.0" diff --git a/bindings/python/src/lib.rs b/bindings/python/src/lib.rs index a65b1aab..e16d7fdd 100644 --- a/bindings/python/src/lib.rs +++ b/bindings/python/src/lib.rs @@ -3,7 +3,7 @@ use memmap2::{Mmap, MmapOptions}; use pyo3::exceptions::{PyException, PyFileNotFoundError}; use pyo3::prelude::*; -use pyo3::sync::GILOnceCell; +use pyo3::sync::OnceLockExt; use pyo3::types::IntoPyDict; use pyo3::types::{PyBool, PyByteArray, PyBytes, PyDict, PyList, PySlice}; use pyo3::Bound as PyBound; @@ -18,12 +18,13 @@ use std::iter::FromIterator; use std::ops::Bound; use std::path::PathBuf; use std::sync::Arc; +use std::sync::OnceLock; -static TORCH_MODULE: GILOnceCell> = GILOnceCell::new(); -static NUMPY_MODULE: GILOnceCell> = GILOnceCell::new(); -static TENSORFLOW_MODULE: GILOnceCell> = GILOnceCell::new(); -static FLAX_MODULE: GILOnceCell> = GILOnceCell::new(); -static MLX_MODULE: GILOnceCell> = GILOnceCell::new(); +static TORCH_MODULE: OnceLock> = OnceLock::new(); +static NUMPY_MODULE: OnceLock> = OnceLock::new(); +static TENSORFLOW_MODULE: OnceLock> = OnceLock::new(); +static FLAX_MODULE: OnceLock> = OnceLock::new(); +static MLX_MODULE: OnceLock> = OnceLock::new(); struct PyView<'a> { shape: Vec, @@ -342,7 +343,7 @@ enum Storage { /// This allows us to not manage it /// so Pytorch can handle the whole lifecycle. /// https://pytorch.org/docs/stable/storage.html#torch.TypedStorage.from_file. - TorchStorage(GILOnceCell), + TorchStorage(OnceLock), } #[derive(Debug, PartialEq, Eq, PartialOrd)] @@ -422,11 +423,11 @@ impl Open { match framework { Framework::Pytorch => { let module = PyModule::import(py, intern!(py, "torch"))?; - TORCH_MODULE.get_or_init(py, || module.into()) + TORCH_MODULE.get_or_init_py_attached(py, || module.into()) } _ => { let module = PyModule::import(py, intern!(py, "numpy"))?; - NUMPY_MODULE.get_or_init(py, || module.into()) + NUMPY_MODULE.get_or_init_py_attached(py, || module.into()) } }; @@ -444,7 +445,13 @@ impl Open { // Same for torch.asarray which is necessary for zero-copy tensor if version >= Version::new(1, 11, 0) { // storage = torch.ByteStorage.from_file(filename, shared=False, size=size).untyped() - let py_filename: PyObject = filename.into_pyobject(py)?.into(); + let py_filename: PyObject = filename + .to_str() + .ok_or_else(|| { + SafetensorError::new_err(format!("Path {filename:?} is not a string")) + })? + .into_pyobject(py)? + .into(); let size: PyObject = buffer.len().into_pyobject(py)?.into(); let shared: PyObject = PyBool::new(py, false).to_owned().into(); let (size_name, storage_name) = if version >= Version::new(2, 0, 0) { @@ -466,8 +473,8 @@ impl Open { Err(_) => storage.getattr(intern!(py, "_untyped"))?, }; let storage = untyped.call0()?.into_pyobject(py)?.into(); - let gil_storage = GILOnceCell::new(); - gil_storage.get_or_init(py, || storage); + let gil_storage = OnceLock::new(); + gil_storage.get_or_init_py_attached(py, || storage); Ok(Storage::TorchStorage(gil_storage)) } else { @@ -579,7 +586,7 @@ impl Open { let stop = (info.data_offsets.1 + self.offset) as isize; let slice = PySlice::new(py, start, stop, 1); let storage: &PyObject = storage - .get(py) + .get() .ok_or_else(|| SafetensorError::new_err("Could not find storage"))?; let storage: &PyBound = storage.bind(py); let storage_slice = storage @@ -954,7 +961,7 @@ impl PySafeSlice { let stop = (self.info.data_offsets.1 + self.offset) as isize; let slice = PySlice::new(py, start, stop, 1); let storage: &PyObject = storage - .get(py) + .get() .ok_or_else(|| SafetensorError::new_err("Could not find storage"))?; let storage: &PyBound<'_, PyAny> = storage.bind(py); @@ -1025,10 +1032,10 @@ impl PySafeSlice { fn get_module<'a>( py: Python<'a>, - cell: &'static GILOnceCell>, + cell: &'static OnceLock>, ) -> PyResult<&'a PyBound<'a, PyModule>> { let module: &PyBound<'a, PyModule> = cell - .get(py) + .get() .ok_or_else(|| SafetensorError::new_err("Could not find module"))? .bind(py); Ok(module) @@ -1045,7 +1052,7 @@ fn create_tensor<'a>( let (module, is_numpy): (&PyBound<'_, PyModule>, bool) = match framework { Framework::Pytorch => ( TORCH_MODULE - .get(py) + .get() .ok_or_else(|| { SafetensorError::new_err(format!("Could not find module {framework:?}",)) })? @@ -1054,7 +1061,7 @@ fn create_tensor<'a>( ), _ => ( NUMPY_MODULE - .get(py) + .get() .ok_or_else(|| { SafetensorError::new_err(format!("Could not find module {framework:?}",)) })? @@ -1097,7 +1104,7 @@ fn create_tensor<'a>( Framework::Flax => { let module = Python::with_gil(|py| -> PyResult<&Py> { let module = PyModule::import(py, intern!(py, "jax"))?; - Ok(FLAX_MODULE.get_or_init(py, || module.into())) + Ok(FLAX_MODULE.get_or_init_py_attached(py, || module.into())) })? .bind(py); module @@ -1108,7 +1115,7 @@ fn create_tensor<'a>( Framework::Tensorflow => { let module = Python::with_gil(|py| -> PyResult<&Py> { let module = PyModule::import(py, intern!(py, "tensorflow"))?; - Ok(TENSORFLOW_MODULE.get_or_init(py, || module.into())) + Ok(TENSORFLOW_MODULE.get_or_init_py_attached(py, || module.into())) })? .bind(py); module @@ -1118,7 +1125,7 @@ fn create_tensor<'a>( Framework::Mlx => { let module = Python::with_gil(|py| -> PyResult<&Py> { let module = PyModule::import(py, intern!(py, "mlx"))?; - Ok(MLX_MODULE.get_or_init(py, || module.into())) + Ok(MLX_MODULE.get_or_init_py_attached(py, || module.into())) })? .bind(py); module @@ -1192,7 +1199,7 @@ pyo3::create_exception!( ); /// A Python module implemented in Rust. -#[pymodule] +#[pymodule(gil_used = false)] fn _safetensors_rust(m: &PyBound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(serialize, m)?)?; m.add_function(wrap_pyfunction!(serialize_file, m)?)?; diff --git a/bindings/python/tests/test_simple.py b/bindings/python/tests/test_simple.py index 8e840138..d198391f 100644 --- a/bindings/python/tests/test_simple.py +++ b/bindings/python/tests/test_simple.py @@ -1,5 +1,6 @@ import os import tempfile +import threading import unittest from pathlib import Path @@ -117,9 +118,10 @@ def test_accept_path(self): "a": torch.zeros((2, 2)), "b": torch.zeros((2, 3), dtype=torch.uint8), } - save_file_pt(tensors, Path("./out.safetensors")) - load_file_pt(Path("./out.safetensors")) - os.remove(Path("./out.safetensors")) + filename = f"./out_{threading.get_ident()}.safetensors" + save_file_pt(tensors, Path(filename)) + load_file_pt(Path(filename)) + os.remove(Path(filename)) def test_pt_sf_save_model_overlapping_storage(self): m = torch.randn(10) @@ -157,14 +159,14 @@ def test_get_correctly_dropped(self): "a": torch.zeros((2, 2)), "b": torch.zeros((2, 3), dtype=torch.uint8), } - save_file_pt(tensors, "./out.safetensors") - with safe_open("./out.safetensors", framework="pt") as f: + save_file_pt(tensors, "./out_windows.safetensors") + with safe_open("./out_windows.safetensors", framework="pt") as f: pass with self.assertRaises(SafetensorError): print(f.keys()) - with open("./out.safetensors", "w") as g: + with open("./out_windows.safetensors", "w") as g: g.write("something") @@ -188,11 +190,11 @@ def assertTensorEqual(self, tensors1, tensors2, equality_fn): def test_numpy_example(self): tensors = {"a": np.zeros((2, 2)), "b": np.zeros((2, 3), dtype=np.uint8)} - save_file(tensors, "./out.safetensors") + save_file(tensors, "./out_np.safetensors") out = save(tensors) # Now loading - loaded = load_file("./out.safetensors") + loaded = load_file("./out_np.safetensors") self.assertTensorEqual(tensors, loaded, np.allclose) loaded = load(out) @@ -220,10 +222,11 @@ def test_torch_example(self): # test to be correct. tensors2 = tensors.copy() - save_file_pt(tensors, "./out.safetensors") + filename = f"./out_pt_{threading.get_ident()}.safetensors" + save_file_pt(tensors, filename) # Now loading - loaded = load_file_pt("./out.safetensors") + loaded = load_file_pt(filename) self.assertTensorEqual(tensors2, loaded, torch.allclose) def test_exception(self): @@ -237,10 +240,11 @@ def test_torch_slice(self): tensors = { "a": A, } - save_file_pt(tensors, "./slice.safetensors") + ident = threading.get_ident() + save_file_pt(tensors, f"./slice_{ident}.safetensors") # Now loading - with safe_open("./slice.safetensors", framework="pt", device="cpu") as f: + with safe_open(f"./slice_{ident}.safetensors", framework="pt", device="cpu") as f: slice_ = f.get_slice("a") tensor = slice_[:] self.assertEqual(list(tensor.shape), [10, 5]) @@ -283,10 +287,11 @@ def test_numpy_slice(self): tensors = { "a": A, } - save_file(tensors, "./slice.safetensors") + filename = f"./slice_{threading.get_ident()}.safetensors" + save_file(tensors, filename) # Now loading - with safe_open("./slice.safetensors", framework="np", device="cpu") as f: + with safe_open(filename, framework="np", device="cpu") as f: slice_ = f.get_slice("a") tensor = slice_[:] self.assertEqual(list(tensor.shape), [10, 5]) From dfd1b9f5378e3ac9ff3e85f562d1a074bab2a81d Mon Sep 17 00:00:00 2001 From: Nicolas Patry Date: Mon, 5 May 2025 21:32:38 +0200 Subject: [PATCH 12/37] Fix the bench action ? (#603) * Fix the bench action ? * Fixing the project by removing python 3.7 support from the bench. * Removing 3.8 support (messes up tensorflow pinned version). --- .github/workflows/python-bench.yml | 10 +- .github/workflows/python.yml | 2 +- bindings/python/pyproject.toml | 2 +- bindings/python/uv.lock | 2568 ++++++++++++++++++++++++++++ 4 files changed, 2575 insertions(+), 7 deletions(-) create mode 100644 bindings/python/uv.lock diff --git a/.github/workflows/python-bench.yml b/.github/workflows/python-bench.yml index 862d8e03..c2f756fb 100644 --- a/.github/workflows/python-bench.yml +++ b/.github/workflows/python-bench.yml @@ -25,22 +25,22 @@ jobs: components: rustfmt, clippy - name: Install Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: - python-version: "3.11" + python-version: "3.12" architecture: "x64" - name: Install working-directory: ./bindings/python run: | - pip install -U pip - pip install .[dev] + pip install -U pip uv + uv sync --extra dev - name: Run tests working-directory: ./bindings/python run: | cargo test - pytest --benchmark-json output.json benches/ + uv run pytest --benchmark-json output.json benches/ # Download previous benchmark result from cache (if exists) - name: Download previous benchmark data uses: actions/cache@v4 diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index f132901f..fa99ae17 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -12,7 +12,7 @@ jobs: os: [ubuntu-latest, macos-13, windows-latest] # Lowest and highest, no version specified so that # new releases get automatically tested against - version: [{torch: torch==1.10, python: "3.8", arch: "x64"}, {torch: torch, python: "3.12", arch: "x64"}] + version: [{torch: torch==1.10, python: "3.9", arch: "x64"}, {torch: torch, python: "3.12", arch: "x64"}] # TODO this would include macos ARM target. # however jax has an illegal instruction issue # that exists only in CI (probably difference in instruction support). diff --git a/bindings/python/pyproject.toml b/bindings/python/pyproject.toml index 2f1123f6..f68234a1 100644 --- a/bindings/python/pyproject.toml +++ b/bindings/python/pyproject.toml @@ -1,6 +1,6 @@ [project] name = 'safetensors' -requires-python = '>=3.7' +requires-python = '>=3.9' authors = [ {name = 'Nicolas Patry', email = 'patry.nicolas@protonmail.com'} ] diff --git a/bindings/python/uv.lock b/bindings/python/uv.lock new file mode 100644 index 00000000..ed80f7ea --- /dev/null +++ b/bindings/python/uv.lock @@ -0,0 +1,2568 @@ +version = 1 +revision = 1 +requires-python = ">=3.9" +resolution-markers = [ + "python_full_version >= '3.12'", + "python_full_version == '3.11.*'", + "python_full_version == '3.10.*'", + "python_full_version < '3.10'", +] + +[[package]] +name = "absl-py" +version = "2.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b5/f0/e6342091061ed3a46aadc116b13edd7bb5249c3ab1b3ef07f24b0c248fc3/absl_py-2.2.2.tar.gz", hash = "sha256:bf25b2c2eed013ca456918c453d687eab4e8309fba81ee2f4c1a6aa2494175eb", size = 119982 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f6/d4/349f7f4bd5ea92dab34f5bb0fe31775ef6c311427a14d5a5b31ecb442341/absl_py-2.2.2-py3-none-any.whl", hash = "sha256:e5797bc6abe45f64fd95dc06394ca3f2bedf3b5d895e9da691c9ee3397d70092", size = 135565 }, +] + +[[package]] +name = "anyio" +version = "4.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "idna" }, + { name = "sniffio" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/95/7d/4c1bd541d4dffa1b52bd83fb8527089e097a106fc90b467a7313b105f840/anyio-4.9.0.tar.gz", hash = "sha256:673c0c244e15788651a4ff38710fea9675823028a6f08a5eda409e0c9840a028", size = 190949 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a1/ee/48ca1a7c89ffec8b6a0c5d02b89c305671d5ffd8d3c94acf8b8c408575bb/anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c", size = 100916 }, +] + +[[package]] +name = "astor" +version = "0.8.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5a/21/75b771132fee241dfe601d39ade629548a9626d1d39f333fde31bc46febe/astor-0.8.1.tar.gz", hash = "sha256:6a6effda93f4e1ce9f618779b2dd1d9d84f1e32812c23a29b3fff6fd7f63fa5e", size = 35090 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c3/88/97eef84f48fa04fbd6750e62dcceafba6c63c81b7ac1420856c8dcc0a3f9/astor-0.8.1-py2.py3-none-any.whl", hash = "sha256:070a54e890cefb5b3739d19f30f5a5ec840ffc9c50ffa7d23cc9fc1a38ebbfc5", size = 27488 }, +] + +[[package]] +name = "astunparse" +version = "1.6.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, + { name = "wheel" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f3/af/4182184d3c338792894f34a62672919db7ca008c89abee9b564dd34d8029/astunparse-1.6.3.tar.gz", hash = "sha256:5ad93a8456f0d084c3456d059fd9a92cce667963232cbf763eac3bc5b7940872", size = 18290 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2b/03/13dde6512ad7b4557eb792fbcf0c653af6076b81e5941d36ec61f7ce6028/astunparse-1.6.3-py2.py3-none-any.whl", hash = "sha256:c2652417f2c8b5bb325c885ae329bdf3f86424075c4fd1a128674bc6fba4b8e8", size = 12732 }, +] + +[[package]] +name = "attrs" +version = "25.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5a/b0/1367933a8532ee6ff8d63537de4f1177af4bff9f3e829baf7331f595bb24/attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b", size = 812032 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3", size = 63815 }, +] + +[[package]] +name = "black" +version = "22.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "mypy-extensions" }, + { name = "pathspec" }, + { name = "platformdirs" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions", marker = "python_full_version < '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ee/1f/b29c7371958ab41a800f8718f5d285bf4333b8d0b5a5a8650234463ee644/black-22.3.0.tar.gz", hash = "sha256:35020b8886c022ced9282b51b5a875b6d1ab0c387b31a065b84db7c33085ca79", size = 554277 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e1/1b/3ba8128f0b6e86d87343a1275e17baeeeee1a89e02d2a0d275f472be3310/black-22.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:2497f9c2386572e28921fa8bec7be3e51de6801f7459dffd6e62492531c47e09", size = 2392131 }, + { url = "https://files.pythonhosted.org/packages/31/1a/0233cdbfbcfbc0864d815cf28ca40cdb65acf3601f3bf943d6d04e867858/black-22.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5795a0375eb87bfe902e80e0c8cfaedf8af4d49694d69161e5bd3206c18618bb", size = 1339315 }, + { url = "https://files.pythonhosted.org/packages/4f/98/8f775455f99a8e4b16d8d26efdc8292f99b1c0ebfe04357d800ff379c0ae/black-22.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e3556168e2e5c49629f7b0f377070240bd5511e45e25a4497bb0073d9dda776a", size = 1212888 }, + { url = "https://files.pythonhosted.org/packages/93/98/6f7c2f7f81d87b5771febcee933ba58640fca29a767262763bc353074f63/black-22.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67c8301ec94e3bcc8906740fe071391bce40a862b7be0b86fb5382beefecd968", size = 1474258 }, + { url = "https://files.pythonhosted.org/packages/5f/10/613ddfc646a1f51f24ad9173e4969025210fe9034a69718f08297ecb9b76/black-22.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:fd57160949179ec517d32ac2ac898b5f20d68ed1a9c977346efbac9c2f1e779d", size = 1137867 }, + { url = "https://files.pythonhosted.org/packages/a4/43/940f848d7d1ecf0be18453a293e5736e9ce60fd6197386a791bcc491f232/black-22.3.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5891ef8abc06576985de8fa88e95ab70641de6c1fca97e2a15820a9b69e51b20", size = 2390442 }, + { url = "https://files.pythonhosted.org/packages/e5/b7/e4e8907dffdac70f018ddb89681dbc77cbc7ac78d1f8a39259110a7e7943/black-22.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:30d78ba6bf080eeaf0b7b875d924b15cd46fec5fd044ddfbad38c8ea9171043a", size = 1338106 }, + { url = "https://files.pythonhosted.org/packages/56/74/c27c496223168af625d6bba8a14bc581e7742bf7248504a4b5743c374767/black-22.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ee8f1f7228cce7dffc2b464f07ce769f478968bfb3dd1254a4c2eeed84928aad", size = 1212264 }, + { url = "https://files.pythonhosted.org/packages/51/ec/c87695b087b7525fd9c7732c630455f231d3df9a300b730bd0e04ea00f84/black-22.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ee227b696ca60dd1c507be80a6bc849a5a6ab57ac7352aad1ffec9e8b805f21", size = 1473733 }, + { url = "https://files.pythonhosted.org/packages/5b/f9/e7aca76001a702dc258fb0443ca2553d5db13a3515c09062fbf344184363/black-22.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:9b542ced1ec0ceeff5b37d69838106a6348e60db7b8fdd245294dc1d26136265", size = 1137278 }, + { url = "https://files.pythonhosted.org/packages/2e/ef/a38a2189959246543e60859fb65bd3143129f6d18dfc7bcdd79217f81ca2/black-22.3.0-py3-none-any.whl", hash = "sha256:bc58025940a896d7e5356952228b68f793cf5fcb342be703c3a2669a1488cb72", size = 153859 }, +] + +[[package]] +name = "certifi" +version = "2025.4.26" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e8/9e/c05b3920a3b7d20d3d3310465f50348e5b3694f4f88c6daf736eef3024c4/certifi-2025.4.26.tar.gz", hash = "sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6", size = 160705 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4a/7e/3db2bd1b1f9e95f7cddca6d6e75e2f2bd9f51b1246e546d88addca0106bd/certifi-2025.4.26-py3-none-any.whl", hash = "sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3", size = 159618 }, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e4/33/89c2ced2b67d1c2a61c19c6751aa8902d46ce3dacb23600a283619f5a12d/charset_normalizer-3.4.2.tar.gz", hash = "sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63", size = 126367 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/95/28/9901804da60055b406e1a1c5ba7aac1276fb77f1dde635aabfc7fd84b8ab/charset_normalizer-3.4.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c48ed483eb946e6c04ccbe02c6b4d1d48e51944b6db70f697e089c193404941", size = 201818 }, + { url = "https://files.pythonhosted.org/packages/d9/9b/892a8c8af9110935e5adcbb06d9c6fe741b6bb02608c6513983048ba1a18/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2d318c11350e10662026ad0eb71bb51c7812fc8590825304ae0bdd4ac283acd", size = 144649 }, + { url = "https://files.pythonhosted.org/packages/7b/a5/4179abd063ff6414223575e008593861d62abfc22455b5d1a44995b7c101/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9cbfacf36cb0ec2897ce0ebc5d08ca44213af24265bd56eca54bee7923c48fd6", size = 155045 }, + { url = "https://files.pythonhosted.org/packages/3b/95/bc08c7dfeddd26b4be8c8287b9bb055716f31077c8b0ea1cd09553794665/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18dd2e350387c87dabe711b86f83c9c78af772c748904d372ade190b5c7c9d4d", size = 147356 }, + { url = "https://files.pythonhosted.org/packages/a8/2d/7a5b635aa65284bf3eab7653e8b4151ab420ecbae918d3e359d1947b4d61/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8075c35cd58273fee266c58c0c9b670947c19df5fb98e7b66710e04ad4e9ff86", size = 149471 }, + { url = "https://files.pythonhosted.org/packages/ae/38/51fc6ac74251fd331a8cfdb7ec57beba8c23fd5493f1050f71c87ef77ed0/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5bf4545e3b962767e5c06fe1738f951f77d27967cb2caa64c28be7c4563e162c", size = 151317 }, + { url = "https://files.pythonhosted.org/packages/b7/17/edee1e32215ee6e9e46c3e482645b46575a44a2d72c7dfd49e49f60ce6bf/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7a6ab32f7210554a96cd9e33abe3ddd86732beeafc7a28e9955cdf22ffadbab0", size = 146368 }, + { url = "https://files.pythonhosted.org/packages/26/2c/ea3e66f2b5f21fd00b2825c94cafb8c326ea6240cd80a91eb09e4a285830/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b33de11b92e9f75a2b545d6e9b6f37e398d86c3e9e9653c4864eb7e89c5773ef", size = 154491 }, + { url = "https://files.pythonhosted.org/packages/52/47/7be7fa972422ad062e909fd62460d45c3ef4c141805b7078dbab15904ff7/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8755483f3c00d6c9a77f490c17e6ab0c8729e39e6390328e42521ef175380ae6", size = 157695 }, + { url = "https://files.pythonhosted.org/packages/2f/42/9f02c194da282b2b340f28e5fb60762de1151387a36842a92b533685c61e/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:68a328e5f55ec37c57f19ebb1fdc56a248db2e3e9ad769919a58672958e8f366", size = 154849 }, + { url = "https://files.pythonhosted.org/packages/67/44/89cacd6628f31fb0b63201a618049be4be2a7435a31b55b5eb1c3674547a/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:21b2899062867b0e1fde9b724f8aecb1af14f2778d69aacd1a5a1853a597a5db", size = 150091 }, + { url = "https://files.pythonhosted.org/packages/1f/79/4b8da9f712bc079c0f16b6d67b099b0b8d808c2292c937f267d816ec5ecc/charset_normalizer-3.4.2-cp310-cp310-win32.whl", hash = "sha256:e8082b26888e2f8b36a042a58307d5b917ef2b1cacab921ad3323ef91901c71a", size = 98445 }, + { url = "https://files.pythonhosted.org/packages/7d/d7/96970afb4fb66497a40761cdf7bd4f6fca0fc7bafde3a84f836c1f57a926/charset_normalizer-3.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:f69a27e45c43520f5487f27627059b64aaf160415589230992cec34c5e18a509", size = 105782 }, + { url = "https://files.pythonhosted.org/packages/05/85/4c40d00dcc6284a1c1ad5de5e0996b06f39d8232f1031cd23c2f5c07ee86/charset_normalizer-3.4.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:be1e352acbe3c78727a16a455126d9ff83ea2dfdcbc83148d2982305a04714c2", size = 198794 }, + { url = "https://files.pythonhosted.org/packages/41/d9/7a6c0b9db952598e97e93cbdfcb91bacd89b9b88c7c983250a77c008703c/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa88ca0b1932e93f2d961bf3addbb2db902198dca337d88c89e1559e066e7645", size = 142846 }, + { url = "https://files.pythonhosted.org/packages/66/82/a37989cda2ace7e37f36c1a8ed16c58cf48965a79c2142713244bf945c89/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d524ba3f1581b35c03cb42beebab4a13e6cdad7b36246bd22541fa585a56cccd", size = 153350 }, + { url = "https://files.pythonhosted.org/packages/df/68/a576b31b694d07b53807269d05ec3f6f1093e9545e8607121995ba7a8313/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28a1005facc94196e1fb3e82a3d442a9d9110b8434fc1ded7a24a2983c9888d8", size = 145657 }, + { url = "https://files.pythonhosted.org/packages/92/9b/ad67f03d74554bed3aefd56fe836e1623a50780f7c998d00ca128924a499/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fdb20a30fe1175ecabed17cbf7812f7b804b8a315a25f24678bcdf120a90077f", size = 147260 }, + { url = "https://files.pythonhosted.org/packages/a6/e6/8aebae25e328160b20e31a7e9929b1578bbdc7f42e66f46595a432f8539e/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f5d9ed7f254402c9e7d35d2f5972c9bbea9040e99cd2861bd77dc68263277c7", size = 149164 }, + { url = "https://files.pythonhosted.org/packages/8b/f2/b3c2f07dbcc248805f10e67a0262c93308cfa149a4cd3d1fe01f593e5fd2/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:efd387a49825780ff861998cd959767800d54f8308936b21025326de4b5a42b9", size = 144571 }, + { url = "https://files.pythonhosted.org/packages/60/5b/c3f3a94bc345bc211622ea59b4bed9ae63c00920e2e8f11824aa5708e8b7/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f0aa37f3c979cf2546b73e8222bbfa3dc07a641585340179d768068e3455e544", size = 151952 }, + { url = "https://files.pythonhosted.org/packages/e2/4d/ff460c8b474122334c2fa394a3f99a04cf11c646da895f81402ae54f5c42/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e70e990b2137b29dc5564715de1e12701815dacc1d056308e2b17e9095372a82", size = 155959 }, + { url = "https://files.pythonhosted.org/packages/a2/2b/b964c6a2fda88611a1fe3d4c400d39c66a42d6c169c924818c848f922415/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0c8c57f84ccfc871a48a47321cfa49ae1df56cd1d965a09abe84066f6853b9c0", size = 153030 }, + { url = "https://files.pythonhosted.org/packages/59/2e/d3b9811db26a5ebf444bc0fa4f4be5aa6d76fc6e1c0fd537b16c14e849b6/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6b66f92b17849b85cad91259efc341dce9c1af48e2173bf38a85c6329f1033e5", size = 148015 }, + { url = "https://files.pythonhosted.org/packages/90/07/c5fd7c11eafd561bb51220d600a788f1c8d77c5eef37ee49454cc5c35575/charset_normalizer-3.4.2-cp311-cp311-win32.whl", hash = "sha256:daac4765328a919a805fa5e2720f3e94767abd632ae410a9062dff5412bae65a", size = 98106 }, + { url = "https://files.pythonhosted.org/packages/a8/05/5e33dbef7e2f773d672b6d79f10ec633d4a71cd96db6673625838a4fd532/charset_normalizer-3.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:e53efc7c7cee4c1e70661e2e112ca46a575f90ed9ae3fef200f2a25e954f4b28", size = 105402 }, + { url = "https://files.pythonhosted.org/packages/d7/a4/37f4d6035c89cac7930395a35cc0f1b872e652eaafb76a6075943754f095/charset_normalizer-3.4.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0c29de6a1a95f24b9a1aa7aefd27d2487263f00dfd55a77719b530788f75cff7", size = 199936 }, + { url = "https://files.pythonhosted.org/packages/ee/8a/1a5e33b73e0d9287274f899d967907cd0bf9c343e651755d9307e0dbf2b3/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cddf7bd982eaa998934a91f69d182aec997c6c468898efe6679af88283b498d3", size = 143790 }, + { url = "https://files.pythonhosted.org/packages/66/52/59521f1d8e6ab1482164fa21409c5ef44da3e9f653c13ba71becdd98dec3/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcbe676a55d7445b22c10967bceaaf0ee69407fbe0ece4d032b6eb8d4565982a", size = 153924 }, + { url = "https://files.pythonhosted.org/packages/86/2d/fb55fdf41964ec782febbf33cb64be480a6b8f16ded2dbe8db27a405c09f/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d41c4d287cfc69060fa91cae9683eacffad989f1a10811995fa309df656ec214", size = 146626 }, + { url = "https://files.pythonhosted.org/packages/8c/73/6ede2ec59bce19b3edf4209d70004253ec5f4e319f9a2e3f2f15601ed5f7/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e594135de17ab3866138f496755f302b72157d115086d100c3f19370839dd3a", size = 148567 }, + { url = "https://files.pythonhosted.org/packages/09/14/957d03c6dc343c04904530b6bef4e5efae5ec7d7990a7cbb868e4595ee30/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf713fe9a71ef6fd5adf7a79670135081cd4431c2943864757f0fa3a65b1fafd", size = 150957 }, + { url = "https://files.pythonhosted.org/packages/0d/c8/8174d0e5c10ccebdcb1b53cc959591c4c722a3ad92461a273e86b9f5a302/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a370b3e078e418187da8c3674eddb9d983ec09445c99a3a263c2011993522981", size = 145408 }, + { url = "https://files.pythonhosted.org/packages/58/aa/8904b84bc8084ac19dc52feb4f5952c6df03ffb460a887b42615ee1382e8/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a955b438e62efdf7e0b7b52a64dc5c3396e2634baa62471768a64bc2adb73d5c", size = 153399 }, + { url = "https://files.pythonhosted.org/packages/c2/26/89ee1f0e264d201cb65cf054aca6038c03b1a0c6b4ae998070392a3ce605/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:7222ffd5e4de8e57e03ce2cef95a4c43c98fcb72ad86909abdfc2c17d227fc1b", size = 156815 }, + { url = "https://files.pythonhosted.org/packages/fd/07/68e95b4b345bad3dbbd3a8681737b4338ff2c9df29856a6d6d23ac4c73cb/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:bee093bf902e1d8fc0ac143c88902c3dfc8941f7ea1d6a8dd2bcb786d33db03d", size = 154537 }, + { url = "https://files.pythonhosted.org/packages/77/1a/5eefc0ce04affb98af07bc05f3bac9094513c0e23b0562d64af46a06aae4/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb8adb91d11846ee08bec4c8236c8549ac721c245678282dcb06b221aab59f", size = 149565 }, + { url = "https://files.pythonhosted.org/packages/37/a0/2410e5e6032a174c95e0806b1a6585eb21e12f445ebe239fac441995226a/charset_normalizer-3.4.2-cp312-cp312-win32.whl", hash = "sha256:db4c7bf0e07fc3b7d89ac2a5880a6a8062056801b83ff56d8464b70f65482b6c", size = 98357 }, + { url = "https://files.pythonhosted.org/packages/6c/4f/c02d5c493967af3eda9c771ad4d2bbc8df6f99ddbeb37ceea6e8716a32bc/charset_normalizer-3.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:5a9979887252a82fefd3d3ed2a8e3b937a7a809f65dcb1e068b090e165bbe99e", size = 105776 }, + { url = "https://files.pythonhosted.org/packages/ea/12/a93df3366ed32db1d907d7593a94f1fe6293903e3e92967bebd6950ed12c/charset_normalizer-3.4.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:926ca93accd5d36ccdabd803392ddc3e03e6d4cd1cf17deff3b989ab8e9dbcf0", size = 199622 }, + { url = "https://files.pythonhosted.org/packages/04/93/bf204e6f344c39d9937d3c13c8cd5bbfc266472e51fc8c07cb7f64fcd2de/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eba9904b0f38a143592d9fc0e19e2df0fa2e41c3c3745554761c5f6447eedabf", size = 143435 }, + { url = "https://files.pythonhosted.org/packages/22/2a/ea8a2095b0bafa6c5b5a55ffdc2f924455233ee7b91c69b7edfcc9e02284/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3fddb7e2c84ac87ac3a947cb4e66d143ca5863ef48e4a5ecb83bd48619e4634e", size = 153653 }, + { url = "https://files.pythonhosted.org/packages/b6/57/1b090ff183d13cef485dfbe272e2fe57622a76694061353c59da52c9a659/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98f862da73774290f251b9df8d11161b6cf25b599a66baf087c1ffe340e9bfd1", size = 146231 }, + { url = "https://files.pythonhosted.org/packages/e2/28/ffc026b26f441fc67bd21ab7f03b313ab3fe46714a14b516f931abe1a2d8/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c9379d65defcab82d07b2a9dfbfc2e95bc8fe0ebb1b176a3190230a3ef0e07c", size = 148243 }, + { url = "https://files.pythonhosted.org/packages/c0/0f/9abe9bd191629c33e69e47c6ef45ef99773320e9ad8e9cb08b8ab4a8d4cb/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e635b87f01ebc977342e2697d05b56632f5f879a4f15955dfe8cef2448b51691", size = 150442 }, + { url = "https://files.pythonhosted.org/packages/67/7c/a123bbcedca91d5916c056407f89a7f5e8fdfce12ba825d7d6b9954a1a3c/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1c95a1e2902a8b722868587c0e1184ad5c55631de5afc0eb96bc4b0d738092c0", size = 145147 }, + { url = "https://files.pythonhosted.org/packages/ec/fe/1ac556fa4899d967b83e9893788e86b6af4d83e4726511eaaad035e36595/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ef8de666d6179b009dce7bcb2ad4c4a779f113f12caf8dc77f0162c29d20490b", size = 153057 }, + { url = "https://files.pythonhosted.org/packages/2b/ff/acfc0b0a70b19e3e54febdd5301a98b72fa07635e56f24f60502e954c461/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:32fc0341d72e0f73f80acb0a2c94216bd704f4f0bce10aedea38f30502b271ff", size = 156454 }, + { url = "https://files.pythonhosted.org/packages/92/08/95b458ce9c740d0645feb0e96cea1f5ec946ea9c580a94adfe0b617f3573/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:289200a18fa698949d2b39c671c2cc7a24d44096784e76614899a7ccf2574b7b", size = 154174 }, + { url = "https://files.pythonhosted.org/packages/78/be/8392efc43487ac051eee6c36d5fbd63032d78f7728cb37aebcc98191f1ff/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4a476b06fbcf359ad25d34a057b7219281286ae2477cc5ff5e3f70a246971148", size = 149166 }, + { url = "https://files.pythonhosted.org/packages/44/96/392abd49b094d30b91d9fbda6a69519e95802250b777841cf3bda8fe136c/charset_normalizer-3.4.2-cp313-cp313-win32.whl", hash = "sha256:aaeeb6a479c7667fbe1099af9617c83aaca22182d6cf8c53966491a0f1b7ffb7", size = 98064 }, + { url = "https://files.pythonhosted.org/packages/e9/b0/0200da600134e001d91851ddc797809e2fe0ea72de90e09bec5a2fbdaccb/charset_normalizer-3.4.2-cp313-cp313-win_amd64.whl", hash = "sha256:aa6af9e7d59f9c12b33ae4e9450619cf2488e2bbe9b44030905877f0b2324980", size = 105641 }, + { url = "https://files.pythonhosted.org/packages/28/f8/dfb01ff6cc9af38552c69c9027501ff5a5117c4cc18dcd27cb5259fa1888/charset_normalizer-3.4.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:005fa3432484527f9732ebd315da8da8001593e2cf46a3d817669f062c3d9ed4", size = 201671 }, + { url = "https://files.pythonhosted.org/packages/32/fb/74e26ee556a9dbfe3bd264289b67be1e6d616329403036f6507bb9f3f29c/charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e92fca20c46e9f5e1bb485887d074918b13543b1c2a1185e69bb8d17ab6236a7", size = 144744 }, + { url = "https://files.pythonhosted.org/packages/ad/06/8499ee5aa7addc6f6d72e068691826ff093329fe59891e83b092ae4c851c/charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:50bf98d5e563b83cc29471fa114366e6806bc06bc7a25fd59641e41445327836", size = 154993 }, + { url = "https://files.pythonhosted.org/packages/f1/a2/5e4c187680728219254ef107a6949c60ee0e9a916a5dadb148c7ae82459c/charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:721c76e84fe669be19c5791da68232ca2e05ba5185575086e384352e2c309597", size = 147382 }, + { url = "https://files.pythonhosted.org/packages/4c/fe/56aca740dda674f0cc1ba1418c4d84534be51f639b5f98f538b332dc9a95/charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82d8fd25b7f4675d0c47cf95b594d4e7b158aca33b76aa63d07186e13c0e0ab7", size = 149536 }, + { url = "https://files.pythonhosted.org/packages/53/13/db2e7779f892386b589173dd689c1b1e304621c5792046edd8a978cbf9e0/charset_normalizer-3.4.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3daeac64d5b371dea99714f08ffc2c208522ec6b06fbc7866a450dd446f5c0f", size = 151349 }, + { url = "https://files.pythonhosted.org/packages/69/35/e52ab9a276186f729bce7a0638585d2982f50402046e4b0faa5d2c3ef2da/charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dccab8d5fa1ef9bfba0590ecf4d46df048d18ffe3eec01eeb73a42e0d9e7a8ba", size = 146365 }, + { url = "https://files.pythonhosted.org/packages/a6/d8/af7333f732fc2e7635867d56cb7c349c28c7094910c72267586947561b4b/charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:aaf27faa992bfee0264dc1f03f4c75e9fcdda66a519db6b957a3f826e285cf12", size = 154499 }, + { url = "https://files.pythonhosted.org/packages/7a/3d/a5b2e48acef264d71e036ff30bcc49e51bde80219bb628ba3e00cf59baac/charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:eb30abc20df9ab0814b5a2524f23d75dcf83cde762c161917a2b4b7b55b1e518", size = 157735 }, + { url = "https://files.pythonhosted.org/packages/85/d8/23e2c112532a29f3eef374375a8684a4f3b8e784f62b01da931186f43494/charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:c72fbbe68c6f32f251bdc08b8611c7b3060612236e960ef848e0a517ddbe76c5", size = 154786 }, + { url = "https://files.pythonhosted.org/packages/c7/57/93e0169f08ecc20fe82d12254a200dfaceddc1c12a4077bf454ecc597e33/charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:982bb1e8b4ffda883b3d0a521e23abcd6fd17418f6d2c4118d257a10199c0ce3", size = 150203 }, + { url = "https://files.pythonhosted.org/packages/2c/9d/9bf2b005138e7e060d7ebdec7503d0ef3240141587651f4b445bdf7286c2/charset_normalizer-3.4.2-cp39-cp39-win32.whl", hash = "sha256:43e0933a0eff183ee85833f341ec567c0980dae57c464d8a508e1b2ceb336471", size = 98436 }, + { url = "https://files.pythonhosted.org/packages/6d/24/5849d46cf4311bbf21b424c443b09b459f5b436b1558c04e45dbb7cc478b/charset_normalizer-3.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:d11b54acf878eef558599658b0ffca78138c8c3655cf4f3a4a673c437e67732e", size = 105772 }, + { url = "https://files.pythonhosted.org/packages/20/94/c5790835a017658cbfabd07f3bfb549140c3ac458cfc196323996b10095a/charset_normalizer-3.4.2-py3-none-any.whl", hash = "sha256:7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0", size = 52626 }, +] + +[[package]] +name = "chex" +version = "0.1.89" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "absl-py" }, + { name = "jax", version = "0.4.30", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "jax", version = "0.5.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "jaxlib", version = "0.4.30", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "jaxlib", version = "0.5.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "numpy" }, + { name = "setuptools", marker = "python_full_version >= '3.12'" }, + { name = "toolz" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ca/ac/504a8019f7ef372fc6cc3999ec9e3d0fbb38e6992f55d845d5b928010c11/chex-0.1.89.tar.gz", hash = "sha256:78f856e6a0a8459edfcbb402c2c044d2b8102eac4b633838cbdfdcdb09c6c8e0", size = 90676 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5e/6c/309972937d931069816dc8b28193a650485bc35cca92c04c8c15c4bd181e/chex-0.1.89-py3-none-any.whl", hash = "sha256:145241c27d8944adb634fb7d472a460e1c1b643f561507d4031ad5156ef82dfa", size = 99908 }, +] + +[[package]] +name = "click" +version = "8.0.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/dd/cf/706c1ad49ab26abed0b77a2f867984c1341ed7387b8030a6aa914e2942a0/click-8.0.4.tar.gz", hash = "sha256:8458d7b1287c5fb128c90e23381cf99dcde74beaf6c7ff6384ce84d6fe090adb", size = 329520 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4a/a8/0b2ced25639fb20cc1c9784de90a8c25f9504a7f18cd8b5397bd61696d7d/click-8.0.4-py3-none-any.whl", hash = "sha256:6a7a62563bbfabfda3a38f3023a1db4a35978c0abd76f6c9605ecd6554d6d9b1", size = 97486 }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, +] + +[[package]] +name = "decorator" +version = "5.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/fa/6d96a0978d19e17b68d634497769987b16c8f4cd0a7a05048bec693caa6b/decorator-5.2.1.tar.gz", hash = "sha256:65f266143752f734b0a7cc83c46f4618af75b8c5911b00ccb61d0ac9b6da0360", size = 56711 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl", hash = "sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a", size = 9190 }, +] + +[[package]] +name = "etils" +version = "1.5.2" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] +sdist = { url = "https://files.pythonhosted.org/packages/ad/fa/8637c95271dd9eed00e258184295dd00ba163bb8924ba3be978ec89f093f/etils-1.5.2.tar.gz", hash = "sha256:ba6a3e1aff95c769130776aa176c11540637f5dd881f3b79172a5149b6b1c446", size = 87021 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0f/6a/d2aaebacf73d5da7126c632ec0d9dc2df99cc4bbd259bad48904a034fc1b/etils-1.5.2-py3-none-any.whl", hash = "sha256:6dc882d355e1e98a5d1a148d6323679dc47c9a5792939b9de72615aa4737eb0b", size = 140603 }, +] + +[package.optional-dependencies] +epath = [ + { name = "fsspec", marker = "python_full_version < '3.10'" }, + { name = "importlib-resources", marker = "python_full_version < '3.10'" }, + { name = "typing-extensions", marker = "python_full_version < '3.10'" }, + { name = "zipp", marker = "python_full_version < '3.10'" }, +] +epy = [ + { name = "typing-extensions", marker = "python_full_version < '3.10'" }, +] + +[[package]] +name = "etils" +version = "1.12.2" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.12'", + "python_full_version == '3.11.*'", + "python_full_version == '3.10.*'", +] +sdist = { url = "https://files.pythonhosted.org/packages/e4/12/1cc11e88a0201280ff389bc4076df7c3432e39d9f22cba8b71aa263f67b8/etils-1.12.2.tar.gz", hash = "sha256:c6b9e1f0ce66d1bbf54f99201b08a60ba396d3446d9eb18d4bc39b26a2e1a5ee", size = 104711 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/dd/71/40ee142e564b8a34a7ae9546e99e665e0001011a3254d5bbbe113d72ccba/etils-1.12.2-py3-none-any.whl", hash = "sha256:4600bec9de6cf5cb043a171e1856e38b5f273719cf3ecef90199f7091a6b3912", size = 167613 }, +] + +[package.optional-dependencies] +epath = [ + { name = "fsspec", marker = "python_full_version >= '3.10'" }, + { name = "importlib-resources", marker = "python_full_version >= '3.10'" }, + { name = "typing-extensions", marker = "python_full_version >= '3.10'" }, + { name = "zipp", marker = "python_full_version >= '3.10'" }, +] +epy = [ + { name = "typing-extensions", marker = "python_full_version >= '3.10'" }, +] + +[[package]] +name = "exceptiongroup" +version = "1.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/09/35/2495c4ac46b980e4ca1f6ad6db102322ef3ad2410b79fdde159a4b0f3b92/exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc", size = 28883 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/02/cc/b7e31358aac6ed1ef2bb790a9746ac2c69bcb3c8588b41616914eb106eaf/exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b", size = 16453 }, +] + +[[package]] +name = "filelock" +version = "3.18.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0a/10/c23352565a6544bdc5353e0b15fc1c563352101f30e24bf500207a54df9a/filelock-3.18.0.tar.gz", hash = "sha256:adbc88eabb99d2fec8c9c1b229b171f18afa655400173ddc653d5d01501fb9f2", size = 18075 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4d/36/2a115987e2d8c300a974597416d9de88f2444426de9571f4b59b2cca3acc/filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de", size = 16215 }, +] + +[[package]] +name = "flake8" +version = "7.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mccabe" }, + { name = "pycodestyle" }, + { name = "pyflakes" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e7/c4/5842fc9fc94584c455543540af62fd9900faade32511fab650e9891ec225/flake8-7.2.0.tar.gz", hash = "sha256:fa558ae3f6f7dbf2b4f22663e5343b6b6023620461f8d4ff2019ef4b5ee70426", size = 48177 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/83/5c/0627be4c9976d56b1217cb5187b7504e7fd7d3503f8bfd312a04077bd4f7/flake8-7.2.0-py2.py3-none-any.whl", hash = "sha256:93b92ba5bdb60754a6da14fa3b93a9361fd00a59632ada61fd7b130436c40343", size = 57786 }, +] + +[[package]] +name = "flatbuffers" +version = "25.2.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e4/30/eb5dce7994fc71a2f685d98ec33cc660c0a5887db5610137e60d8cbc4489/flatbuffers-25.2.10.tar.gz", hash = "sha256:97e451377a41262f8d9bd4295cc836133415cc03d8cb966410a4af92eb00d26e", size = 22170 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b8/25/155f9f080d5e4bc0082edfda032ea2bc2b8fab3f4d25d46c1e9dd22a1a89/flatbuffers-25.2.10-py2.py3-none-any.whl", hash = "sha256:ebba5f4d5ea615af3f7fd70fc310636fbb2bbd1f566ac0a23d98dd412de50051", size = 30953 }, +] + +[[package]] +name = "flax" +version = "0.8.5" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] +dependencies = [ + { name = "jax", version = "0.4.30", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "msgpack", marker = "python_full_version < '3.10'" }, + { name = "numpy", marker = "python_full_version < '3.10'" }, + { name = "optax", marker = "python_full_version < '3.10'" }, + { name = "orbax-checkpoint", version = "0.6.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "pyyaml", marker = "python_full_version < '3.10'" }, + { name = "rich", marker = "python_full_version < '3.10'" }, + { name = "tensorstore", version = "0.1.69", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "typing-extensions", marker = "python_full_version < '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/29/fb/b259e2e33e5740c62fc05677c395e96809e83c0467677d3e714b125ec24c/flax-0.8.5.tar.gz", hash = "sha256:4a9cb7950ece54b0addaa73d77eba24e46138dbe783d01987be79d20ccb2b09b", size = 2862557 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1c/a9/6978d2547b1d8ca0ce75b534c0ba5c60e8e7b918c5c1800225aa0169cb7f/flax-0.8.5-py3-none-any.whl", hash = "sha256:c96e46d1c48a300d010ebf5c4846f163bdd7acc6efff5ff2bfb1cb5b08aa65d8", size = 731342 }, +] + +[[package]] +name = "flax" +version = "0.10.6" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.12'", + "python_full_version == '3.11.*'", + "python_full_version == '3.10.*'", +] +dependencies = [ + { name = "jax", version = "0.5.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "msgpack", marker = "python_full_version >= '3.10'" }, + { name = "numpy", marker = "python_full_version >= '3.11'" }, + { name = "optax", marker = "python_full_version >= '3.10'" }, + { name = "orbax-checkpoint", version = "0.11.13", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "pyyaml", marker = "python_full_version >= '3.10'" }, + { name = "rich", marker = "python_full_version >= '3.10'" }, + { name = "tensorstore", version = "0.1.74", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "treescope", marker = "python_full_version >= '3.10'" }, + { name = "typing-extensions", marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6d/e6/2eee448a8b64ddde6fca53b067e6dbfe974bb198f6b21dc13f52aaeab7e3/flax-0.10.6.tar.gz", hash = "sha256:8f3d1eb7de9bbaa18e08d0423dce890aef88a8b9dc6daa23baa631e8dfb09618", size = 5215148 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fb/f8/aaf70a427f7e17afc1877d69c610b6b0c5093dba5addb63fb6990944e989/flax-0.10.6-py3-none-any.whl", hash = "sha256:86a5f0ba0f1603c687714999b58a4e362e784a6d2dc5a510b18a8e7a6c729e18", size = 447094 }, +] + +[[package]] +name = "fsspec" +version = "2025.3.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/45/d8/8425e6ba5fcec61a1d16e41b1b71d2bf9344f1fe48012c2b48b9620feae5/fsspec-2025.3.2.tar.gz", hash = "sha256:e52c77ef398680bbd6a98c0e628fbc469491282981209907bbc8aea76a04fdc6", size = 299281 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/44/4b/e0cfc1a6f17e990f3e64b7d941ddc4acdc7b19d6edd51abf495f32b1a9e4/fsspec-2025.3.2-py3-none-any.whl", hash = "sha256:2daf8dc3d1dfa65b6aa37748d112773a7a08416f6c70d96b264c96476ecaf711", size = 194435 }, +] + +[[package]] +name = "gast" +version = "0.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3c/14/c566f5ca00c115db7725263408ff952b8ae6d6a4e792ef9c84e77d9af7a1/gast-0.6.0.tar.gz", hash = "sha256:88fc5300d32c7ac6ca7b515310862f71e6fdf2c029bbec7c66c0f5dd47b6b1fb", size = 27708 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a3/61/8001b38461d751cd1a0c3a6ae84346796a5758123f3ed97a1b121dfbf4f3/gast-0.6.0-py3-none-any.whl", hash = "sha256:52b182313f7330389f72b069ba00f174cfe2a06411099547288839c6cbafbd54", size = 21173 }, +] + +[[package]] +name = "google-pasta" +version = "0.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/35/4a/0bd53b36ff0323d10d5f24ebd67af2de10a1117f5cf4d7add90df92756f1/google-pasta-0.2.0.tar.gz", hash = "sha256:c9f2c8dfc8f96d0d5808299920721be30c9eec37f2389f28904f454565c8a16e", size = 40430 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a3/de/c648ef6835192e6e2cc03f40b19eeda4382c49b5bafb43d88b931c4c74ac/google_pasta-0.2.0-py3-none-any.whl", hash = "sha256:b32482794a366b5366a32c92a9a9201b107821889935a02b3e51f6b432ea84ed", size = 57471 }, +] + +[[package]] +name = "grpcio" +version = "1.71.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1c/95/aa11fc09a85d91fbc7dd405dcb2a1e0256989d67bf89fa65ae24b3ba105a/grpcio-1.71.0.tar.gz", hash = "sha256:2b85f7820475ad3edec209d3d89a7909ada16caab05d3f2e08a7e8ae3200a55c", size = 12549828 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7c/c5/ef610b3f988cc0cc67b765f72b8e2db06a1db14e65acb5ae7810a6b7042e/grpcio-1.71.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:c200cb6f2393468142eb50ab19613229dcc7829b5ccee8b658a36005f6669fdd", size = 5210643 }, + { url = "https://files.pythonhosted.org/packages/bf/de/c84293c961622df302c0d5d07ec6e2d4cd3874ea42f602be2df09c4ad44f/grpcio-1.71.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:b2266862c5ad664a380fbbcdbdb8289d71464c42a8c29053820ee78ba0119e5d", size = 11308962 }, + { url = "https://files.pythonhosted.org/packages/7c/38/04c9e0dc8c904570c80faa1f1349b190b63e45d6b2782ec8567b050efa9d/grpcio-1.71.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:0ab8b2864396663a5b0b0d6d79495657ae85fa37dcb6498a2669d067c65c11ea", size = 5699236 }, + { url = "https://files.pythonhosted.org/packages/95/96/e7be331d1298fa605ea7c9ceafc931490edd3d5b33c4f695f1a0667f3491/grpcio-1.71.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c30f393f9d5ff00a71bb56de4aa75b8fe91b161aeb61d39528db6b768d7eac69", size = 6339767 }, + { url = "https://files.pythonhosted.org/packages/5d/b7/7e7b7bb6bb18baf156fd4f2f5b254150dcdd6cbf0def1ee427a2fb2bfc4d/grpcio-1.71.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f250ff44843d9a0615e350c77f890082102a0318d66a99540f54769c8766ab73", size = 5943028 }, + { url = "https://files.pythonhosted.org/packages/13/aa/5fb756175995aeb47238d706530772d9a7ac8e73bcca1b47dc145d02c95f/grpcio-1.71.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e6d8de076528f7c43a2f576bc311799f89d795aa6c9b637377cc2b1616473804", size = 6031841 }, + { url = "https://files.pythonhosted.org/packages/54/93/172783e01eed61f7f180617b7fa4470f504e383e32af2587f664576a7101/grpcio-1.71.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:9b91879d6da1605811ebc60d21ab6a7e4bae6c35f6b63a061d61eb818c8168f6", size = 6651039 }, + { url = "https://files.pythonhosted.org/packages/6f/99/62654b220a27ed46d3313252214f4bc66261143dc9b58004085cd0646753/grpcio-1.71.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f71574afdf944e6652203cd1badcda195b2a27d9c83e6d88dc1ce3cfb73b31a5", size = 6198465 }, + { url = "https://files.pythonhosted.org/packages/68/35/96116de833b330abe4412cc94edc68f99ed2fa3e39d8713ff307b3799e81/grpcio-1.71.0-cp310-cp310-win32.whl", hash = "sha256:8997d6785e93308f277884ee6899ba63baafa0dfb4729748200fcc537858a509", size = 3620382 }, + { url = "https://files.pythonhosted.org/packages/b7/09/f32ef637e386f3f2c02effac49699229fa560ce9007682d24e9e212d2eb4/grpcio-1.71.0-cp310-cp310-win_amd64.whl", hash = "sha256:7d6ac9481d9d0d129224f6d5934d5832c4b1cddb96b59e7eba8416868909786a", size = 4280302 }, + { url = "https://files.pythonhosted.org/packages/63/04/a085f3ad4133426f6da8c1becf0749872a49feb625a407a2e864ded3fb12/grpcio-1.71.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:d6aa986318c36508dc1d5001a3ff169a15b99b9f96ef5e98e13522c506b37eef", size = 5210453 }, + { url = "https://files.pythonhosted.org/packages/b4/d5/0bc53ed33ba458de95020970e2c22aa8027b26cc84f98bea7fcad5d695d1/grpcio-1.71.0-cp311-cp311-macosx_10_14_universal2.whl", hash = "sha256:d2c170247315f2d7e5798a22358e982ad6eeb68fa20cf7a820bb74c11f0736e7", size = 11347567 }, + { url = "https://files.pythonhosted.org/packages/e3/6d/ce334f7e7a58572335ccd61154d808fe681a4c5e951f8a1ff68f5a6e47ce/grpcio-1.71.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:e6f83a583ed0a5b08c5bc7a3fe860bb3c2eac1f03f1f63e0bc2091325605d2b7", size = 5696067 }, + { url = "https://files.pythonhosted.org/packages/05/4a/80befd0b8b1dc2b9ac5337e57473354d81be938f87132e147c4a24a581bd/grpcio-1.71.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4be74ddeeb92cc87190e0e376dbc8fc7736dbb6d3d454f2fa1f5be1dee26b9d7", size = 6348377 }, + { url = "https://files.pythonhosted.org/packages/c7/67/cbd63c485051eb78663355d9efd1b896cfb50d4a220581ec2cb9a15cd750/grpcio-1.71.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4dd0dfbe4d5eb1fcfec9490ca13f82b089a309dc3678e2edabc144051270a66e", size = 5940407 }, + { url = "https://files.pythonhosted.org/packages/98/4b/7a11aa4326d7faa499f764eaf8a9b5a0eb054ce0988ee7ca34897c2b02ae/grpcio-1.71.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a2242d6950dc892afdf9e951ed7ff89473aaf744b7d5727ad56bdaace363722b", size = 6030915 }, + { url = "https://files.pythonhosted.org/packages/eb/a2/cdae2d0e458b475213a011078b0090f7a1d87f9a68c678b76f6af7c6ac8c/grpcio-1.71.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:0fa05ee31a20456b13ae49ad2e5d585265f71dd19fbd9ef983c28f926d45d0a7", size = 6648324 }, + { url = "https://files.pythonhosted.org/packages/27/df/f345c8daaa8d8574ce9869f9b36ca220c8845923eb3087e8f317eabfc2a8/grpcio-1.71.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3d081e859fb1ebe176de33fc3adb26c7d46b8812f906042705346b314bde32c3", size = 6197839 }, + { url = "https://files.pythonhosted.org/packages/f2/2c/cd488dc52a1d0ae1bad88b0d203bc302efbb88b82691039a6d85241c5781/grpcio-1.71.0-cp311-cp311-win32.whl", hash = "sha256:d6de81c9c00c8a23047136b11794b3584cdc1460ed7cbc10eada50614baa1444", size = 3619978 }, + { url = "https://files.pythonhosted.org/packages/ee/3f/cf92e7e62ccb8dbdf977499547dfc27133124d6467d3a7d23775bcecb0f9/grpcio-1.71.0-cp311-cp311-win_amd64.whl", hash = "sha256:24e867651fc67717b6f896d5f0cac0ec863a8b5fb7d6441c2ab428f52c651c6b", size = 4282279 }, + { url = "https://files.pythonhosted.org/packages/4c/83/bd4b6a9ba07825bd19c711d8b25874cd5de72c2a3fbf635c3c344ae65bd2/grpcio-1.71.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:0ff35c8d807c1c7531d3002be03221ff9ae15712b53ab46e2a0b4bb271f38537", size = 5184101 }, + { url = "https://files.pythonhosted.org/packages/31/ea/2e0d90c0853568bf714693447f5c73272ea95ee8dad107807fde740e595d/grpcio-1.71.0-cp312-cp312-macosx_10_14_universal2.whl", hash = "sha256:b78a99cd1ece4be92ab7c07765a0b038194ded2e0a26fd654591ee136088d8d7", size = 11310927 }, + { url = "https://files.pythonhosted.org/packages/ac/bc/07a3fd8af80467390af491d7dc66882db43884128cdb3cc8524915e0023c/grpcio-1.71.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:dc1a1231ed23caac1de9f943d031f1bc38d0f69d2a3b243ea0d664fc1fbd7fec", size = 5654280 }, + { url = "https://files.pythonhosted.org/packages/16/af/21f22ea3eed3d0538b6ef7889fce1878a8ba4164497f9e07385733391e2b/grpcio-1.71.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e6beeea5566092c5e3c4896c6d1d307fb46b1d4bdf3e70c8340b190a69198594", size = 6312051 }, + { url = "https://files.pythonhosted.org/packages/49/9d/e12ddc726dc8bd1aa6cba67c85ce42a12ba5b9dd75d5042214a59ccf28ce/grpcio-1.71.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5170929109450a2c031cfe87d6716f2fae39695ad5335d9106ae88cc32dc84c", size = 5910666 }, + { url = "https://files.pythonhosted.org/packages/d9/e9/38713d6d67aedef738b815763c25f092e0454dc58e77b1d2a51c9d5b3325/grpcio-1.71.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:5b08d03ace7aca7b2fadd4baf291139b4a5f058805a8327bfe9aece7253b6d67", size = 6012019 }, + { url = "https://files.pythonhosted.org/packages/80/da/4813cd7adbae6467724fa46c952d7aeac5e82e550b1c62ed2aeb78d444ae/grpcio-1.71.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:f903017db76bf9cc2b2d8bdd37bf04b505bbccad6be8a81e1542206875d0e9db", size = 6637043 }, + { url = "https://files.pythonhosted.org/packages/52/ca/c0d767082e39dccb7985c73ab4cf1d23ce8613387149e9978c70c3bf3b07/grpcio-1.71.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:469f42a0b410883185eab4689060a20488a1a0a00f8bbb3cbc1061197b4c5a79", size = 6186143 }, + { url = "https://files.pythonhosted.org/packages/00/61/7b2c8ec13303f8fe36832c13d91ad4d4ba57204b1c723ada709c346b2271/grpcio-1.71.0-cp312-cp312-win32.whl", hash = "sha256:ad9f30838550695b5eb302add33f21f7301b882937460dd24f24b3cc5a95067a", size = 3604083 }, + { url = "https://files.pythonhosted.org/packages/fd/7c/1e429c5fb26122055d10ff9a1d754790fb067d83c633ff69eddcf8e3614b/grpcio-1.71.0-cp312-cp312-win_amd64.whl", hash = "sha256:652350609332de6dac4ece254e5d7e1ff834e203d6afb769601f286886f6f3a8", size = 4272191 }, + { url = "https://files.pythonhosted.org/packages/04/dd/b00cbb45400d06b26126dcfdbdb34bb6c4f28c3ebbd7aea8228679103ef6/grpcio-1.71.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:cebc1b34ba40a312ab480ccdb396ff3c529377a2fce72c45a741f7215bfe8379", size = 5184138 }, + { url = "https://files.pythonhosted.org/packages/ed/0a/4651215983d590ef53aac40ba0e29dda941a02b097892c44fa3357e706e5/grpcio-1.71.0-cp313-cp313-macosx_10_14_universal2.whl", hash = "sha256:85da336e3649a3d2171e82f696b5cad2c6231fdd5bad52616476235681bee5b3", size = 11310747 }, + { url = "https://files.pythonhosted.org/packages/57/a3/149615b247f321e13f60aa512d3509d4215173bdb982c9098d78484de216/grpcio-1.71.0-cp313-cp313-manylinux_2_17_aarch64.whl", hash = "sha256:f9a412f55bb6e8f3bb000e020dbc1e709627dcb3a56f6431fa7076b4c1aab0db", size = 5653991 }, + { url = "https://files.pythonhosted.org/packages/ca/56/29432a3e8d951b5e4e520a40cd93bebaa824a14033ea8e65b0ece1da6167/grpcio-1.71.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:47be9584729534660416f6d2a3108aaeac1122f6b5bdbf9fd823e11fe6fbaa29", size = 6312781 }, + { url = "https://files.pythonhosted.org/packages/a3/f8/286e81a62964ceb6ac10b10925261d4871a762d2a763fbf354115f9afc98/grpcio-1.71.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c9c80ac6091c916db81131d50926a93ab162a7e97e4428ffc186b6e80d6dda4", size = 5910479 }, + { url = "https://files.pythonhosted.org/packages/35/67/d1febb49ec0f599b9e6d4d0d44c2d4afdbed9c3e80deb7587ec788fcf252/grpcio-1.71.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:789d5e2a3a15419374b7b45cd680b1e83bbc1e52b9086e49308e2c0b5bbae6e3", size = 6013262 }, + { url = "https://files.pythonhosted.org/packages/a1/04/f9ceda11755f0104a075ad7163fc0d96e2e3a9fe25ef38adfc74c5790daf/grpcio-1.71.0-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:1be857615e26a86d7363e8a163fade914595c81fec962b3d514a4b1e8760467b", size = 6643356 }, + { url = "https://files.pythonhosted.org/packages/fb/ce/236dbc3dc77cf9a9242adcf1f62538734ad64727fabf39e1346ad4bd5c75/grpcio-1.71.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:a76d39b5fafd79ed604c4be0a869ec3581a172a707e2a8d7a4858cb05a5a7637", size = 6186564 }, + { url = "https://files.pythonhosted.org/packages/10/fd/b3348fce9dd4280e221f513dd54024e765b21c348bc475516672da4218e9/grpcio-1.71.0-cp313-cp313-win32.whl", hash = "sha256:74258dce215cb1995083daa17b379a1a5a87d275387b7ffe137f1d5131e2cfbb", size = 3601890 }, + { url = "https://files.pythonhosted.org/packages/be/f8/db5d5f3fc7e296166286c2a397836b8b042f7ad1e11028d82b061701f0f7/grpcio-1.71.0-cp313-cp313-win_amd64.whl", hash = "sha256:22c3bc8d488c039a199f7a003a38cb7635db6656fa96437a8accde8322ce2366", size = 4273308 }, + { url = "https://files.pythonhosted.org/packages/c8/e3/22cb31bbb42de95b35b8f0fb691d8da6e0579e658bb37b86efe2999c702b/grpcio-1.71.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:c6a0a28450c16809f94e0b5bfe52cabff63e7e4b97b44123ebf77f448534d07d", size = 5210667 }, + { url = "https://files.pythonhosted.org/packages/f6/5e/4970fb231e57aad8f41682292343551f58fec5c7a07e261294def3cb8bb6/grpcio-1.71.0-cp39-cp39-macosx_10_14_universal2.whl", hash = "sha256:a371e6b6a5379d3692cc4ea1cb92754d2a47bdddeee755d3203d1f84ae08e03e", size = 11336193 }, + { url = "https://files.pythonhosted.org/packages/7f/a4/dd71a5540d5e86526b39c23060b7d3195f3144af3fe291947b30c3fcbdad/grpcio-1.71.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:39983a9245d37394fd59de71e88c4b295eb510a3555e0a847d9965088cdbd033", size = 5699572 }, + { url = "https://files.pythonhosted.org/packages/d0/69/3e3522d7c2c525a60f4bbf811891925ac7594b768b1ac8e6c9d955a72c45/grpcio-1.71.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9182e0063112e55e74ee7584769ec5a0b4f18252c35787f48738627e23a62b97", size = 6339648 }, + { url = "https://files.pythonhosted.org/packages/32/f2/9d864ca8f3949bf507db9c6a18532c150fc03910dd3d3e17fd4bc5d3e462/grpcio-1.71.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:693bc706c031aeb848849b9d1c6b63ae6bcc64057984bb91a542332b75aa4c3d", size = 5943469 }, + { url = "https://files.pythonhosted.org/packages/9b/58/aec6ce541b7fb2a9efa15d968db5897c2700bd2da6fb159c1d27515f120c/grpcio-1.71.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:20e8f653abd5ec606be69540f57289274c9ca503ed38388481e98fa396ed0b41", size = 6030255 }, + { url = "https://files.pythonhosted.org/packages/f7/4f/7356b7edd1f622d49e72faaea75a5d6ac7bdde8f4c14dd19bcfbafd56f4c/grpcio-1.71.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:8700a2a57771cc43ea295296330daaddc0d93c088f0a35cc969292b6db959bf3", size = 6651120 }, + { url = "https://files.pythonhosted.org/packages/54/10/c1bb13137dc8d1637e2373a85904aa57991e65ef429791bfb8a64a60d5bd/grpcio-1.71.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d35a95f05a8a2cbe8e02be137740138b3b2ea5f80bd004444e4f9a1ffc511e32", size = 6197989 }, + { url = "https://files.pythonhosted.org/packages/0e/dc/0fd537831501df786bc2f9ec5ac1724528a344cd146f6335f7991763eb2b/grpcio-1.71.0-cp39-cp39-win32.whl", hash = "sha256:f9c30c464cb2ddfbc2ddf9400287701270fdc0f14be5f08a1e3939f1e749b455", size = 3620173 }, + { url = "https://files.pythonhosted.org/packages/97/22/b1535291aaa9c046c79a9dc4db125f6b9974d41de154221b72da4e8a005c/grpcio-1.71.0-cp39-cp39-win_amd64.whl", hash = "sha256:63e41b91032f298b3e973b3fa4093cbbc620c875e2da7b93e249d4728b54559a", size = 4280941 }, +] + +[[package]] +name = "h11" +version = "0.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515 }, +] + +[[package]] +name = "h5py" +version = "3.13.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/03/2e/a22d6a8bfa6f8be33e7febd985680fba531562795f0a9077ed1eb047bfb0/h5py-3.13.0.tar.gz", hash = "sha256:1870e46518720023da85d0895a1960ff2ce398c5671eac3b1a41ec696b7105c3", size = 414876 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/02/8a/bc76588ff1a254e939ce48f30655a8f79fac614ca8bd1eda1a79fa276671/h5py-3.13.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5540daee2b236d9569c950b417f13fd112d51d78b4c43012de05774908dff3f5", size = 3413286 }, + { url = "https://files.pythonhosted.org/packages/19/bd/9f249ecc6c517b2796330b0aab7d2351a108fdbd00d4bb847c0877b5533e/h5py-3.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:10894c55d46df502d82a7a4ed38f9c3fdbcb93efb42e25d275193e093071fade", size = 2915673 }, + { url = "https://files.pythonhosted.org/packages/72/71/0dd079208d7d3c3988cebc0776c2de58b4d51d8eeb6eab871330133dfee6/h5py-3.13.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb267ce4b83f9c42560e9ff4d30f60f7ae492eacf9c7ede849edf8c1b860e16b", size = 4283822 }, + { url = "https://files.pythonhosted.org/packages/d8/fa/0b6a59a1043c53d5d287effa02303bd248905ee82b25143c7caad8b340ad/h5py-3.13.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2cf6a231a07c14acd504a945a6e9ec115e0007f675bde5e0de30a4dc8d86a31", size = 4548100 }, + { url = "https://files.pythonhosted.org/packages/12/42/ad555a7ff7836c943fe97009405566dc77bcd2a17816227c10bd067a3ee1/h5py-3.13.0-cp310-cp310-win_amd64.whl", hash = "sha256:851ae3a8563d87a5a0dc49c2e2529c75b8842582ccaefbf84297d2cfceeacd61", size = 2950547 }, + { url = "https://files.pythonhosted.org/packages/86/2b/50b15fdefb577d073b49699e6ea6a0a77a3a1016c2b67e2149fc50124a10/h5py-3.13.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8a8e38ef4ceb969f832cc230c0cf808c613cc47e31e768fd7b1106c55afa1cb8", size = 3422922 }, + { url = "https://files.pythonhosted.org/packages/94/59/36d87a559cab9c59b59088d52e86008d27a9602ce3afc9d3b51823014bf3/h5py-3.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f35640e81b03c02a88b8bf99fb6a9d3023cc52f7c627694db2f379e0028f2868", size = 2921619 }, + { url = "https://files.pythonhosted.org/packages/37/ef/6f80b19682c0b0835bbee7b253bec9c16af9004f2fd6427b1dd858100273/h5py-3.13.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:337af114616f3656da0c83b68fcf53ecd9ce9989a700b0883a6e7c483c3235d4", size = 4259366 }, + { url = "https://files.pythonhosted.org/packages/03/71/c99f662d4832c8835453cf3476f95daa28372023bda4aa1fca9e97c24f09/h5py-3.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:782ff0ac39f455f21fd1c8ebc007328f65f43d56718a89327eec76677ebf238a", size = 4509058 }, + { url = "https://files.pythonhosted.org/packages/56/89/e3ff23e07131ff73a72a349be9639e4de84e163af89c1c218b939459a98a/h5py-3.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:22ffe2a25770a2d67213a1b94f58006c14dce06933a42d2aaa0318c5868d1508", size = 2966428 }, + { url = "https://files.pythonhosted.org/packages/d8/20/438f6366ba4ded80eadb38f8927f5e2cd6d2e087179552f20ae3dbcd5d5b/h5py-3.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:477c58307b6b9a2509c59c57811afb9f598aedede24a67da808262dfa0ee37b4", size = 3384442 }, + { url = "https://files.pythonhosted.org/packages/10/13/cc1cb7231399617d9951233eb12fddd396ff5d4f7f057ee5d2b1ca0ee7e7/h5py-3.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:57c4c74f627c616f02b7aec608a8c706fe08cb5b0ba7c08555a4eb1dde20805a", size = 2917567 }, + { url = "https://files.pythonhosted.org/packages/9e/d9/aed99e1c858dc698489f916eeb7c07513bc864885d28ab3689d572ba0ea0/h5py-3.13.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:357e6dc20b101a805ccfd0024731fbaf6e8718c18c09baf3b5e4e9d198d13fca", size = 4669544 }, + { url = "https://files.pythonhosted.org/packages/a7/da/3c137006ff5f0433f0fb076b1ebe4a7bf7b5ee1e8811b5486af98b500dd5/h5py-3.13.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d6f13f9b5ce549448c01e4dfe08ea8d1772e6078799af2c1c8d09e941230a90d", size = 4932139 }, + { url = "https://files.pythonhosted.org/packages/25/61/d897952629cae131c19d4c41b2521e7dd6382f2d7177c87615c2e6dced1a/h5py-3.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:21daf38171753899b5905f3d82c99b0b1ec2cbbe282a037cad431feb620e62ec", size = 2954179 }, + { url = "https://files.pythonhosted.org/packages/60/43/f276f27921919a9144074320ce4ca40882fc67b3cfee81c3f5c7df083e97/h5py-3.13.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e520ec76de00943dd017c8ea3f354fa1d2f542eac994811943a8faedf2a7d5cb", size = 3358040 }, + { url = "https://files.pythonhosted.org/packages/1b/86/ad4a4cf781b08d4572be8bbdd8f108bb97b266a14835c640dc43dafc0729/h5py-3.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e79d8368cd9295045956bfb436656bea3f915beaa11d342e9f79f129f5178763", size = 2892766 }, + { url = "https://files.pythonhosted.org/packages/69/84/4c6367d6b58deaf0fa84999ec819e7578eee96cea6cbd613640d0625ed5e/h5py-3.13.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56dd172d862e850823c4af02dc4ddbc308f042b85472ffdaca67f1598dff4a57", size = 4664255 }, + { url = "https://files.pythonhosted.org/packages/fd/41/bc2df86b72965775f6d621e0ee269a5f3ac23e8f870abf519de9c7d93b4d/h5py-3.13.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be949b46b7388074c5acae017fbbe3e5ba303fd9daaa52157fdfef30bbdacadd", size = 4927580 }, + { url = "https://files.pythonhosted.org/packages/97/34/165b87ea55184770a0c1fcdb7e017199974ad2e271451fd045cfe35f3add/h5py-3.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:4f97ecde7ac6513b21cd95efdfc38dc6d19f96f6ca6f2a30550e94e551458e0a", size = 2940890 }, + { url = "https://files.pythonhosted.org/packages/cd/91/3e5b4e4c399bb57141a2451c67808597ab6993f799587566c9f11dbaefe9/h5py-3.13.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:82690e89c72b85addf4fc4d5058fb1e387b6c14eb063b0b879bf3f42c3b93c35", size = 3424729 }, + { url = "https://files.pythonhosted.org/packages/12/82/4e455e12e7ff26533c762eaf324edd6b076f84c3a003a40a1e52d805e0fb/h5py-3.13.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d571644958c5e19a61c793d8d23cd02479572da828e333498c9acc463f4a3997", size = 2926632 }, + { url = "https://files.pythonhosted.org/packages/ab/c9/fb430d3277e81eade92e54e87bd73e9f60c98240a86a5f43e3b85620d7d8/h5py-3.13.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:560e71220dc92dfa254b10a4dcb12d56b574d2d87e095db20466b32a93fec3f9", size = 4285580 }, + { url = "https://files.pythonhosted.org/packages/3f/9b/3e8cded7877ec84b707df82b9c6289cd1d7ad80fef9a10bb1389c5fee8f2/h5py-3.13.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c10f061764d8dce0a9592ce08bfd5f243a00703325c388f1086037e5d619c5f1", size = 4550898 }, + { url = "https://files.pythonhosted.org/packages/cb/47/8353102cff9290861135e13eefff5a916855d2ab23bd052ec7ac144f4c48/h5py-3.13.0-cp39-cp39-win_amd64.whl", hash = "sha256:9c82ece71ed1c2b807b6628e3933bc6eae57ea21dac207dca3470e3ceaaf437c", size = 2960208 }, +] + +[[package]] +name = "httpcore" +version = "1.0.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784 }, +] + +[[package]] +name = "httpx" +version = "0.28.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "certifi" }, + { name = "httpcore" }, + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517 }, +] + +[[package]] +name = "huggingface-hub" +version = "0.30.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "filelock" }, + { name = "fsspec" }, + { name = "packaging" }, + { name = "pyyaml" }, + { name = "requests" }, + { name = "tqdm" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/df/22/8eb91736b1dcb83d879bd49050a09df29a57cc5cd9f38e48a4b1c45ee890/huggingface_hub-0.30.2.tar.gz", hash = "sha256:9a7897c5b6fd9dad3168a794a8998d6378210f5b9688d0dfc180b1a228dc2466", size = 400868 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/93/27/1fb384a841e9661faad1c31cbfa62864f59632e876df5d795234da51c395/huggingface_hub-0.30.2-py3-none-any.whl", hash = "sha256:68ff05969927058cfa41df4f2155d4bb48f5f54f719dd0390103eefa9b191e28", size = 481433 }, +] + +[[package]] +name = "humanize" +version = "4.12.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/22/d1/bbc4d251187a43f69844f7fd8941426549bbe4723e8ff0a7441796b0789f/humanize-4.12.3.tar.gz", hash = "sha256:8430be3a615106fdfceb0b2c1b41c4c98c6b0fc5cc59663a5539b111dd325fb0", size = 80514 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/1e/62a2ec3104394a2975a2629eec89276ede9dbe717092f6966fcf963e1bf0/humanize-4.12.3-py3-none-any.whl", hash = "sha256:2cbf6370af06568fa6d2da77c86edb7886f3160ecd19ee1ffef07979efc597f6", size = 128487 }, +] + +[[package]] +name = "hypothesis" +version = "6.131.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "sortedcontainers" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/10/ff/217417d065aa8a4e6815ddc39acee1222f1b67bd0e4803b85de86a837873/hypothesis-6.131.9.tar.gz", hash = "sha256:ee9b0e1403e1121c91921dbdc79d7f509fdb96d457a0389222d2a68d6c8a8f8e", size = 435415 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bd/e5/41a6733bfe11997795669dec3b3d785c28918e06568a2540dcc29f0d3fa7/hypothesis-6.131.9-py3-none-any.whl", hash = "sha256:7c2d9d6382e98e5337b27bd34e5b223bac23956787a827e1d087e00d893561d6", size = 499853 }, +] + +[[package]] +name = "idna" +version = "3.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 }, +] + +[[package]] +name = "importlib-metadata" +version = "8.7.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "zipp", marker = "python_full_version < '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/76/66/650a33bd90f786193e4de4b3ad86ea60b53c89b669a5c7be931fac31cdb0/importlib_metadata-8.7.0.tar.gz", hash = "sha256:d13b81ad223b890aa16c5471f2ac3056cf76c5f10f82d6f9292f0b415f389000", size = 56641 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/b0/36bd937216ec521246249be3bf9855081de4c5e06a0c9b4219dbeda50373/importlib_metadata-8.7.0-py3-none-any.whl", hash = "sha256:e5dd1551894c77868a30651cef00984d50e1002d06942a7101d34870c5f02afd", size = 27656 }, +] + +[[package]] +name = "importlib-resources" +version = "6.5.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "zipp", marker = "python_full_version < '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cf/8c/f834fbf984f691b4f7ff60f50b514cc3de5cc08abfc3295564dd89c5e2e7/importlib_resources-6.5.2.tar.gz", hash = "sha256:185f87adef5bcc288449d98fb4fba07cea78bc036455dd44c5fc4a2fe78fed2c", size = 44693 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a4/ed/1f1afb2e9e7f38a545d628f864d562a5ae64fe6f7a10e28ffb9b185b4e89/importlib_resources-6.5.2-py3-none-any.whl", hash = "sha256:789cfdc3ed28c78b67a06acb8126751ced69a3d5f79c095a98298cd8a760ccec", size = 37461 }, +] + +[[package]] +name = "iniconfig" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050 }, +] + +[[package]] +name = "isort" +version = "6.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b8/21/1e2a441f74a653a144224d7d21afe8f4169e6c7c20bb13aec3a2dc3815e0/isort-6.0.1.tar.gz", hash = "sha256:1cb5df28dfbc742e490c5e41bad6da41b805b0a8be7bc93cd0fb2a8a890ac450", size = 821955 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/11/114d0a5f4dabbdcedc1125dee0888514c3c3b16d3e9facad87ed96fad97c/isort-6.0.1-py3-none-any.whl", hash = "sha256:2dc5d7f65c9678d94c88dfc29161a320eec67328bc97aad576874cb4be1e9615", size = 94186 }, +] + +[[package]] +name = "jax" +version = "0.4.30" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] +dependencies = [ + { name = "importlib-metadata", marker = "python_full_version < '3.10'" }, + { name = "jaxlib", version = "0.4.30", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "ml-dtypes", marker = "python_full_version < '3.10'" }, + { name = "numpy", marker = "python_full_version < '3.10'" }, + { name = "opt-einsum", marker = "python_full_version < '3.10'" }, + { name = "scipy", version = "1.13.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/15/41/d6dbafc31d6bd93eeec2e1c709adfa454266e83714ebeeed9de52a6ad881/jax-0.4.30.tar.gz", hash = "sha256:94d74b5b2db0d80672b61d83f1f63ebf99d2ab7398ec12b2ca0c9d1e97afe577", size = 1715462 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fd/f2/9dbb75de3058acfd1600cf0839bcce7ea391148c9d2b4fa5f5666e66f09e/jax-0.4.30-py3-none-any.whl", hash = "sha256:289b30ae03b52f7f4baf6ef082a9f4e3e29c1080e22d13512c5ecf02d5f1a55b", size = 2009197 }, +] + +[[package]] +name = "jax" +version = "0.5.3" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.12'", + "python_full_version == '3.11.*'", + "python_full_version == '3.10.*'", +] +dependencies = [ + { name = "jaxlib", version = "0.5.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "ml-dtypes", marker = "python_full_version >= '3.10'" }, + { name = "numpy", marker = "python_full_version >= '3.10'" }, + { name = "opt-einsum", marker = "python_full_version >= '3.10'" }, + { name = "scipy", version = "1.15.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/13/e5/dabb73ab10330e9535aba14fc668b04a46fcd8e78f06567c4f4f1adce340/jax-0.5.3.tar.gz", hash = "sha256:f17fcb0fd61dc289394af6ce4de2dada2312f2689bb0d73642c6f026a95fbb2c", size = 2072748 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/86/bb/fdc6513a9aada13fd21e9860e2adee5f6eea2b4f0a145b219288875acb26/jax-0.5.3-py3-none-any.whl", hash = "sha256:1483dc237b4f47e41755d69429e8c3c138736716147cd43bb2b99b259d4e3c41", size = 2406371 }, +] + +[[package]] +name = "jaxlib" +version = "0.4.30" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] +dependencies = [ + { name = "ml-dtypes", marker = "python_full_version < '3.10'" }, + { name = "numpy", marker = "python_full_version < '3.10'" }, + { name = "scipy", version = "1.13.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/f3/18/ff7f2f6d6195853ed55c5b5d835f5c8c3c8b190c7221cb04a0cb81f5db10/jaxlib-0.4.30-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:c40856e28f300938c6824ab1a615166193d6997dec946578823f6d402ad454e5", size = 83542097 }, + { url = "https://files.pythonhosted.org/packages/d4/c0/ff65503ecfed3aee11e4abe4c4e9e8a3513f072e0b595f8247b9989d1510/jaxlib-0.4.30-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4bdfda6a3c7a2b0cc0a7131009eb279e98ca4a6f25679fabb5302dd135a5e349", size = 66694495 }, + { url = "https://files.pythonhosted.org/packages/b9/d7/82df748a31a1cfbd531a12979ea846d6b676d4adfa1e91114b848665b2aa/jaxlib-0.4.30-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:28e032c9b394ab7624d89b0d9d3bbcf4d1d71694fe8b3e09d3fe64122eda7b0c", size = 67781242 }, + { url = "https://files.pythonhosted.org/packages/4a/ca/561aabed63007bb2621a62f0d816aa2f68cfe947859c8b4e61519940344b/jaxlib-0.4.30-cp310-cp310-manylinux2014_x86_64.whl", hash = "sha256:d83f36ef42a403bbf7c7f2da526b34ba286988e170f4df5e58b3bb735417868c", size = 79640266 }, + { url = "https://files.pythonhosted.org/packages/b0/90/8e5347eda95d3cb695cd5ebb82f850fa7866078a6a7a0568549e34125a82/jaxlib-0.4.30-cp310-cp310-win_amd64.whl", hash = "sha256:a56678b28f96b524ded6da8ef4b38e72a532356d139cfd434da804abf4234e14", size = 51945307 }, + { url = "https://files.pythonhosted.org/packages/33/2d/b6078f5d173d3087d32b1b49e5f65d406985fb3894ff1d21905972b9c89d/jaxlib-0.4.30-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:bfb5d85b69c29c3c6e8051a0ea715ac1e532d6e54494c8d9c3813dcc00deac30", size = 83539315 }, + { url = "https://files.pythonhosted.org/packages/12/95/399da9204c3b13696baefb93468402f3389416b0caecfd9126aa94742bf2/jaxlib-0.4.30-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:974998cd8a78550402e6c09935c1f8d850cad9cc19ccd7488bde45b6f7f99c12", size = 66690971 }, + { url = "https://files.pythonhosted.org/packages/a4/f8/b85a46cb0cc4bc228cea4366b0d15caf42656c6d43cf8c91d90f7399aa4d/jaxlib-0.4.30-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:e93eb0646b41ba213252b51b0b69096b9cd1d81a35ea85c9d06663b5d11efe45", size = 67780747 }, + { url = "https://files.pythonhosted.org/packages/a6/a3/951da3d1487b2f8995a2a14cc7e9496c9a7c93aa1f1d0b33e833e24dee92/jaxlib-0.4.30-cp311-cp311-manylinux2014_x86_64.whl", hash = "sha256:16b2ab18ea90d2e15941bcf45de37afc2f289a029129c88c8d7aba0404dd0043", size = 79640352 }, + { url = "https://files.pythonhosted.org/packages/bb/1a/8f45ea28a5ca67e4d23ebd70fc78ea94be6fa20323f983c7607c32c6f9a5/jaxlib-0.4.30-cp311-cp311-win_amd64.whl", hash = "sha256:3a2e2c11c179f8851a72249ba1ae40ae817dfaee9877d23b3b8f7c6b7a012f76", size = 51943960 }, + { url = "https://files.pythonhosted.org/packages/19/40/ae943d3c1fc8b50947aebbaa3bad2842759e43bc9fc91e1758c1c20a81ab/jaxlib-0.4.30-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:7704db5962b32a2be3cc07185433cbbcc94ed90ee50c84021a3f8a1ecfd66ee3", size = 83587124 }, + { url = "https://files.pythonhosted.org/packages/c6/e3/97f8edff6f64245a500415be021869522b235e8b38cd930d358b91243583/jaxlib-0.4.30-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:57090d33477fd0f0c99dc686274882ea75c44c7d712ae42dd2460b10f896131d", size = 66724768 }, + { url = "https://files.pythonhosted.org/packages/4c/c7/ee1f48f8daa409d0ed039e0d8b5ae1a447e53db3acb2ff06239828ad96d5/jaxlib-0.4.30-cp312-cp312-manylinux2014_aarch64.whl", hash = "sha256:0a3850e76278038e21685975a62b622bcf3708485f13125757a0561ee4512940", size = 67800348 }, + { url = "https://files.pythonhosted.org/packages/f2/fa/a2dddea0d6965b8e433bb99aeedbe5c8a9b47110c1c4f197a7b6239daf44/jaxlib-0.4.30-cp312-cp312-manylinux2014_x86_64.whl", hash = "sha256:c58a8071c4e00898282118169f6a5a97eb15a79c2897858f3a732b17891c99ab", size = 79674030 }, + { url = "https://files.pythonhosted.org/packages/db/31/3500633d61b20b882a0fbcf8100013195c31b51f71249b0b38737851fc9a/jaxlib-0.4.30-cp312-cp312-win_amd64.whl", hash = "sha256:b7079a5b1ab6864a7d4f2afaa963841451186d22c90f39719a3ff85735ce3915", size = 51965689 }, + { url = "https://files.pythonhosted.org/packages/46/12/9de601dbae3c66666eeaaf5a28683d947909c046880baef390b7cd1d4b1d/jaxlib-0.4.30-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:ea3a00005faafbe3c18b178d3b534208b3b4027b2be6230227e7b87ce399fc29", size = 83544602 }, + { url = "https://files.pythonhosted.org/packages/f3/1d/2d417a1445d5e696bb44d564c7519d4a6761db4d3e31712620c510ed0127/jaxlib-0.4.30-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3d31e01191ce8052bd611aaf16ff967d8d0ec0b63f1ea4b199020cecb248d667", size = 66695975 }, + { url = "https://files.pythonhosted.org/packages/e4/f9/e29370046f4648bd464df7eceaebbbaefd091cc88c77da4a6e3a5f1a00d7/jaxlib-0.4.30-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:11602d5556e8baa2f16314c36518e9be4dfae0c2c256a361403fb29dc9dc79a4", size = 67784388 }, + { url = "https://files.pythonhosted.org/packages/07/3b/a596036325666624ca084df554636fb3777e78e9386b52476d96fa14394e/jaxlib-0.4.30-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:f74a6b0e09df4b5e2ee399ebb9f0e01190e26e84ccb0a758fadb516415c07f18", size = 79643370 }, + { url = "https://files.pythonhosted.org/packages/8a/a3/7342ceb02e49803af9a42ab3ad9b6c272cf7b2a83163e3a06859360012d5/jaxlib-0.4.30-cp39-cp39-win_amd64.whl", hash = "sha256:54987e97a22db70f3829b437b9329e4799d653634bacc8b398554d3b90c76b2a", size = 51946140 }, +] + +[[package]] +name = "jaxlib" +version = "0.5.3" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.12'", + "python_full_version == '3.11.*'", + "python_full_version == '3.10.*'", +] +dependencies = [ + { name = "ml-dtypes", marker = "python_full_version >= '3.10'" }, + { name = "numpy", marker = "python_full_version >= '3.10'" }, + { name = "scipy", version = "1.15.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/2e/12/b1da8468ad843b30976b0e87c6b344ee621fb75ef8bbd39156a303f59059/jaxlib-0.5.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:48ff5c89fb8a0fe04d475e9ddc074b4879a91d7ab68a51cec5cd1e87f81e6c47", size = 63694868 }, + { url = "https://files.pythonhosted.org/packages/0e/a5/378d71e8bcffbb229a0952d713a2ed766c959a04777abc0ee01b5aac29b7/jaxlib-0.5.3-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:972400db4af6e85270d81db5e6e620d31395f0472e510c50dfcd4cb3f72b7220", size = 95766664 }, + { url = "https://files.pythonhosted.org/packages/f1/86/1edf85f425532cbba0180d969f396590dd266909e4dfb0e95f8ee9a8e5fe/jaxlib-0.5.3-cp310-cp310-manylinux2014_x86_64.whl", hash = "sha256:52be6c9775aff738a61170d8c047505c75bb799a45518e66a7a0908127b11785", size = 105118562 }, + { url = "https://files.pythonhosted.org/packages/61/84/427cd89dd7904a4c923a3fc5494daec8d42d824c1a40d7a5d1c985e2f5ac/jaxlib-0.5.3-cp310-cp310-win_amd64.whl", hash = "sha256:b41a6fcaeb374fabc4ee7e74cfed60843bdab607cd54f60a68b7f7655cde2b66", size = 65766784 }, + { url = "https://files.pythonhosted.org/packages/c2/f2/d9397f264141f2289e229b2faf3b3ddb6397b014a09abe234367814f9697/jaxlib-0.5.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b62bd8b29e5a4f9bfaa57c8daf6e04820b2c994f448f3dec602d64255545e9f2", size = 63696815 }, + { url = "https://files.pythonhosted.org/packages/e8/91/04bf391a21ccfb299b9952f91d5c082e5f9877221e5d98592875af4a50e4/jaxlib-0.5.3-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:a4666f81d72c060ed3e581ded116a9caa9b0a70a148a54cb12a1d3afca3624b5", size = 95770114 }, + { url = "https://files.pythonhosted.org/packages/67/de/50debb40944baa5ba459604578f8c721be9f38c78ef9e8902895566e6a66/jaxlib-0.5.3-cp311-cp311-manylinux2014_x86_64.whl", hash = "sha256:29e1530fc81833216f1e28b578d0c59697654f72ee31c7a44ed7753baf5ac466", size = 105119259 }, + { url = "https://files.pythonhosted.org/packages/20/91/d73c842d1e5cc6b914bb521006d668fbfda4c53cd4424ce9c3a097f6c071/jaxlib-0.5.3-cp311-cp311-win_amd64.whl", hash = "sha256:8eb54e38d789557579f900ea3d70f104a440f8555a9681ed45f4a122dcbfd92e", size = 65765739 }, + { url = "https://files.pythonhosted.org/packages/d5/a5/646af791ccf75641b4df84fb6cb6e3914b0df87ec5fa5f82397fd5dc30ee/jaxlib-0.5.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d394dbde4a1c6bd67501cfb29d3819a10b900cb534cc0fc603319f7092f24cfa", size = 63711839 }, + { url = "https://files.pythonhosted.org/packages/53/8c/cbd861e40f0efe7923962ade21919fddcea43fae2794634833e800009b14/jaxlib-0.5.3-cp312-cp312-manylinux2014_aarch64.whl", hash = "sha256:bddf6360377aa1c792e47fd87f307c342e331e5ff3582f940b1bca00f6b4bc73", size = 95764647 }, + { url = "https://files.pythonhosted.org/packages/3e/03/bace4acec295febca9329b3d2dd927b8ac74841e620e0d675f76109b805b/jaxlib-0.5.3-cp312-cp312-manylinux2014_x86_64.whl", hash = "sha256:5a5e88ab1cd6fdf78d69abe3544e8f09cce200dd339bb85fbe3c2ea67f2a5e68", size = 105132789 }, + { url = "https://files.pythonhosted.org/packages/79/f8/34568ec75f53d55b68649b6e1d6befd976fb9646e607954477264f5379ce/jaxlib-0.5.3-cp312-cp312-win_amd64.whl", hash = "sha256:520665929649f29f7d948d4070dbaf3e032a4c1f7c11f2863eac73320fcee784", size = 65789714 }, + { url = "https://files.pythonhosted.org/packages/b4/d0/ed6007cd17dc0f37f950f89e785092d9f0541f3fa6021d029657955206b5/jaxlib-0.5.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:31321c25282a06a6dfc940507bc14d0a0ac838d8ced6c07aa00a7fae34ce7b3f", size = 63710483 }, + { url = "https://files.pythonhosted.org/packages/36/8f/cafdf24170084de897ffe2a030241c2ba72d12eede85b940a81a94cab156/jaxlib-0.5.3-cp313-cp313-manylinux2014_aarch64.whl", hash = "sha256:e904b92dedfbc7e545725a8d7676987030ae9c069001d94701bc109c6dab4100", size = 95765995 }, + { url = "https://files.pythonhosted.org/packages/86/c7/fc0755ebd999c7c66ac4203d99f958d5ffc0a34eb270f57932ca0213bb54/jaxlib-0.5.3-cp313-cp313-manylinux2014_x86_64.whl", hash = "sha256:bb7593cb7fffcb13963f22fa5229ed960b8fb4ae5ec3b0820048cbd67f1e8e31", size = 105130796 }, + { url = "https://files.pythonhosted.org/packages/83/98/e32da21a490dc408d172ba246d6c47428482fe50d771c3f813e5fc063781/jaxlib-0.5.3-cp313-cp313-win_amd64.whl", hash = "sha256:8019f73a10b1290f988dd3768c684f3a8a147239091c3b790ce7e47e3bbc00bd", size = 65792205 }, + { url = "https://files.pythonhosted.org/packages/88/c6/0d69ed0d408c811959a471563afa99baecacdc56ed1799002e309520b565/jaxlib-0.5.3-cp313-cp313t-manylinux2014_x86_64.whl", hash = "sha256:4c9a9d4cda091a3ef068ace8379fff9e98eea2fc51dbdd7c3386144a1bdf715d", size = 105318736 }, +] + +[[package]] +name = "jinja2" +version = "3.1.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899 }, +] + +[[package]] +name = "keras" +version = "3.9.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "absl-py" }, + { name = "h5py" }, + { name = "ml-dtypes" }, + { name = "namex" }, + { name = "numpy" }, + { name = "optree" }, + { name = "packaging" }, + { name = "rich" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/28/4e/82a1176f1ea70982ade0f7e360c6f259b68203f64a108cc1967500d4b7ff/keras-3.9.2.tar.gz", hash = "sha256:322aab6418ee3de1e2bd0871b60a07f0e444e744a7e8cba79af8b42408879ecf", size = 1002482 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3f/0a/678ebcf4b6dad6ad63dfc2445d190f79a97fa7bc7150f57a6c505459e2bc/keras-3.9.2-py3-none-any.whl", hash = "sha256:404427856c2dc30e38c9fa6fa6a13ffb1844a8c35af312ca32a8e7dea9840f1e", size = 1341966 }, +] + +[[package]] +name = "libclang" +version = "18.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6e/5c/ca35e19a4f142adffa27e3d652196b7362fa612243e2b916845d801454fc/libclang-18.1.1.tar.gz", hash = "sha256:a1214966d08d73d971287fc3ead8dfaf82eb07fb197680d8b3859dbbbbf78250", size = 39612 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4b/49/f5e3e7e1419872b69f6f5e82ba56e33955a74bd537d8a1f5f1eff2f3668a/libclang-18.1.1-1-py2.py3-none-macosx_11_0_arm64.whl", hash = "sha256:0b2e143f0fac830156feb56f9231ff8338c20aecfe72b4ffe96f19e5a1dbb69a", size = 25836045 }, + { url = "https://files.pythonhosted.org/packages/e2/e5/fc61bbded91a8830ccce94c5294ecd6e88e496cc85f6704bf350c0634b70/libclang-18.1.1-py2.py3-none-macosx_10_9_x86_64.whl", hash = "sha256:6f14c3f194704e5d09769108f03185fce7acaf1d1ae4bbb2f30a72c2400cb7c5", size = 26502641 }, + { url = "https://files.pythonhosted.org/packages/db/ed/1df62b44db2583375f6a8a5e2ca5432bbdc3edb477942b9b7c848c720055/libclang-18.1.1-py2.py3-none-macosx_11_0_arm64.whl", hash = "sha256:83ce5045d101b669ac38e6da8e58765f12da2d3aafb3b9b98d88b286a60964d8", size = 26420207 }, + { url = "https://files.pythonhosted.org/packages/1d/fc/716c1e62e512ef1c160e7984a73a5fc7df45166f2ff3f254e71c58076f7c/libclang-18.1.1-py2.py3-none-manylinux2010_x86_64.whl", hash = "sha256:c533091d8a3bbf7460a00cb6c1a71da93bffe148f172c7d03b1c31fbf8aa2a0b", size = 24515943 }, + { url = "https://files.pythonhosted.org/packages/3c/3d/f0ac1150280d8d20d059608cf2d5ff61b7c3b7f7bcf9c0f425ab92df769a/libclang-18.1.1-py2.py3-none-manylinux2014_aarch64.whl", hash = "sha256:54dda940a4a0491a9d1532bf071ea3ef26e6dbaf03b5000ed94dd7174e8f9592", size = 23784972 }, + { url = "https://files.pythonhosted.org/packages/fe/2f/d920822c2b1ce9326a4c78c0c2b4aa3fde610c7ee9f631b600acb5376c26/libclang-18.1.1-py2.py3-none-manylinux2014_armv7l.whl", hash = "sha256:cf4a99b05376513717ab5d82a0db832c56ccea4fd61a69dbb7bccf2dfb207dbe", size = 20259606 }, + { url = "https://files.pythonhosted.org/packages/2d/c2/de1db8c6d413597076a4259cea409b83459b2db997c003578affdd32bf66/libclang-18.1.1-py2.py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:69f8eb8f65c279e765ffd28aaa7e9e364c776c17618af8bff22a8df58677ff4f", size = 24921494 }, + { url = "https://files.pythonhosted.org/packages/0b/2d/3f480b1e1d31eb3d6de5e3ef641954e5c67430d5ac93b7fa7e07589576c7/libclang-18.1.1-py2.py3-none-win_amd64.whl", hash = "sha256:4dd2d3b82fab35e2bf9ca717d7b63ac990a3519c7e312f19fa8e86dcc712f7fb", size = 26415083 }, + { url = "https://files.pythonhosted.org/packages/71/cf/e01dc4cc79779cd82d77888a88ae2fa424d93b445ad4f6c02bfc18335b70/libclang-18.1.1-py2.py3-none-win_arm64.whl", hash = "sha256:3f0e1f49f04d3cd198985fea0511576b0aee16f9ff0e0f0cad7f9c57ec3c20e8", size = 22361112 }, +] + +[[package]] +name = "markdown" +version = "3.8" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "importlib-metadata", marker = "python_full_version < '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2f/15/222b423b0b88689c266d9eac4e61396fe2cc53464459d6a37618ac863b24/markdown-3.8.tar.gz", hash = "sha256:7df81e63f0df5c4b24b7d156eb81e4690595239b7d70937d0409f1b0de319c6f", size = 360906 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/51/3f/afe76f8e2246ffbc867440cbcf90525264df0e658f8a5ca1f872b3f6192a/markdown-3.8-py3-none-any.whl", hash = "sha256:794a929b79c5af141ef5ab0f2f642d0f7b1872981250230e72682346f7cc90dc", size = 106210 }, +] + +[[package]] +name = "markdown-it-py" +version = "3.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mdurl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528 }, +] + +[[package]] +name = "markupsafe" +version = "3.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b2/97/5d42485e71dfc078108a86d6de8fa46db44a1a9295e89c5d6d4a06e23a62/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", size = 20537 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/90/d08277ce111dd22f77149fd1a5d4653eeb3b3eaacbdfcbae5afb2600eebd/MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8", size = 14357 }, + { url = "https://files.pythonhosted.org/packages/04/e1/6e2194baeae0bca1fae6629dc0cbbb968d4d941469cbab11a3872edff374/MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158", size = 12393 }, + { url = "https://files.pythonhosted.org/packages/1d/69/35fa85a8ece0a437493dc61ce0bb6d459dcba482c34197e3efc829aa357f/MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579", size = 21732 }, + { url = "https://files.pythonhosted.org/packages/22/35/137da042dfb4720b638d2937c38a9c2df83fe32d20e8c8f3185dbfef05f7/MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d", size = 20866 }, + { url = "https://files.pythonhosted.org/packages/29/28/6d029a903727a1b62edb51863232152fd335d602def598dade38996887f0/MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb", size = 20964 }, + { url = "https://files.pythonhosted.org/packages/cc/cd/07438f95f83e8bc028279909d9c9bd39e24149b0d60053a97b2bc4f8aa51/MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b", size = 21977 }, + { url = "https://files.pythonhosted.org/packages/29/01/84b57395b4cc062f9c4c55ce0df7d3108ca32397299d9df00fedd9117d3d/MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c", size = 21366 }, + { url = "https://files.pythonhosted.org/packages/bd/6e/61ebf08d8940553afff20d1fb1ba7294b6f8d279df9fd0c0db911b4bbcfd/MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171", size = 21091 }, + { url = "https://files.pythonhosted.org/packages/11/23/ffbf53694e8c94ebd1e7e491de185124277964344733c45481f32ede2499/MarkupSafe-3.0.2-cp310-cp310-win32.whl", hash = "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50", size = 15065 }, + { url = "https://files.pythonhosted.org/packages/44/06/e7175d06dd6e9172d4a69a72592cb3f7a996a9c396eee29082826449bbc3/MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a", size = 15514 }, + { url = "https://files.pythonhosted.org/packages/6b/28/bbf83e3f76936960b850435576dd5e67034e200469571be53f69174a2dfd/MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d", size = 14353 }, + { url = "https://files.pythonhosted.org/packages/6c/30/316d194b093cde57d448a4c3209f22e3046c5bb2fb0820b118292b334be7/MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93", size = 12392 }, + { url = "https://files.pythonhosted.org/packages/f2/96/9cdafba8445d3a53cae530aaf83c38ec64c4d5427d975c974084af5bc5d2/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832", size = 23984 }, + { url = "https://files.pythonhosted.org/packages/f1/a4/aefb044a2cd8d7334c8a47d3fb2c9f328ac48cb349468cc31c20b539305f/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84", size = 23120 }, + { url = "https://files.pythonhosted.org/packages/8d/21/5e4851379f88f3fad1de30361db501300d4f07bcad047d3cb0449fc51f8c/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca", size = 23032 }, + { url = "https://files.pythonhosted.org/packages/00/7b/e92c64e079b2d0d7ddf69899c98842f3f9a60a1ae72657c89ce2655c999d/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798", size = 24057 }, + { url = "https://files.pythonhosted.org/packages/f9/ac/46f960ca323037caa0a10662ef97d0a4728e890334fc156b9f9e52bcc4ca/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e", size = 23359 }, + { url = "https://files.pythonhosted.org/packages/69/84/83439e16197337b8b14b6a5b9c2105fff81d42c2a7c5b58ac7b62ee2c3b1/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4", size = 23306 }, + { url = "https://files.pythonhosted.org/packages/9a/34/a15aa69f01e2181ed8d2b685c0d2f6655d5cca2c4db0ddea775e631918cd/MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d", size = 15094 }, + { url = "https://files.pythonhosted.org/packages/da/b8/3a3bd761922d416f3dc5d00bfbed11f66b1ab89a0c2b6e887240a30b0f6b/MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b", size = 15521 }, + { url = "https://files.pythonhosted.org/packages/22/09/d1f21434c97fc42f09d290cbb6350d44eb12f09cc62c9476effdb33a18aa/MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf", size = 14274 }, + { url = "https://files.pythonhosted.org/packages/6b/b0/18f76bba336fa5aecf79d45dcd6c806c280ec44538b3c13671d49099fdd0/MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225", size = 12348 }, + { url = "https://files.pythonhosted.org/packages/e0/25/dd5c0f6ac1311e9b40f4af06c78efde0f3b5cbf02502f8ef9501294c425b/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028", size = 24149 }, + { url = "https://files.pythonhosted.org/packages/f3/f0/89e7aadfb3749d0f52234a0c8c7867877876e0a20b60e2188e9850794c17/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8", size = 23118 }, + { url = "https://files.pythonhosted.org/packages/d5/da/f2eeb64c723f5e3777bc081da884b414671982008c47dcc1873d81f625b6/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c", size = 22993 }, + { url = "https://files.pythonhosted.org/packages/da/0e/1f32af846df486dce7c227fe0f2398dc7e2e51d4a370508281f3c1c5cddc/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557", size = 24178 }, + { url = "https://files.pythonhosted.org/packages/c4/f6/bb3ca0532de8086cbff5f06d137064c8410d10779c4c127e0e47d17c0b71/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22", size = 23319 }, + { url = "https://files.pythonhosted.org/packages/a2/82/8be4c96ffee03c5b4a034e60a31294daf481e12c7c43ab8e34a1453ee48b/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48", size = 23352 }, + { url = "https://files.pythonhosted.org/packages/51/ae/97827349d3fcffee7e184bdf7f41cd6b88d9919c80f0263ba7acd1bbcb18/MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30", size = 15097 }, + { url = "https://files.pythonhosted.org/packages/c1/80/a61f99dc3a936413c3ee4e1eecac96c0da5ed07ad56fd975f1a9da5bc630/MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87", size = 15601 }, + { url = "https://files.pythonhosted.org/packages/83/0e/67eb10a7ecc77a0c2bbe2b0235765b98d164d81600746914bebada795e97/MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd", size = 14274 }, + { url = "https://files.pythonhosted.org/packages/2b/6d/9409f3684d3335375d04e5f05744dfe7e9f120062c9857df4ab490a1031a/MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430", size = 12352 }, + { url = "https://files.pythonhosted.org/packages/d2/f5/6eadfcd3885ea85fe2a7c128315cc1bb7241e1987443d78c8fe712d03091/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094", size = 24122 }, + { url = "https://files.pythonhosted.org/packages/0c/91/96cf928db8236f1bfab6ce15ad070dfdd02ed88261c2afafd4b43575e9e9/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396", size = 23085 }, + { url = "https://files.pythonhosted.org/packages/c2/cf/c9d56af24d56ea04daae7ac0940232d31d5a8354f2b457c6d856b2057d69/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79", size = 22978 }, + { url = "https://files.pythonhosted.org/packages/2a/9f/8619835cd6a711d6272d62abb78c033bda638fdc54c4e7f4272cf1c0962b/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a", size = 24208 }, + { url = "https://files.pythonhosted.org/packages/f9/bf/176950a1792b2cd2102b8ffeb5133e1ed984547b75db47c25a67d3359f77/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca", size = 23357 }, + { url = "https://files.pythonhosted.org/packages/ce/4f/9a02c1d335caabe5c4efb90e1b6e8ee944aa245c1aaaab8e8a618987d816/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c", size = 23344 }, + { url = "https://files.pythonhosted.org/packages/ee/55/c271b57db36f748f0e04a759ace9f8f759ccf22b4960c270c78a394f58be/MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1", size = 15101 }, + { url = "https://files.pythonhosted.org/packages/29/88/07df22d2dd4df40aba9f3e402e6dc1b8ee86297dddbad4872bd5e7b0094f/MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f", size = 15603 }, + { url = "https://files.pythonhosted.org/packages/62/6a/8b89d24db2d32d433dffcd6a8779159da109842434f1dd2f6e71f32f738c/MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c", size = 14510 }, + { url = "https://files.pythonhosted.org/packages/7a/06/a10f955f70a2e5a9bf78d11a161029d278eeacbd35ef806c3fd17b13060d/MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb", size = 12486 }, + { url = "https://files.pythonhosted.org/packages/34/cf/65d4a571869a1a9078198ca28f39fba5fbb910f952f9dbc5220afff9f5e6/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c", size = 25480 }, + { url = "https://files.pythonhosted.org/packages/0c/e3/90e9651924c430b885468b56b3d597cabf6d72be4b24a0acd1fa0e12af67/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d", size = 23914 }, + { url = "https://files.pythonhosted.org/packages/66/8c/6c7cf61f95d63bb866db39085150df1f2a5bd3335298f14a66b48e92659c/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe", size = 23796 }, + { url = "https://files.pythonhosted.org/packages/bb/35/cbe9238ec3f47ac9a7c8b3df7a808e7cb50fe149dc7039f5f454b3fba218/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5", size = 25473 }, + { url = "https://files.pythonhosted.org/packages/e6/32/7621a4382488aa283cc05e8984a9c219abad3bca087be9ec77e89939ded9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a", size = 24114 }, + { url = "https://files.pythonhosted.org/packages/0d/80/0985960e4b89922cb5a0bac0ed39c5b96cbc1a536a99f30e8c220a996ed9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9", size = 24098 }, + { url = "https://files.pythonhosted.org/packages/82/78/fedb03c7d5380df2427038ec8d973587e90561b2d90cd472ce9254cf348b/MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6", size = 15208 }, + { url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739 }, + { url = "https://files.pythonhosted.org/packages/a7/ea/9b1530c3fdeeca613faeb0fb5cbcf2389d816072fab72a71b45749ef6062/MarkupSafe-3.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a", size = 14344 }, + { url = "https://files.pythonhosted.org/packages/4b/c2/fbdbfe48848e7112ab05e627e718e854d20192b674952d9042ebd8c9e5de/MarkupSafe-3.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff", size = 12389 }, + { url = "https://files.pythonhosted.org/packages/f0/25/7a7c6e4dbd4f867d95d94ca15449e91e52856f6ed1905d58ef1de5e211d0/MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13", size = 21607 }, + { url = "https://files.pythonhosted.org/packages/53/8f/f339c98a178f3c1e545622206b40986a4c3307fe39f70ccd3d9df9a9e425/MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144", size = 20728 }, + { url = "https://files.pythonhosted.org/packages/1a/03/8496a1a78308456dbd50b23a385c69b41f2e9661c67ea1329849a598a8f9/MarkupSafe-3.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29", size = 20826 }, + { url = "https://files.pythonhosted.org/packages/e6/cf/0a490a4bd363048c3022f2f475c8c05582179bb179defcee4766fb3dcc18/MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0", size = 21843 }, + { url = "https://files.pythonhosted.org/packages/19/a3/34187a78613920dfd3cdf68ef6ce5e99c4f3417f035694074beb8848cd77/MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0", size = 21219 }, + { url = "https://files.pythonhosted.org/packages/17/d8/5811082f85bb88410ad7e452263af048d685669bbbfb7b595e8689152498/MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178", size = 20946 }, + { url = "https://files.pythonhosted.org/packages/7c/31/bd635fb5989440d9365c5e3c47556cfea121c7803f5034ac843e8f37c2f2/MarkupSafe-3.0.2-cp39-cp39-win32.whl", hash = "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f", size = 15063 }, + { url = "https://files.pythonhosted.org/packages/b3/73/085399401383ce949f727afec55ec3abd76648d04b9f22e1c0e99cb4bec3/MarkupSafe-3.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a", size = 15506 }, +] + +[[package]] +name = "mccabe" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/ff/0ffefdcac38932a54d2b5eed4e0ba8a408f215002cd178ad1df0f2806ff8/mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325", size = 9658 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/27/1a/1f68f9ba0c207934b35b86a8ca3aad8395a3d6dd7921c0686e23853ff5a9/mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e", size = 7350 }, +] + +[[package]] +name = "mdurl" +version = "0.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979 }, +] + +[[package]] +name = "ml-dtypes" +version = "0.4.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fd/15/76f86faa0902836cc133939732f7611ace68cf54148487a99c539c272dc8/ml_dtypes-0.4.1.tar.gz", hash = "sha256:fad5f2de464fd09127e49b7fd1252b9006fb43d2edc1ff112d390c324af5ca7a", size = 692594 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/56/9e/76b84f77c7afee3b116dc8407903a2d5004ba3059a8f3dcdcfa6ebf33fff/ml_dtypes-0.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1fe8b5b5e70cd67211db94b05cfd58dace592f24489b038dc6f9fe347d2e07d5", size = 397975 }, + { url = "https://files.pythonhosted.org/packages/03/7b/32650e1b2a2713a5923a0af2a8503d0d4a8fc99d1e1e0a1c40e996634460/ml_dtypes-0.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c09a6d11d8475c2a9fd2bc0695628aec105f97cab3b3a3fb7c9660348ff7d24", size = 2182570 }, + { url = "https://files.pythonhosted.org/packages/16/86/a9f7569e7e4f5395f927de38a13b92efa73f809285d04f2923b291783dd2/ml_dtypes-0.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f5e8f75fa371020dd30f9196e7d73babae2abd51cf59bdd56cb4f8de7e13354", size = 2160365 }, + { url = "https://files.pythonhosted.org/packages/04/1b/9a3afb437702503514f3934ec8d7904270edf013d28074f3e700e5dfbb0f/ml_dtypes-0.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:15fdd922fea57e493844e5abb930b9c0bd0af217d9edd3724479fc3d7ce70e3f", size = 126633 }, + { url = "https://files.pythonhosted.org/packages/d1/76/9835c8609c29f2214359e88f29255fc4aad4ea0f613fb48aa8815ceda1b6/ml_dtypes-0.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2d55b588116a7085d6e074cf0cdb1d6fa3875c059dddc4d2c94a4cc81c23e975", size = 397973 }, + { url = "https://files.pythonhosted.org/packages/7e/99/e68c56fac5de973007a10254b6e17a0362393724f40f66d5e4033f4962c2/ml_dtypes-0.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e138a9b7a48079c900ea969341a5754019a1ad17ae27ee330f7ebf43f23877f9", size = 2185134 }, + { url = "https://files.pythonhosted.org/packages/28/bc/6a2344338ea7b61cd7b46fb24ec459360a5a0903b57c55b156c1e46c644a/ml_dtypes-0.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:74c6cfb5cf78535b103fde9ea3ded8e9f16f75bc07789054edc7776abfb3d752", size = 2163661 }, + { url = "https://files.pythonhosted.org/packages/e8/d3/ddfd9878b223b3aa9a930c6100a99afca5cfab7ea703662e00323acb7568/ml_dtypes-0.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:274cc7193dd73b35fb26bef6c5d40ae3eb258359ee71cd82f6e96a8c948bdaa6", size = 126727 }, + { url = "https://files.pythonhosted.org/packages/ba/1a/99e924f12e4b62139fbac87419698c65f956d58de0dbfa7c028fa5b096aa/ml_dtypes-0.4.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:827d3ca2097085cf0355f8fdf092b888890bb1b1455f52801a2d7756f056f54b", size = 405077 }, + { url = "https://files.pythonhosted.org/packages/8f/8c/7b610bd500617854c8cc6ed7c8cfb9d48d6a5c21a1437a36a4b9bc8a3598/ml_dtypes-0.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:772426b08a6172a891274d581ce58ea2789cc8abc1c002a27223f314aaf894e7", size = 2181554 }, + { url = "https://files.pythonhosted.org/packages/c7/c6/f89620cecc0581dc1839e218c4315171312e46c62a62da6ace204bda91c0/ml_dtypes-0.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:126e7d679b8676d1a958f2651949fbfa182832c3cd08020d8facd94e4114f3e9", size = 2160488 }, + { url = "https://files.pythonhosted.org/packages/ae/11/a742d3c31b2cc8557a48efdde53427fd5f9caa2fa3c9c27d826e78a66f51/ml_dtypes-0.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:df0fb650d5c582a9e72bb5bd96cfebb2cdb889d89daff621c8fbc60295eba66c", size = 127462 }, + { url = "https://files.pythonhosted.org/packages/8f/d7/6e1372052fe95c0cacfdb9718dba04726203885ffddb0cfddd8f8aa89a3b/ml_dtypes-0.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e35e486e97aee577d0890bc3bd9e9f9eece50c08c163304008587ec8cfe7575b", size = 396578 }, + { url = "https://files.pythonhosted.org/packages/1a/f6/ad0bd2735b9570ebf9c113f024b4f2b34f2331f16197c60babdc168b22d5/ml_dtypes-0.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:560be16dc1e3bdf7c087eb727e2cf9c0e6a3d87e9f415079d2491cc419b3ebf5", size = 2181057 }, + { url = "https://files.pythonhosted.org/packages/3e/55/b9711de47135d4d8766ff7907fe54c8bffff545fd646817c352de37b0ad5/ml_dtypes-0.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad0b757d445a20df39035c4cdeed457ec8b60d236020d2560dbc25887533cf50", size = 2156131 }, + { url = "https://files.pythonhosted.org/packages/4b/f3/e5ff8dd27f66c8b80f97f0f89bb0b74e4a7005e5ff5f8f4237126c827911/ml_dtypes-0.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:ef0d7e3fece227b49b544fa69e50e607ac20948f0043e9f76b44f35f229ea450", size = 126727 }, +] + +[[package]] +name = "mlx" +version = "0.25.1" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8b/42/6ce1ce83a8d7b600a69bde314b4c1b3e6aaeb6acd83d762124162dd8a751/mlx-0.25.1-cp310-cp310-macosx_13_0_arm64.whl", hash = "sha256:d13aa885d38a04d32f9818fffbceaa17555eb67fea02d16e53d2217ab4d8eb5d", size = 30723244 }, + { url = "https://files.pythonhosted.org/packages/fc/cd/bdbc33a51fa5ada9d593e8c4c491331ce57e5ab49e0d107f214e340c4417/mlx-0.25.1-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:d07082c35e4196fdc17813f344a529dbc6c7210edb35aaa5833cf3509fecf183", size = 30134290 }, + { url = "https://files.pythonhosted.org/packages/df/88/60f88cf4717ee497f0ba1f3ae77ace23cef486eaed1c85bbc65d81e2b687/mlx-0.25.1-cp310-cp310-macosx_15_0_arm64.whl", hash = "sha256:1fdafc0b247e22d324699245e2a339225265d3b6d12e669fe02402eb73f46216", size = 30134777 }, + { url = "https://files.pythonhosted.org/packages/0d/99/24b7c3622aab9eef8875fd96ae9183923ef8da00ecfe0997c9979c9a4f84/mlx-0.25.1-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:c647a242a7880ad89215a118df2f7d97b554fa54e55cc1b90ef7506e593a83eb", size = 30723278 }, + { url = "https://files.pythonhosted.org/packages/33/a0/9694271393ec8f135f4a3b1f16a9b475f3ea42e8fe4a18397b5680e6f162/mlx-0.25.1-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:d6da7ab9e51fd780083a3003c96cdd538b465d2b1a16e2fd77217348c70dfb44", size = 30134574 }, + { url = "https://files.pythonhosted.org/packages/60/7e/16c84be009c0c37862aa328915c2d188abd05756819668e87d138dabe353/mlx-0.25.1-cp311-cp311-macosx_15_0_arm64.whl", hash = "sha256:db0caac2c9dd6fe0ae15448b4dcb40cd3bd28d6ad9f935e2c383eb1844af77a2", size = 30135217 }, + { url = "https://files.pythonhosted.org/packages/8c/44/868009d072fca94fabf1cdb55a6c61d49ce72bc829a560d05ec94714cd0c/mlx-0.25.1-cp312-cp312-macosx_13_0_arm64.whl", hash = "sha256:8f6c0754570a94be4a1b25ce10986665ed0b57ee8ad8f50bc713b4801264eb98", size = 30717669 }, + { url = "https://files.pythonhosted.org/packages/64/8e/f84e1fada4f64d9a88974e3b208eedd5dfa94f06d542c86ff1a7a9d1197c/mlx-0.25.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:bc9a387819fc214dc915b2fff9164346bf9c3aa90aabcc38dbf1c232329861f7", size = 30135893 }, + { url = "https://files.pythonhosted.org/packages/b1/19/7174aeea051995d10d0b09383c6b2b88a1222e17d7a41151becf87dc3c46/mlx-0.25.1-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:cb6e5fb85535c3438bcb16e616e3aa2ec47844fcadf67d85ee862b256369f185", size = 30136426 }, + { url = "https://files.pythonhosted.org/packages/02/1b/7da8f1d224a4287cdd5eda77d878a73ff13c22e2c89097bc6effcc5c318a/mlx-0.25.1-cp313-cp313-macosx_13_0_arm64.whl", hash = "sha256:f2ca5c2f60804bbb3968ee3e087ce4cf5789065f4c927f76b025b3f5f122a63a", size = 30717676 }, + { url = "https://files.pythonhosted.org/packages/50/0f/1b4752c9325716ae7d1b8050442fe28372390cf2a4d993456535c4f50e16/mlx-0.25.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:59d233b12dc0c003d63883c73abbf40e29fe0a3176dd9d2095399c5f3688eb58", size = 30135902 }, + { url = "https://files.pythonhosted.org/packages/53/06/10f2465ea3b1fa2d7ca31e79b19869f8df0de4b8b57a932eab607aa36e3f/mlx-0.25.1-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:67d192dbd0677ea365f3305592ddb449488f3486f4791a7ac2e76494bea668a5", size = 30136384 }, + { url = "https://files.pythonhosted.org/packages/41/c8/3b872d4a32042973d1d24900215e1b299a8e648fd95de8b1c0144e423819/mlx-0.25.1-cp39-cp39-macosx_13_0_arm64.whl", hash = "sha256:324de0673922309fe0ab3a230fa66a7d0ce4f4b9b2e9d273f2816adddc99e285", size = 30723570 }, + { url = "https://files.pythonhosted.org/packages/b0/4e/da5e5cd2afe1e429c2893c7ed9bfb7ea9181f17e711b5515bca3e28a691b/mlx-0.25.1-cp39-cp39-macosx_14_0_arm64.whl", hash = "sha256:b7bb2e7e996c27a5e6ad19bbfc336bde71e0d4df23b5673a35087b321dd05b3b", size = 30134765 }, + { url = "https://files.pythonhosted.org/packages/b1/71/fc94cbe575b52ff1f0f95074b970271e93ff9a5d9e42864ea8f664c93e77/mlx-0.25.1-cp39-cp39-macosx_15_0_arm64.whl", hash = "sha256:138b0e7daf1f4014a184d8fc05df1f0a92a50fd99c9aeac8fef0b9bc31358cc1", size = 30135576 }, +] + +[[package]] +name = "mpmath" +version = "1.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e0/47/dd32fa426cc72114383ac549964eecb20ecfd886d1e5ccf5340b55b02f57/mpmath-1.3.0.tar.gz", hash = "sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f", size = 508106 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl", hash = "sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c", size = 536198 }, +] + +[[package]] +name = "msgpack" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cb/d0/7555686ae7ff5731205df1012ede15dd9d927f6227ea151e901c7406af4f/msgpack-1.1.0.tar.gz", hash = "sha256:dd432ccc2c72b914e4cb77afce64aab761c1137cc698be3984eee260bcb2896e", size = 167260 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4b/f9/a892a6038c861fa849b11a2bb0502c07bc698ab6ea53359e5771397d883b/msgpack-1.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7ad442d527a7e358a469faf43fda45aaf4ac3249c8310a82f0ccff9164e5dccd", size = 150428 }, + { url = "https://files.pythonhosted.org/packages/df/7a/d174cc6a3b6bb85556e6a046d3193294a92f9a8e583cdbd46dc8a1d7e7f4/msgpack-1.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:74bed8f63f8f14d75eec75cf3d04ad581da6b914001b474a5d3cd3372c8cc27d", size = 84131 }, + { url = "https://files.pythonhosted.org/packages/08/52/bf4fbf72f897a23a56b822997a72c16de07d8d56d7bf273242f884055682/msgpack-1.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:914571a2a5b4e7606997e169f64ce53a8b1e06f2cf2c3a7273aa106236d43dd5", size = 81215 }, + { url = "https://files.pythonhosted.org/packages/02/95/dc0044b439b518236aaf012da4677c1b8183ce388411ad1b1e63c32d8979/msgpack-1.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c921af52214dcbb75e6bdf6a661b23c3e6417f00c603dd2070bccb5c3ef499f5", size = 371229 }, + { url = "https://files.pythonhosted.org/packages/ff/75/09081792db60470bef19d9c2be89f024d366b1e1973c197bb59e6aabc647/msgpack-1.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8ce0b22b890be5d252de90d0e0d119f363012027cf256185fc3d474c44b1b9e", size = 378034 }, + { url = "https://files.pythonhosted.org/packages/32/d3/c152e0c55fead87dd948d4b29879b0f14feeeec92ef1fd2ec21b107c3f49/msgpack-1.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:73322a6cc57fcee3c0c57c4463d828e9428275fb85a27aa2aa1a92fdc42afd7b", size = 363070 }, + { url = "https://files.pythonhosted.org/packages/d9/2c/82e73506dd55f9e43ac8aa007c9dd088c6f0de2aa19e8f7330e6a65879fc/msgpack-1.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e1f3c3d21f7cf67bcf2da8e494d30a75e4cf60041d98b3f79875afb5b96f3a3f", size = 359863 }, + { url = "https://files.pythonhosted.org/packages/cb/a0/3d093b248837094220e1edc9ec4337de3443b1cfeeb6e0896af8ccc4cc7a/msgpack-1.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:64fc9068d701233effd61b19efb1485587560b66fe57b3e50d29c5d78e7fef68", size = 368166 }, + { url = "https://files.pythonhosted.org/packages/e4/13/7646f14f06838b406cf5a6ddbb7e8dc78b4996d891ab3b93c33d1ccc8678/msgpack-1.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:42f754515e0f683f9c79210a5d1cad631ec3d06cea5172214d2176a42e67e19b", size = 370105 }, + { url = "https://files.pythonhosted.org/packages/67/fa/dbbd2443e4578e165192dabbc6a22c0812cda2649261b1264ff515f19f15/msgpack-1.1.0-cp310-cp310-win32.whl", hash = "sha256:3df7e6b05571b3814361e8464f9304c42d2196808e0119f55d0d3e62cd5ea044", size = 68513 }, + { url = "https://files.pythonhosted.org/packages/24/ce/c2c8fbf0ded750cb63cbcbb61bc1f2dfd69e16dca30a8af8ba80ec182dcd/msgpack-1.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:685ec345eefc757a7c8af44a3032734a739f8c45d1b0ac45efc5d8977aa4720f", size = 74687 }, + { url = "https://files.pythonhosted.org/packages/b7/5e/a4c7154ba65d93be91f2f1e55f90e76c5f91ccadc7efc4341e6f04c8647f/msgpack-1.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3d364a55082fb2a7416f6c63ae383fbd903adb5a6cf78c5b96cc6316dc1cedc7", size = 150803 }, + { url = "https://files.pythonhosted.org/packages/60/c2/687684164698f1d51c41778c838d854965dd284a4b9d3a44beba9265c931/msgpack-1.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:79ec007767b9b56860e0372085f8504db5d06bd6a327a335449508bbee9648fa", size = 84343 }, + { url = "https://files.pythonhosted.org/packages/42/ae/d3adea9bb4a1342763556078b5765e666f8fdf242e00f3f6657380920972/msgpack-1.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6ad622bf7756d5a497d5b6836e7fc3752e2dd6f4c648e24b1803f6048596f701", size = 81408 }, + { url = "https://files.pythonhosted.org/packages/dc/17/6313325a6ff40ce9c3207293aee3ba50104aed6c2c1559d20d09e5c1ff54/msgpack-1.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e59bca908d9ca0de3dc8684f21ebf9a690fe47b6be93236eb40b99af28b6ea6", size = 396096 }, + { url = "https://files.pythonhosted.org/packages/a8/a1/ad7b84b91ab5a324e707f4c9761633e357820b011a01e34ce658c1dda7cc/msgpack-1.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e1da8f11a3dd397f0a32c76165cf0c4eb95b31013a94f6ecc0b280c05c91b59", size = 403671 }, + { url = "https://files.pythonhosted.org/packages/bb/0b/fd5b7c0b308bbf1831df0ca04ec76fe2f5bf6319833646b0a4bd5e9dc76d/msgpack-1.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:452aff037287acb1d70a804ffd022b21fa2bb7c46bee884dbc864cc9024128a0", size = 387414 }, + { url = "https://files.pythonhosted.org/packages/f0/03/ff8233b7c6e9929a1f5da3c7860eccd847e2523ca2de0d8ef4878d354cfa/msgpack-1.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8da4bf6d54ceed70e8861f833f83ce0814a2b72102e890cbdfe4b34764cdd66e", size = 383759 }, + { url = "https://files.pythonhosted.org/packages/1f/1b/eb82e1fed5a16dddd9bc75f0854b6e2fe86c0259c4353666d7fab37d39f4/msgpack-1.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:41c991beebf175faf352fb940bf2af9ad1fb77fd25f38d9142053914947cdbf6", size = 394405 }, + { url = "https://files.pythonhosted.org/packages/90/2e/962c6004e373d54ecf33d695fb1402f99b51832631e37c49273cc564ffc5/msgpack-1.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a52a1f3a5af7ba1c9ace055b659189f6c669cf3657095b50f9602af3a3ba0fe5", size = 396041 }, + { url = "https://files.pythonhosted.org/packages/f8/20/6e03342f629474414860c48aeffcc2f7f50ddaf351d95f20c3f1c67399a8/msgpack-1.1.0-cp311-cp311-win32.whl", hash = "sha256:58638690ebd0a06427c5fe1a227bb6b8b9fdc2bd07701bec13c2335c82131a88", size = 68538 }, + { url = "https://files.pythonhosted.org/packages/aa/c4/5a582fc9a87991a3e6f6800e9bb2f3c82972912235eb9539954f3e9997c7/msgpack-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:fd2906780f25c8ed5d7b323379f6138524ba793428db5d0e9d226d3fa6aa1788", size = 74871 }, + { url = "https://files.pythonhosted.org/packages/e1/d6/716b7ca1dbde63290d2973d22bbef1b5032ca634c3ff4384a958ec3f093a/msgpack-1.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:d46cf9e3705ea9485687aa4001a76e44748b609d260af21c4ceea7f2212a501d", size = 152421 }, + { url = "https://files.pythonhosted.org/packages/70/da/5312b067f6773429cec2f8f08b021c06af416bba340c912c2ec778539ed6/msgpack-1.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5dbad74103df937e1325cc4bfeaf57713be0b4f15e1c2da43ccdd836393e2ea2", size = 85277 }, + { url = "https://files.pythonhosted.org/packages/28/51/da7f3ae4462e8bb98af0d5bdf2707f1b8c65a0d4f496e46b6afb06cbc286/msgpack-1.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:58dfc47f8b102da61e8949708b3eafc3504509a5728f8b4ddef84bd9e16ad420", size = 82222 }, + { url = "https://files.pythonhosted.org/packages/33/af/dc95c4b2a49cff17ce47611ca9ba218198806cad7796c0b01d1e332c86bb/msgpack-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4676e5be1b472909b2ee6356ff425ebedf5142427842aa06b4dfd5117d1ca8a2", size = 392971 }, + { url = "https://files.pythonhosted.org/packages/f1/54/65af8de681fa8255402c80eda2a501ba467921d5a7a028c9c22a2c2eedb5/msgpack-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17fb65dd0bec285907f68b15734a993ad3fc94332b5bb21b0435846228de1f39", size = 401403 }, + { url = "https://files.pythonhosted.org/packages/97/8c/e333690777bd33919ab7024269dc3c41c76ef5137b211d776fbb404bfead/msgpack-1.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a51abd48c6d8ac89e0cfd4fe177c61481aca2d5e7ba42044fd218cfd8ea9899f", size = 385356 }, + { url = "https://files.pythonhosted.org/packages/57/52/406795ba478dc1c890559dd4e89280fa86506608a28ccf3a72fbf45df9f5/msgpack-1.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2137773500afa5494a61b1208619e3871f75f27b03bcfca7b3a7023284140247", size = 383028 }, + { url = "https://files.pythonhosted.org/packages/e7/69/053b6549bf90a3acadcd8232eae03e2fefc87f066a5b9fbb37e2e608859f/msgpack-1.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:398b713459fea610861c8a7b62a6fec1882759f308ae0795b5413ff6a160cf3c", size = 391100 }, + { url = "https://files.pythonhosted.org/packages/23/f0/d4101d4da054f04274995ddc4086c2715d9b93111eb9ed49686c0f7ccc8a/msgpack-1.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:06f5fd2f6bb2a7914922d935d3b8bb4a7fff3a9a91cfce6d06c13bc42bec975b", size = 394254 }, + { url = "https://files.pythonhosted.org/packages/1c/12/cf07458f35d0d775ff3a2dc5559fa2e1fcd06c46f1ef510e594ebefdca01/msgpack-1.1.0-cp312-cp312-win32.whl", hash = "sha256:ad33e8400e4ec17ba782f7b9cf868977d867ed784a1f5f2ab46e7ba53b6e1e1b", size = 69085 }, + { url = "https://files.pythonhosted.org/packages/73/80/2708a4641f7d553a63bc934a3eb7214806b5b39d200133ca7f7afb0a53e8/msgpack-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:115a7af8ee9e8cddc10f87636767857e7e3717b7a2e97379dc2054712693e90f", size = 75347 }, + { url = "https://files.pythonhosted.org/packages/c8/b0/380f5f639543a4ac413e969109978feb1f3c66e931068f91ab6ab0f8be00/msgpack-1.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:071603e2f0771c45ad9bc65719291c568d4edf120b44eb36324dcb02a13bfddf", size = 151142 }, + { url = "https://files.pythonhosted.org/packages/c8/ee/be57e9702400a6cb2606883d55b05784fada898dfc7fd12608ab1fdb054e/msgpack-1.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0f92a83b84e7c0749e3f12821949d79485971f087604178026085f60ce109330", size = 84523 }, + { url = "https://files.pythonhosted.org/packages/7e/3a/2919f63acca3c119565449681ad08a2f84b2171ddfcff1dba6959db2cceb/msgpack-1.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4a1964df7b81285d00a84da4e70cb1383f2e665e0f1f2a7027e683956d04b734", size = 81556 }, + { url = "https://files.pythonhosted.org/packages/7c/43/a11113d9e5c1498c145a8925768ea2d5fce7cbab15c99cda655aa09947ed/msgpack-1.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59caf6a4ed0d164055ccff8fe31eddc0ebc07cf7326a2aaa0dbf7a4001cd823e", size = 392105 }, + { url = "https://files.pythonhosted.org/packages/2d/7b/2c1d74ca6c94f70a1add74a8393a0138172207dc5de6fc6269483519d048/msgpack-1.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0907e1a7119b337971a689153665764adc34e89175f9a34793307d9def08e6ca", size = 399979 }, + { url = "https://files.pythonhosted.org/packages/82/8c/cf64ae518c7b8efc763ca1f1348a96f0e37150061e777a8ea5430b413a74/msgpack-1.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:65553c9b6da8166e819a6aa90ad15288599b340f91d18f60b2061f402b9a4915", size = 383816 }, + { url = "https://files.pythonhosted.org/packages/69/86/a847ef7a0f5ef3fa94ae20f52a4cacf596a4e4a010197fbcc27744eb9a83/msgpack-1.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7a946a8992941fea80ed4beae6bff74ffd7ee129a90b4dd5cf9c476a30e9708d", size = 380973 }, + { url = "https://files.pythonhosted.org/packages/aa/90/c74cf6e1126faa93185d3b830ee97246ecc4fe12cf9d2d31318ee4246994/msgpack-1.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4b51405e36e075193bc051315dbf29168d6141ae2500ba8cd80a522964e31434", size = 387435 }, + { url = "https://files.pythonhosted.org/packages/7a/40/631c238f1f338eb09f4acb0f34ab5862c4e9d7eda11c1b685471a4c5ea37/msgpack-1.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b4c01941fd2ff87c2a934ee6055bda4ed353a7846b8d4f341c428109e9fcde8c", size = 399082 }, + { url = "https://files.pythonhosted.org/packages/e9/1b/fa8a952be252a1555ed39f97c06778e3aeb9123aa4cccc0fd2acd0b4e315/msgpack-1.1.0-cp313-cp313-win32.whl", hash = "sha256:7c9a35ce2c2573bada929e0b7b3576de647b0defbd25f5139dcdaba0ae35a4cc", size = 69037 }, + { url = "https://files.pythonhosted.org/packages/b6/bc/8bd826dd03e022153bfa1766dcdec4976d6c818865ed54223d71f07862b3/msgpack-1.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:bce7d9e614a04d0883af0b3d4d501171fbfca038f12c77fa838d9f198147a23f", size = 75140 }, + { url = "https://files.pythonhosted.org/packages/f7/3b/544a5c5886042b80e1f4847a4757af3430f60d106d8d43bb7be72c9e9650/msgpack-1.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:53258eeb7a80fc46f62fd59c876957a2d0e15e6449a9e71842b6d24419d88ca1", size = 150713 }, + { url = "https://files.pythonhosted.org/packages/93/af/d63f25bcccd3d6f06fd518ba4a321f34a4370c67b579ca5c70b4a37721b4/msgpack-1.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7e7b853bbc44fb03fbdba34feb4bd414322180135e2cb5164f20ce1c9795ee48", size = 84277 }, + { url = "https://files.pythonhosted.org/packages/92/9b/5c0dfb0009b9f96328664fecb9f8e4e9c8a1ae919e6d53986c1b813cb493/msgpack-1.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3e9b4936df53b970513eac1758f3882c88658a220b58dcc1e39606dccaaf01c", size = 81357 }, + { url = "https://files.pythonhosted.org/packages/d1/7c/3a9ee6ec9fc3e47681ad39b4d344ee04ff20a776b594fba92d88d8b68356/msgpack-1.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46c34e99110762a76e3911fc923222472c9d681f1094096ac4102c18319e6468", size = 371256 }, + { url = "https://files.pythonhosted.org/packages/f7/0a/8a213cecea7b731c540f25212ba5f9a818f358237ac51a44d448bd753690/msgpack-1.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a706d1e74dd3dea05cb54580d9bd8b2880e9264856ce5068027eed09680aa74", size = 377868 }, + { url = "https://files.pythonhosted.org/packages/1b/94/a82b0db0981e9586ed5af77d6cfb343da05d7437dceaae3b35d346498110/msgpack-1.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:534480ee5690ab3cbed89d4c8971a5c631b69a8c0883ecfea96c19118510c846", size = 363370 }, + { url = "https://files.pythonhosted.org/packages/93/fc/6c7f0dcc1c913e14861e16eaf494c07fc1dde454ec726ff8cebcf348ae53/msgpack-1.1.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8cf9e8c3a2153934a23ac160cc4cba0ec035f6867c8013cc6077a79823370346", size = 358970 }, + { url = "https://files.pythonhosted.org/packages/1f/c6/e4a04c0089deace870dabcdef5c9f12798f958e2e81d5012501edaff342f/msgpack-1.1.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3180065ec2abbe13a4ad37688b61b99d7f9e012a535b930e0e683ad6bc30155b", size = 366358 }, + { url = "https://files.pythonhosted.org/packages/b6/54/7d8317dac590cf16b3e08e3fb74d2081e5af44eb396f0effa13f17777f30/msgpack-1.1.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c5a91481a3cc573ac8c0d9aace09345d989dc4a0202b7fcb312c88c26d4e71a8", size = 370336 }, + { url = "https://files.pythonhosted.org/packages/dc/6f/a5a1f43b6566831e9630e5bc5d86034a8884386297302be128402555dde1/msgpack-1.1.0-cp39-cp39-win32.whl", hash = "sha256:f80bc7d47f76089633763f952e67f8214cb7b3ee6bfa489b3cb6a84cfac114cd", size = 68683 }, + { url = "https://files.pythonhosted.org/packages/5f/e8/2162621e18dbc36e2bc8492fd0e97b3975f5d89fe0472ae6d5f7fbdd8cf7/msgpack-1.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:4d1b7ff2d6146e16e8bd665ac726a89c74163ef8cd39fa8c1087d4e52d3a2325", size = 74787 }, +] + +[[package]] +name = "mypy-extensions" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963 }, +] + +[[package]] +name = "namex" +version = "0.0.9" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ca/03/00afe7f32962d0778d757aed89cd7f970179e5f7fbe42e883fd494ebbbc7/namex-0.0.9.tar.gz", hash = "sha256:8adfea9da5cea5be8f4e632349b4669e30172c7859e1fd97459fdf3b17469253", size = 6569 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/46/16/7f616b55a147d9d4e9eb910a7eacde96cfa7ce3109d4c57ac32b91348ef3/namex-0.0.9-py3-none-any.whl", hash = "sha256:7bd4e4a2cc3876592111609fdf4cbe6ff19883adbe6b3b40d842fd340f77025e", size = 5847 }, +] + +[[package]] +name = "nest-asyncio" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/83/f8/51569ac65d696c8ecbee95938f89d4abf00f47d58d48f6fbabfe8f0baefe/nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe", size = 7418 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/c4/c2971a3ba4c6103a3d10c4b0f24f461ddc027f0f09763220cf35ca1401b3/nest_asyncio-1.6.0-py3-none-any.whl", hash = "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c", size = 5195 }, +] + +[[package]] +name = "networkx" +version = "3.2.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] +sdist = { url = "https://files.pythonhosted.org/packages/c4/80/a84676339aaae2f1cfdf9f418701dd634aef9cc76f708ef55c36ff39c3ca/networkx-3.2.1.tar.gz", hash = "sha256:9f1bb5cf3409bf324e0a722c20bdb4c20ee39bf1c30ce8ae499c8502b0b5e0c6", size = 2073928 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d5/f0/8fbc882ca80cf077f1b246c0e3c3465f7f415439bdea6b899f6b19f61f70/networkx-3.2.1-py3-none-any.whl", hash = "sha256:f18c69adc97877c42332c170849c96cefa91881c99a7cb3e95b7c659ebdc1ec2", size = 1647772 }, +] + +[[package]] +name = "networkx" +version = "3.4.2" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.12'", + "python_full_version == '3.11.*'", + "python_full_version == '3.10.*'", +] +sdist = { url = "https://files.pythonhosted.org/packages/fd/1d/06475e1cd5264c0b870ea2cc6fdb3e37177c1e565c43f56ff17a10e3937f/networkx-3.4.2.tar.gz", hash = "sha256:307c3669428c5362aab27c8a1260aa8f47c4e91d3891f48be0141738d8d053e1", size = 2151368 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b9/54/dd730b32ea14ea797530a4479b2ed46a6fb250f682a9cfb997e968bf0261/networkx-3.4.2-py3-none-any.whl", hash = "sha256:df5d4365b724cf81b8c6a7312509d0c22386097011ad1abe274afd5e9d3bbc5f", size = 1723263 }, +] + +[[package]] +name = "numpy" +version = "2.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a9/75/10dd1f8116a8b796cb2c737b674e02d02e80454bda953fa7e65d8c12b016/numpy-2.0.2.tar.gz", hash = "sha256:883c987dee1880e2a864ab0dc9892292582510604156762362d9326444636e78", size = 18902015 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/21/91/3495b3237510f79f5d81f2508f9f13fea78ebfdf07538fc7444badda173d/numpy-2.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:51129a29dbe56f9ca83438b706e2e69a39892b5eda6cedcb6b0c9fdc9b0d3ece", size = 21165245 }, + { url = "https://files.pythonhosted.org/packages/05/33/26178c7d437a87082d11019292dce6d3fe6f0e9026b7b2309cbf3e489b1d/numpy-2.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f15975dfec0cf2239224d80e32c3170b1d168335eaedee69da84fbe9f1f9cd04", size = 13738540 }, + { url = "https://files.pythonhosted.org/packages/ec/31/cc46e13bf07644efc7a4bf68df2df5fb2a1a88d0cd0da9ddc84dc0033e51/numpy-2.0.2-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:8c5713284ce4e282544c68d1c3b2c7161d38c256d2eefc93c1d683cf47683e66", size = 5300623 }, + { url = "https://files.pythonhosted.org/packages/6e/16/7bfcebf27bb4f9d7ec67332ffebee4d1bf085c84246552d52dbb548600e7/numpy-2.0.2-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:becfae3ddd30736fe1889a37f1f580e245ba79a5855bff5f2a29cb3ccc22dd7b", size = 6901774 }, + { url = "https://files.pythonhosted.org/packages/f9/a3/561c531c0e8bf082c5bef509d00d56f82e0ea7e1e3e3a7fc8fa78742a6e5/numpy-2.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2da5960c3cf0df7eafefd806d4e612c5e19358de82cb3c343631188991566ccd", size = 13907081 }, + { url = "https://files.pythonhosted.org/packages/fa/66/f7177ab331876200ac7563a580140643d1179c8b4b6a6b0fc9838de2a9b8/numpy-2.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:496f71341824ed9f3d2fd36cf3ac57ae2e0165c143b55c3a035ee219413f3318", size = 19523451 }, + { url = "https://files.pythonhosted.org/packages/25/7f/0b209498009ad6453e4efc2c65bcdf0ae08a182b2b7877d7ab38a92dc542/numpy-2.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a61ec659f68ae254e4d237816e33171497e978140353c0c2038d46e63282d0c8", size = 19927572 }, + { url = "https://files.pythonhosted.org/packages/3e/df/2619393b1e1b565cd2d4c4403bdd979621e2c4dea1f8532754b2598ed63b/numpy-2.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d731a1c6116ba289c1e9ee714b08a8ff882944d4ad631fd411106a30f083c326", size = 14400722 }, + { url = "https://files.pythonhosted.org/packages/22/ad/77e921b9f256d5da36424ffb711ae79ca3f451ff8489eeca544d0701d74a/numpy-2.0.2-cp310-cp310-win32.whl", hash = "sha256:984d96121c9f9616cd33fbd0618b7f08e0cfc9600a7ee1d6fd9b239186d19d97", size = 6472170 }, + { url = "https://files.pythonhosted.org/packages/10/05/3442317535028bc29cf0c0dd4c191a4481e8376e9f0db6bcf29703cadae6/numpy-2.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:c7b0be4ef08607dd04da4092faee0b86607f111d5ae68036f16cc787e250a131", size = 15905558 }, + { url = "https://files.pythonhosted.org/packages/8b/cf/034500fb83041aa0286e0fb16e7c76e5c8b67c0711bb6e9e9737a717d5fe/numpy-2.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:49ca4decb342d66018b01932139c0961a8f9ddc7589611158cb3c27cbcf76448", size = 21169137 }, + { url = "https://files.pythonhosted.org/packages/4a/d9/32de45561811a4b87fbdee23b5797394e3d1504b4a7cf40c10199848893e/numpy-2.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:11a76c372d1d37437857280aa142086476136a8c0f373b2e648ab2c8f18fb195", size = 13703552 }, + { url = "https://files.pythonhosted.org/packages/c1/ca/2f384720020c7b244d22508cb7ab23d95f179fcfff33c31a6eeba8d6c512/numpy-2.0.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:807ec44583fd708a21d4a11d94aedf2f4f3c3719035c76a2bbe1fe8e217bdc57", size = 5298957 }, + { url = "https://files.pythonhosted.org/packages/0e/78/a3e4f9fb6aa4e6fdca0c5428e8ba039408514388cf62d89651aade838269/numpy-2.0.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:8cafab480740e22f8d833acefed5cc87ce276f4ece12fdaa2e8903db2f82897a", size = 6905573 }, + { url = "https://files.pythonhosted.org/packages/a0/72/cfc3a1beb2caf4efc9d0b38a15fe34025230da27e1c08cc2eb9bfb1c7231/numpy-2.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a15f476a45e6e5a3a79d8a14e62161d27ad897381fecfa4a09ed5322f2085669", size = 13914330 }, + { url = "https://files.pythonhosted.org/packages/ba/a8/c17acf65a931ce551fee11b72e8de63bf7e8a6f0e21add4c937c83563538/numpy-2.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13e689d772146140a252c3a28501da66dfecd77490b498b168b501835041f951", size = 19534895 }, + { url = "https://files.pythonhosted.org/packages/ba/86/8767f3d54f6ae0165749f84648da9dcc8cd78ab65d415494962c86fac80f/numpy-2.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9ea91dfb7c3d1c56a0e55657c0afb38cf1eeae4544c208dc465c3c9f3a7c09f9", size = 19937253 }, + { url = "https://files.pythonhosted.org/packages/df/87/f76450e6e1c14e5bb1eae6836478b1028e096fd02e85c1c37674606ab752/numpy-2.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c1c9307701fec8f3f7a1e6711f9089c06e6284b3afbbcd259f7791282d660a15", size = 14414074 }, + { url = "https://files.pythonhosted.org/packages/5c/ca/0f0f328e1e59f73754f06e1adfb909de43726d4f24c6a3f8805f34f2b0fa/numpy-2.0.2-cp311-cp311-win32.whl", hash = "sha256:a392a68bd329eafac5817e5aefeb39038c48b671afd242710b451e76090e81f4", size = 6470640 }, + { url = "https://files.pythonhosted.org/packages/eb/57/3a3f14d3a759dcf9bf6e9eda905794726b758819df4663f217d658a58695/numpy-2.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:286cd40ce2b7d652a6f22efdfc6d1edf879440e53e76a75955bc0c826c7e64dc", size = 15910230 }, + { url = "https://files.pythonhosted.org/packages/45/40/2e117be60ec50d98fa08c2f8c48e09b3edea93cfcabd5a9ff6925d54b1c2/numpy-2.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:df55d490dea7934f330006d0f81e8551ba6010a5bf035a249ef61a94f21c500b", size = 20895803 }, + { url = "https://files.pythonhosted.org/packages/46/92/1b8b8dee833f53cef3e0a3f69b2374467789e0bb7399689582314df02651/numpy-2.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8df823f570d9adf0978347d1f926b2a867d5608f434a7cff7f7908c6570dcf5e", size = 13471835 }, + { url = "https://files.pythonhosted.org/packages/7f/19/e2793bde475f1edaea6945be141aef6c8b4c669b90c90a300a8954d08f0a/numpy-2.0.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:9a92ae5c14811e390f3767053ff54eaee3bf84576d99a2456391401323f4ec2c", size = 5038499 }, + { url = "https://files.pythonhosted.org/packages/e3/ff/ddf6dac2ff0dd50a7327bcdba45cb0264d0e96bb44d33324853f781a8f3c/numpy-2.0.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:a842d573724391493a97a62ebbb8e731f8a5dcc5d285dfc99141ca15a3302d0c", size = 6633497 }, + { url = "https://files.pythonhosted.org/packages/72/21/67f36eac8e2d2cd652a2e69595a54128297cdcb1ff3931cfc87838874bd4/numpy-2.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c05e238064fc0610c840d1cf6a13bf63d7e391717d247f1bf0318172e759e692", size = 13621158 }, + { url = "https://files.pythonhosted.org/packages/39/68/e9f1126d757653496dbc096cb429014347a36b228f5a991dae2c6b6cfd40/numpy-2.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0123ffdaa88fa4ab64835dcbde75dcdf89c453c922f18dced6e27c90d1d0ec5a", size = 19236173 }, + { url = "https://files.pythonhosted.org/packages/d1/e9/1f5333281e4ebf483ba1c888b1d61ba7e78d7e910fdd8e6499667041cc35/numpy-2.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:96a55f64139912d61de9137f11bf39a55ec8faec288c75a54f93dfd39f7eb40c", size = 19634174 }, + { url = "https://files.pythonhosted.org/packages/71/af/a469674070c8d8408384e3012e064299f7a2de540738a8e414dcfd639996/numpy-2.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ec9852fb39354b5a45a80bdab5ac02dd02b15f44b3804e9f00c556bf24b4bded", size = 14099701 }, + { url = "https://files.pythonhosted.org/packages/d0/3d/08ea9f239d0e0e939b6ca52ad403c84a2bce1bde301a8eb4888c1c1543f1/numpy-2.0.2-cp312-cp312-win32.whl", hash = "sha256:671bec6496f83202ed2d3c8fdc486a8fc86942f2e69ff0e986140339a63bcbe5", size = 6174313 }, + { url = "https://files.pythonhosted.org/packages/b2/b5/4ac39baebf1fdb2e72585c8352c56d063b6126be9fc95bd2bb5ef5770c20/numpy-2.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:cfd41e13fdc257aa5778496b8caa5e856dc4896d4ccf01841daee1d96465467a", size = 15606179 }, + { url = "https://files.pythonhosted.org/packages/43/c1/41c8f6df3162b0c6ffd4437d729115704bd43363de0090c7f913cfbc2d89/numpy-2.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9059e10581ce4093f735ed23f3b9d283b9d517ff46009ddd485f1747eb22653c", size = 21169942 }, + { url = "https://files.pythonhosted.org/packages/39/bc/fd298f308dcd232b56a4031fd6ddf11c43f9917fbc937e53762f7b5a3bb1/numpy-2.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:423e89b23490805d2a5a96fe40ec507407b8ee786d66f7328be214f9679df6dd", size = 13711512 }, + { url = "https://files.pythonhosted.org/packages/96/ff/06d1aa3eeb1c614eda245c1ba4fb88c483bee6520d361641331872ac4b82/numpy-2.0.2-cp39-cp39-macosx_14_0_arm64.whl", hash = "sha256:2b2955fa6f11907cf7a70dab0d0755159bca87755e831e47932367fc8f2f2d0b", size = 5306976 }, + { url = "https://files.pythonhosted.org/packages/2d/98/121996dcfb10a6087a05e54453e28e58694a7db62c5a5a29cee14c6e047b/numpy-2.0.2-cp39-cp39-macosx_14_0_x86_64.whl", hash = "sha256:97032a27bd9d8988b9a97a8c4d2c9f2c15a81f61e2f21404d7e8ef00cb5be729", size = 6906494 }, + { url = "https://files.pythonhosted.org/packages/15/31/9dffc70da6b9bbf7968f6551967fc21156207366272c2a40b4ed6008dc9b/numpy-2.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e795a8be3ddbac43274f18588329c72939870a16cae810c2b73461c40718ab1", size = 13912596 }, + { url = "https://files.pythonhosted.org/packages/b9/14/78635daab4b07c0930c919d451b8bf8c164774e6a3413aed04a6d95758ce/numpy-2.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f26b258c385842546006213344c50655ff1555a9338e2e5e02a0756dc3e803dd", size = 19526099 }, + { url = "https://files.pythonhosted.org/packages/26/4c/0eeca4614003077f68bfe7aac8b7496f04221865b3a5e7cb230c9d055afd/numpy-2.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5fec9451a7789926bcf7c2b8d187292c9f93ea30284802a0ab3f5be8ab36865d", size = 19932823 }, + { url = "https://files.pythonhosted.org/packages/f1/46/ea25b98b13dccaebddf1a803f8c748680d972e00507cd9bc6dcdb5aa2ac1/numpy-2.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:9189427407d88ff25ecf8f12469d4d39d35bee1db5d39fc5c168c6f088a6956d", size = 14404424 }, + { url = "https://files.pythonhosted.org/packages/c8/a6/177dd88d95ecf07e722d21008b1b40e681a929eb9e329684d449c36586b2/numpy-2.0.2-cp39-cp39-win32.whl", hash = "sha256:905d16e0c60200656500c95b6b8dca5d109e23cb24abc701d41c02d74c6b3afa", size = 6476809 }, + { url = "https://files.pythonhosted.org/packages/ea/2b/7fc9f4e7ae5b507c1a3a21f0f15ed03e794c1242ea8a242ac158beb56034/numpy-2.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:a3f4ab0caa7f053f6797fcd4e1e25caee367db3112ef2b6ef82d749530768c73", size = 15911314 }, + { url = "https://files.pythonhosted.org/packages/8f/3b/df5a870ac6a3be3a86856ce195ef42eec7ae50d2a202be1f5a4b3b340e14/numpy-2.0.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:7f0a0c6f12e07fa94133c8a67404322845220c06a9e80e85999afe727f7438b8", size = 21025288 }, + { url = "https://files.pythonhosted.org/packages/2c/97/51af92f18d6f6f2d9ad8b482a99fb74e142d71372da5d834b3a2747a446e/numpy-2.0.2-pp39-pypy39_pp73-macosx_14_0_x86_64.whl", hash = "sha256:312950fdd060354350ed123c0e25a71327d3711584beaef30cdaa93320c392d4", size = 6762793 }, + { url = "https://files.pythonhosted.org/packages/12/46/de1fbd0c1b5ccaa7f9a005b66761533e2f6a3e560096682683a223631fe9/numpy-2.0.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26df23238872200f63518dd2aa984cfca675d82469535dc7162dc2ee52d9dd5c", size = 19334885 }, + { url = "https://files.pythonhosted.org/packages/cc/dc/d330a6faefd92b446ec0f0dfea4c3207bb1fef3c4771d19cf4543efd2c78/numpy-2.0.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a46288ec55ebbd58947d31d72be2c63cbf839f0a63b49cb755022310792a3385", size = 15828784 }, +] + +[[package]] +name = "nvidia-cublas-cu12" +version = "12.6.4.1" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/af/eb/ff4b8c503fa1f1796679dce648854d58751982426e4e4b37d6fce49d259c/nvidia_cublas_cu12-12.6.4.1-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:08ed2686e9875d01b58e3cb379c6896df8e76c75e0d4a7f7dace3d7b6d9ef8eb", size = 393138322 }, +] + +[[package]] +name = "nvidia-cuda-cupti-cu12" +version = "12.6.80" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/49/60/7b6497946d74bcf1de852a21824d63baad12cd417db4195fc1bfe59db953/nvidia_cuda_cupti_cu12-12.6.80-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6768bad6cab4f19e8292125e5f1ac8aa7d1718704012a0e3272a6f61c4bce132", size = 8917980 }, + { url = "https://files.pythonhosted.org/packages/a5/24/120ee57b218d9952c379d1e026c4479c9ece9997a4fb46303611ee48f038/nvidia_cuda_cupti_cu12-12.6.80-py3-none-manylinux2014_x86_64.whl", hash = "sha256:a3eff6cdfcc6a4c35db968a06fcadb061cbc7d6dde548609a941ff8701b98b73", size = 8917972 }, +] + +[[package]] +name = "nvidia-cuda-nvrtc-cu12" +version = "12.6.77" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/75/2e/46030320b5a80661e88039f59060d1790298b4718944a65a7f2aeda3d9e9/nvidia_cuda_nvrtc_cu12-12.6.77-py3-none-manylinux2014_x86_64.whl", hash = "sha256:35b0cc6ee3a9636d5409133e79273ce1f3fd087abb0532d2d2e8fff1fe9efc53", size = 23650380 }, +] + +[[package]] +name = "nvidia-cuda-runtime-cu12" +version = "12.6.77" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e1/23/e717c5ac26d26cf39a27fbc076240fad2e3b817e5889d671b67f4f9f49c5/nvidia_cuda_runtime_cu12-12.6.77-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ba3b56a4f896141e25e19ab287cd71e52a6a0f4b29d0d31609f60e3b4d5219b7", size = 897690 }, + { url = "https://files.pythonhosted.org/packages/f0/62/65c05e161eeddbafeca24dc461f47de550d9fa8a7e04eb213e32b55cfd99/nvidia_cuda_runtime_cu12-12.6.77-py3-none-manylinux2014_x86_64.whl", hash = "sha256:a84d15d5e1da416dd4774cb42edf5e954a3e60cc945698dc1d5be02321c44dc8", size = 897678 }, +] + +[[package]] +name = "nvidia-cudnn-cu12" +version = "9.5.1.17" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "nvidia-cublas-cu12" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/78/4535c9c7f859a64781e43c969a3a7e84c54634e319a996d43ef32ce46f83/nvidia_cudnn_cu12-9.5.1.17-py3-none-manylinux_2_28_x86_64.whl", hash = "sha256:30ac3869f6db17d170e0e556dd6cc5eee02647abc31ca856634d5a40f82c15b2", size = 570988386 }, +] + +[[package]] +name = "nvidia-cufft-cu12" +version = "11.3.0.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "nvidia-nvjitlink-cu12" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/8f/16/73727675941ab8e6ffd86ca3a4b7b47065edcca7a997920b831f8147c99d/nvidia_cufft_cu12-11.3.0.4-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ccba62eb9cef5559abd5e0d54ceed2d9934030f51163df018532142a8ec533e5", size = 200221632 }, + { url = "https://files.pythonhosted.org/packages/60/de/99ec247a07ea40c969d904fc14f3a356b3e2a704121675b75c366b694ee1/nvidia_cufft_cu12-11.3.0.4-py3-none-manylinux2014_x86_64.whl", hash = "sha256:768160ac89f6f7b459bee747e8d175dbf53619cfe74b2a5636264163138013ca", size = 200221622 }, +] + +[[package]] +name = "nvidia-cufile-cu12" +version = "1.11.1.6" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b2/66/cc9876340ac68ae71b15c743ddb13f8b30d5244af344ec8322b449e35426/nvidia_cufile_cu12-1.11.1.6-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:cc23469d1c7e52ce6c1d55253273d32c565dd22068647f3aa59b3c6b005bf159", size = 1142103 }, +] + +[[package]] +name = "nvidia-curand-cu12" +version = "10.3.7.77" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/73/1b/44a01c4e70933637c93e6e1a8063d1e998b50213a6b65ac5a9169c47e98e/nvidia_curand_cu12-10.3.7.77-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a42cd1344297f70b9e39a1e4f467a4e1c10f1da54ff7a85c12197f6c652c8bdf", size = 56279010 }, + { url = "https://files.pythonhosted.org/packages/4a/aa/2c7ff0b5ee02eaef890c0ce7d4f74bc30901871c5e45dee1ae6d0083cd80/nvidia_curand_cu12-10.3.7.77-py3-none-manylinux2014_x86_64.whl", hash = "sha256:99f1a32f1ac2bd134897fc7a203f779303261268a65762a623bf30cc9fe79117", size = 56279000 }, +] + +[[package]] +name = "nvidia-cusolver-cu12" +version = "11.7.1.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "nvidia-cublas-cu12" }, + { name = "nvidia-cusparse-cu12" }, + { name = "nvidia-nvjitlink-cu12" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/f0/6e/c2cf12c9ff8b872e92b4a5740701e51ff17689c4d726fca91875b07f655d/nvidia_cusolver_cu12-11.7.1.2-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e9e49843a7707e42022babb9bcfa33c29857a93b88020c4e4434656a655b698c", size = 158229790 }, + { url = "https://files.pythonhosted.org/packages/9f/81/baba53585da791d043c10084cf9553e074548408e04ae884cfe9193bd484/nvidia_cusolver_cu12-11.7.1.2-py3-none-manylinux2014_x86_64.whl", hash = "sha256:6cf28f17f64107a0c4d7802be5ff5537b2130bfc112f25d5a30df227058ca0e6", size = 158229780 }, +] + +[[package]] +name = "nvidia-cusparse-cu12" +version = "12.5.4.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "nvidia-nvjitlink-cu12" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/06/1e/b8b7c2f4099a37b96af5c9bb158632ea9e5d9d27d7391d7eb8fc45236674/nvidia_cusparse_cu12-12.5.4.2-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7556d9eca156e18184b94947ade0fba5bb47d69cec46bf8660fd2c71a4b48b73", size = 216561367 }, + { url = "https://files.pythonhosted.org/packages/43/ac/64c4316ba163e8217a99680c7605f779accffc6a4bcd0c778c12948d3707/nvidia_cusparse_cu12-12.5.4.2-py3-none-manylinux2014_x86_64.whl", hash = "sha256:23749a6571191a215cb74d1cdbff4a86e7b19f1200c071b3fcf844a5bea23a2f", size = 216561357 }, +] + +[[package]] +name = "nvidia-cusparselt-cu12" +version = "0.6.3" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3b/9a/72ef35b399b0e183bc2e8f6f558036922d453c4d8237dab26c666a04244b/nvidia_cusparselt_cu12-0.6.3-py3-none-manylinux2014_x86_64.whl", hash = "sha256:e5c8a26c36445dd2e6812f1177978a24e2d37cacce7e090f297a688d1ec44f46", size = 156785796 }, +] + +[[package]] +name = "nvidia-nccl-cu12" +version = "2.26.2" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/67/ca/f42388aed0fddd64ade7493dbba36e1f534d4e6fdbdd355c6a90030ae028/nvidia_nccl_cu12-2.26.2-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:694cf3879a206553cc9d7dbda76b13efaf610fdb70a50cba303de1b0d1530ac6", size = 201319755 }, +] + +[[package]] +name = "nvidia-nvjitlink-cu12" +version = "12.6.85" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9d/d7/c5383e47c7e9bf1c99d5bd2a8c935af2b6d705ad831a7ec5c97db4d82f4f/nvidia_nvjitlink_cu12-12.6.85-py3-none-manylinux2010_x86_64.manylinux_2_12_x86_64.whl", hash = "sha256:eedc36df9e88b682efe4309aa16b5b4e78c2407eac59e8c10a6a47535164369a", size = 19744971 }, +] + +[[package]] +name = "nvidia-nvtx-cu12" +version = "12.6.77" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/56/9a/fff8376f8e3d084cd1530e1ef7b879bb7d6d265620c95c1b322725c694f4/nvidia_nvtx_cu12-12.6.77-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b90bed3df379fa79afbd21be8e04a0314336b8ae16768b58f2d34cb1d04cd7d2", size = 89276 }, + { url = "https://files.pythonhosted.org/packages/9e/4e/0d0c945463719429b7bd21dece907ad0bde437a2ff12b9b12fee94722ab0/nvidia_nvtx_cu12-12.6.77-py3-none-manylinux2014_x86_64.whl", hash = "sha256:6574241a3ec5fdc9334353ab8c479fe75841dbe8f4532a8fc97ce63503330ba1", size = 89265 }, +] + +[[package]] +name = "opt-einsum" +version = "3.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7d/bf/9257e53a0e7715bc1127e15063e831f076723c6cd60985333a1c18878fb8/opt_einsum-3.3.0.tar.gz", hash = "sha256:59f6475f77bbc37dcf7cd748519c0ec60722e91e63ca114e68821c0c54a46549", size = 73951 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bc/19/404708a7e54ad2798907210462fd950c3442ea51acc8790f3da48d2bee8b/opt_einsum-3.3.0-py3-none-any.whl", hash = "sha256:2455e59e3947d3c275477df7f5205b30635e266fe6dc300e3d9f9646bfcea147", size = 65486 }, +] + +[[package]] +name = "optax" +version = "0.2.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "absl-py" }, + { name = "chex" }, + { name = "etils", version = "1.5.2", source = { registry = "https://pypi.org/simple" }, extra = ["epy"], marker = "python_full_version < '3.10'" }, + { name = "etils", version = "1.12.2", source = { registry = "https://pypi.org/simple" }, extra = ["epy"], marker = "python_full_version >= '3.10'" }, + { name = "jax", version = "0.4.30", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "jax", version = "0.5.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "jaxlib", version = "0.4.30", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "jaxlib", version = "0.5.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "numpy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/af/b5/f88a0d851547b2e6b2c7e7e6509ad66236b3e7019f1f095bb03dbaa61fa1/optax-0.2.4.tar.gz", hash = "sha256:4e05d3d5307e6dde4c319187ae36e6cd3a0c035d4ed25e9e992449a304f47336", size = 229717 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5c/24/28d0bb21600a78e46754947333ec9a297044af884d360092eb8561575fe9/optax-0.2.4-py3-none-any.whl", hash = "sha256:db35c04e50b52596662efb002334de08c2a0a74971e4da33f467e84fac08886a", size = 319212 }, +] + +[[package]] +name = "optree" +version = "0.15.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4c/10/37411ac8cf8cb07b9db9ddc3e36f84869fd1cabcee3d6af8d347c28744f2/optree-0.15.0.tar.gz", hash = "sha256:d00a45e3b192093ef2cd32bf0d541ecbfc93c1bd73a5f3fe36293499f28a50cf", size = 171403 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/17/07/eaae03b46385dd8b9987433d63352a9d2ebf00df3bda785501665eac9b79/optree-0.15.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6e73e390520a545ebcaa0b77fd77943a85d1952df658268129e6c523d4d38972", size = 609468 }, + { url = "https://files.pythonhosted.org/packages/aa/d5/34605464c764853aa45c969c0673975897732ff0a975ad3f3ba461af2e3f/optree-0.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c45593a818c67b72fd0beaeaa6410fa3c5debd39af500127fa367f8ee1f4bd8e", size = 329906 }, + { url = "https://files.pythonhosted.org/packages/f9/27/3d42845627a39f130c65c1a84a60b769557942da04e5eebf843bb24c30f4/optree-0.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4e440de109529ce919d0a0a4fa234d3b949da6f99630c9406c9f21160800831", size = 360986 }, + { url = "https://files.pythonhosted.org/packages/60/1f/285429c597e5c56c42732716400e399a0c4a45d97f11420f8bc0840560c0/optree-0.15.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7614ad2f7bde7b905c897011be573d89a9cb5cf851784ee8efb0020d8e067b27", size = 406114 }, + { url = "https://files.pythonhosted.org/packages/14/6d/33fc164efc396622f0cd0a9c9de67c14c8161cadc10f73b2187d7e5d786d/optree-0.15.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:655ab99f9f9570fbb124f81fdf7e480250b59b1f1d9bd07df04c8751eecc1450", size = 403859 }, + { url = "https://files.pythonhosted.org/packages/d0/e0/5e69e4988f9d98deaeaec7141f1e5cbef3c18300ae32e0a4d0037a1ea366/optree-0.15.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e63b965b62f461513983095750fd1331cad5674153bf3811bd7e2748044df4cd", size = 374122 }, + { url = "https://files.pythonhosted.org/packages/4b/f5/8b4ea051730c461e8957652ae58a895e5cc740b162adfe12f15d144d7c76/optree-0.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14e515b011d965bd3f7aeb021bb523265cb49fde47be0033ba5601e386fff90a", size = 397070 }, + { url = "https://files.pythonhosted.org/packages/e2/2f/70e2bbe99e8dbc2004ac4fc314946e3ab00ccb28a71daea6a4d67a15d8c4/optree-0.15.0-cp310-cp310-win32.whl", hash = "sha256:27031f507828c18606047e695129e9ec9678cd4321f57856da59c7fcc8f8666c", size = 268873 }, + { url = "https://files.pythonhosted.org/packages/ee/15/2db908ee685ef73340224abdc8d312c8d31836d808af0ae12e6a85e1b9ca/optree-0.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:f0392bebcd24fc70ca9a397c1eb2373727fa775e1007f27f3983c50f16a98e45", size = 297297 }, + { url = "https://files.pythonhosted.org/packages/cc/14/443f9dd63d158b5d01ba0e834d3aaa224d081d3459793e21764ef73619f8/optree-0.15.0-cp310-cp310-win_arm64.whl", hash = "sha256:c3122f73eca03e38712ceee16a6acf75d5244ba8b8d1adf5cd6613d1a60a6c26", size = 296510 }, + { url = "https://files.pythonhosted.org/packages/e8/89/1267444a074b6e4402b5399b73b930a7b86cde054a41cecb9694be726a92/optree-0.15.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c15d98e6f587badb9df67d67fa914fcfa0b63db2db270951915c563816c29f3d", size = 629067 }, + { url = "https://files.pythonhosted.org/packages/98/a5/f8d6c278ce72b2ed8c1ebac968c3c652832bd2d9e65ec81fe6a21082c313/optree-0.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8d58949ef132beb3a025ace512a71a0fcf92e0e5ef350f289f33a782ae6cb85", size = 338192 }, + { url = "https://files.pythonhosted.org/packages/c8/88/3508c7ed217a37d35e2f30187dd2073c8130c09f80e47d3a0c9cadf42b14/optree-0.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f71d4759de0c4abc132dab69d1aa6ea4561ba748efabeee7b25db57c08652b79", size = 373749 }, + { url = "https://files.pythonhosted.org/packages/e1/05/f20f4ee6164e0e2b13e8cd588ba46f80fc0e8945a585d34f7250bcf7c31c/optree-0.15.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4ba65d4c48d76bd5caac7f0b1b8db55223c1c3707d26f6d1d2ff18baf6f81850", size = 421870 }, + { url = "https://files.pythonhosted.org/packages/1f/e8/fcaeb5de1e53349dc45867706cd2a79c45500868e1bc010904511c4d7d58/optree-0.15.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aad3878acdb082701e5f77a153cd86af8819659bfa7e27debd0dc1a52f16c365", size = 418929 }, + { url = "https://files.pythonhosted.org/packages/b8/16/11d0954c39c3526e2d4198628abba80cb2858c6963e52aebd89c38fac93a/optree-0.15.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6676b8c3f4cd4c8d8d052b66767a9e4cf852627bf256da6e49d2c38a95f07712", size = 386787 }, + { url = "https://files.pythonhosted.org/packages/aa/3d/52a75740d6c449073d4bb54da382f6368553f285fb5a680b27dd198dd839/optree-0.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1f185b0d21bc4dda1f4fd03f5ba9e2bc9d28ca14bce3ce3d36b5817140a345e", size = 410434 }, + { url = "https://files.pythonhosted.org/packages/ef/0f/fe199a99fbb3c3f33c1a98328d4bf9a1b42a72df3aa2de0c9046873075b7/optree-0.15.0-cp311-cp311-win32.whl", hash = "sha256:927b579a76c13b9328580c09dd4a9947646531f0a371a170a785002c50dedb94", size = 274360 }, + { url = "https://files.pythonhosted.org/packages/b0/86/9743be6eac8cc5ef69fa2b6585a36254aca0815714f57a0763bcfa774906/optree-0.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:d6525d6a550a1030957e5205e57a415d608a9f7561154e0fb29670e967424578", size = 306609 }, + { url = "https://files.pythonhosted.org/packages/87/41/4b4130f921c886ec83ba53809da83bce13039653be37c56ea6b9b7c4bd2b/optree-0.15.0-cp311-cp311-win_arm64.whl", hash = "sha256:081e8bed7583b625819659d68288365bd4348b3c4281935a6ecfa53c93619b13", size = 304507 }, + { url = "https://files.pythonhosted.org/packages/32/a5/2589d9790a6dd7c4b1dd22bd228238c575ec5384ce5bc16a30e7f43cdd99/optree-0.15.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ba2eee9de9d57e145b4c1a71749f7f8b8fe1c645abbb306d4a26cfa45a9cdbb5", size = 639476 }, + { url = "https://files.pythonhosted.org/packages/a5/2c/5363abf03c8d47ad7bc3b45a735cbdf24a10f99f82e776ef2949ffce77c6/optree-0.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4aad5023686cd7caad68d70ad3706b82cfe9ae8ff9a13c08c1edef2a9b4c9d72", size = 342569 }, + { url = "https://files.pythonhosted.org/packages/0c/e2/d2ee348f26cbfba68d51f971112db1e4560f60db95598c88ce63d4c99204/optree-0.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9810e84466025da55ce19ac6b2b79a5cb2c0c1349d318a17504f6e44528221f8", size = 369181 }, + { url = "https://files.pythonhosted.org/packages/ec/f8/dafdc4bc40d699b0a8b3ae9cdd5c33984a9cbf1f964151f9608e24e409d9/optree-0.15.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:20b07d8a097b810d68b0ee35f287c1f0b7c9844133ada613a92cc10bade9cdbe", size = 416191 }, + { url = "https://files.pythonhosted.org/packages/81/aa/c2027d6314fa62787639ff2bba42884fd80a65f53b4a3bdc4fd87700649d/optree-0.15.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0304ec416258edebe2cd2a1ef71770e43405d5e7366ecbc134c520b4ab44d155", size = 413041 }, + { url = "https://files.pythonhosted.org/packages/ac/17/01050e00e74291925796309b38dfbbffc03e2893dc929dd9e48d361456ee/optree-0.15.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:759a72e6dcca3e7239d202a253e1e8e44e8df5033a5e178df585778ac85ddd13", size = 381367 }, + { url = "https://files.pythonhosted.org/packages/86/f0/a00cf9f2cf1e8d54f71116ad5eea73fc5b1177644283704535bb8e43090e/optree-0.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01a0dc75c594c884d0ca502b8d169cec538e19a70883d2e5f5b9b08fce740958", size = 404769 }, + { url = "https://files.pythonhosted.org/packages/60/e6/abc48777d38c0ab429b84c91fabfa76c64991bc98ef10538d6fc6d8e88f4/optree-0.15.0-cp312-cp312-win32.whl", hash = "sha256:7e10e5c2a8110f5f4fbc999ff8580d1db3a915f851f63f602fff3bbd250ffa20", size = 275492 }, + { url = "https://files.pythonhosted.org/packages/25/33/cd41ab38ef313874eb2000f1037ccce001dd680873713cc2d1a2ae5d0041/optree-0.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:def5b08f219c31edd029b47624e689ffa07747b0694222156f28a28d341d29ac", size = 307368 }, + { url = "https://files.pythonhosted.org/packages/df/04/9ed5f07d78b303c4bcadcf3ec763358ea64472d1a005dc1249278df66600/optree-0.15.0-cp312-cp312-win_arm64.whl", hash = "sha256:8ec6d3040b1cbfe3f0bc045a3302ee9f9e329c2cd96e928360d22e1cfd9d973a", size = 300733 }, + { url = "https://files.pythonhosted.org/packages/70/e3/99135565340ac34857b6edbb3df6e15eb35aa7160f900f12d83f71d38eeb/optree-0.15.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:4ab606720ae319cb43da47c71d7d5fa7cfbb6a02e6da4857331e6f93800c970e", size = 647666 }, + { url = "https://files.pythonhosted.org/packages/93/fc/c9c04494d2ab54f98f8d8c18cb5095a81ad23fb64105cb05e926bb3d1a0c/optree-0.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9cfc5771115f85b0bfa8f72cce1599186fd6a0ea71c8154d8b2751d9170be428", size = 346205 }, + { url = "https://files.pythonhosted.org/packages/b8/c8/25484ec6784435d63e64e87a7dca32760eed4ca60ddd4be1ca14ed421e08/optree-0.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f958a20a311854aaab8bdd0f124aab5b9848f07976b54da3e95526a491aa860", size = 372427 }, + { url = "https://files.pythonhosted.org/packages/a3/27/615a2987137fd8add27e62217527e49f7fd2ec391bbec354dbc59a0cd0af/optree-0.15.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:47ce7e9d81eaed5a05004df1fa279d2608e063dd5eb236e9c95803b4fa0a286c", size = 421611 }, + { url = "https://files.pythonhosted.org/packages/98/e7/0106ee7ebec2e4cfa09f0a3b857e03c80bc80521227f4d64c289ac9601e8/optree-0.15.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c6d6ab3717d48e0e747d9e348e23be1fa0f8a812f73632face6303c438d259ba", size = 415804 }, + { url = "https://files.pythonhosted.org/packages/47/0e/a40ccedb0bac4a894b2b0d17d915b7e8cd3fdc44a5104026cec4102a53fb/optree-0.15.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c7d101a15be39a9c7c4afae9f0bb85f682eb7d719117e2f9e5fb39c9f6f2c92", size = 386208 }, + { url = "https://files.pythonhosted.org/packages/c0/f6/1d98163b283048d80cb0c8e67d086a1e0ecabe35004d7180d0f28303f611/optree-0.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aae337ab30b45a096eb5b4ffc3ad8909731617543a7eb288e0b297b9d10a241f", size = 409276 }, + { url = "https://files.pythonhosted.org/packages/e4/65/4275cd763bafb22c41443b7c7bfd5986b9c97f984537669c356e2c7008a1/optree-0.15.0-cp313-cp313-win32.whl", hash = "sha256:eb9c51d728485f5908111191b5403a3f9bc310d121a981f29fad45750b9ff89c", size = 277924 }, + { url = "https://files.pythonhosted.org/packages/b2/fe/3d9f5463609ac6cb5857d0040739ae7709e1fbc134c58f0dd7cb3d2d93d5/optree-0.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:7f00e6f011f021ae470efe070ec4d2339fb1a8cd0dcdd16fe3dab782a47aba45", size = 309617 }, + { url = "https://files.pythonhosted.org/packages/7d/bb/b7a443be665a91307cd78196018bc45bb0c6ab04fe265f009698311c7bc7/optree-0.15.0-cp313-cp313-win_arm64.whl", hash = "sha256:17990fbc7f4c461de7ae546fc5661f6a248c3dcee966c89c2e2e5ad7f6228bae", size = 303390 }, + { url = "https://files.pythonhosted.org/packages/30/8d/c6977786cc40626f24068d9bd6acbff377b9bed0cd64b7faff1bc3f2d60c/optree-0.15.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b31c88af70e3f5c14ff2aacd38c4076e6cde98f75169fe0bb59543f01bfb9719", size = 747468 }, + { url = "https://files.pythonhosted.org/packages/5c/3f/e5b50c7af3712a97d0341744cd8ebd8ab19cd38561e26caa7a8a10fdf702/optree-0.15.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:bc440f81f738d9c822030c3b4f53b6dec9ceb52410f02fd06b9338dc25a8447f", size = 392638 }, + { url = "https://files.pythonhosted.org/packages/54/3b/1aab1a9dba5c8eb85810ba2683b42b057b1ce1de9bb7ca08c5d35448979e/optree-0.15.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76ffc2dd8c754e95495163dde55b38dc37e6712b6a3bc7f2190b0547a2c403bb", size = 390030 }, + { url = "https://files.pythonhosted.org/packages/fc/95/195be32055ce48cdf8beb31eda74f4643c6a443f1367346c6a8f6606c9eb/optree-0.15.0-cp313-cp313t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9fa9fb0197cd7b5f2b1fa7e05d30946b3b79bcfc3608fe54dbfc67969895cac9", size = 437350 }, + { url = "https://files.pythonhosted.org/packages/02/01/9eefcdd9112aebc52db668a87f1df2f45c784e34e5a35182d3dad731fc92/optree-0.15.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6828639b01ba1177c04875dd9529d938d7b28122c97e7ae14ec41c68ec22826c", size = 434500 }, + { url = "https://files.pythonhosted.org/packages/6d/b3/0749c3a752b4921d54aa88eb1246315a008b5199c6d0e6127bd672a21c87/optree-0.15.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:93c74eed0f52818c30212dba4867f5672e498567bad49dcdffbe8db6703a0d65", size = 404306 }, + { url = "https://files.pythonhosted.org/packages/04/91/1538085ace361f99280a26f9ccdc6023b22e7d0e23fdb849e2ef104fb54f/optree-0.15.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:12188f6832c29dac37385a2f42fce961e303349909cff6d40e21cb27a8d09023", size = 423468 }, + { url = "https://files.pythonhosted.org/packages/c8/ec/c4d2203a6f1206790ea8b794df943a16918649b23cd03ec6beb7f75a81df/optree-0.15.0-cp313-cp313t-win32.whl", hash = "sha256:d7b8ce7d13580985922dcfbda515da3f004cd7cb1b03320b96ea32d8cfd76392", size = 308837 }, + { url = "https://files.pythonhosted.org/packages/66/db/567ea8d2874eb15e9a8a82598ab84a6b809ca16df083b7650deffb8a6171/optree-0.15.0-cp313-cp313t-win_amd64.whl", hash = "sha256:daccdb583abaab14346f0af316ee570152a5c058e7b9fb09d8f8171fe751f2b3", size = 344774 }, + { url = "https://files.pythonhosted.org/packages/ae/67/26804ab0222febadab6e27af4f4e607fad2d9520bb32422842509b79cf63/optree-0.15.0-cp313-cp313t-win_arm64.whl", hash = "sha256:e0162a36a6cedb0829efe980d0b370d4e5970fdb28a6609daa2c906d547add5f", size = 337502 }, + { url = "https://files.pythonhosted.org/packages/b1/0f/41522727f593b9f098cf8ed53955fe22c62433492ca19775e822c61e032e/optree-0.15.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0f9ea3208a14d1677c8966ea1eabe5b8f148424a8c3214ed4d4769beecd48a8a", size = 609481 }, + { url = "https://files.pythonhosted.org/packages/83/fd/607f6675b9a3b97d0a2ee1d988592373af64b9eeea00838baa1f7121097f/optree-0.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ebd608b02cb207e4851983b78f57e800c542758f131abe3b23cd4a5f0153676c", size = 329946 }, + { url = "https://files.pythonhosted.org/packages/31/bd/fa0a394f4b052a72abd3f569208f0086720abc438f027d4dba6fe932bda2/optree-0.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09d11111194a6211e9d806828d29d932ad5f998ea156c76ad0e4d5da39654541", size = 362467 }, + { url = "https://files.pythonhosted.org/packages/2f/1e/f435b9678f8421282d449c6494072b168f435a2cde62acafa48f7f67462b/optree-0.15.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44cb5d1e5317dbb3044ad4b76af2d4f5e51de73d6ff6e858077d8af00756fe16", size = 406337 }, + { url = "https://files.pythonhosted.org/packages/44/74/6a64a75ce8798082be6206b430348577ed2e2cb7334e94d2ce50af36bb35/optree-0.15.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1493f3e97f921b8742368406d3de390f051a7c405959e2088d72b4a4ff3f5394", size = 405884 }, + { url = "https://files.pythonhosted.org/packages/84/a6/11c870f25775ad0bfb8edbdef1823031cfa4a622b76797e5342265a5739d/optree-0.15.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fef87f006da3c4dfc914f6c0f863c7f4712e958f56c991c320b06026e9ccfd87", size = 375161 }, + { url = "https://files.pythonhosted.org/packages/b9/05/391fbe3715d48391a456fa0a4eb53ccf9d157740fcd0e28e6592cc6e8f9d/optree-0.15.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad409276099b89fb5077b0b9311c9e8500086888eba9c77546353c18d520bfe5", size = 397173 }, + { url = "https://files.pythonhosted.org/packages/f8/b4/a249f849b26753e37067a040f1fb4f8976881e514a50f3ab21b82df1d144/optree-0.15.0-cp39-cp39-win32.whl", hash = "sha256:a6103a3d33cc300ea567f373680e29a29ae854e8775bf87231aae12664b4732e", size = 268867 }, + { url = "https://files.pythonhosted.org/packages/9a/b9/ef20091177026b28782e3ed26efe48b594a937788eb4813b2f6b0c43d1dd/optree-0.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:a68a813a2141493566178ae87e1906856f1549e2c3e439ff76801f8fb05bd3a7", size = 292349 }, + { url = "https://files.pythonhosted.org/packages/47/96/c675d6b6b40c2fb0d3f8266da3abd87b73585dafac6f2e024c83575ce79d/optree-0.15.0-cp39-cp39-win_arm64.whl", hash = "sha256:59d8d252cb83465ecac2f7ff457489606a56316fe8b8f7635770ee8e27b6a3b8", size = 292943 }, + { url = "https://files.pythonhosted.org/packages/69/2c/dddb2166b43bbbb7a83d17a0585ec6df2f5312cec9a81816ad26f9b779f8/optree-0.15.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b30673fe30d4d77eef18534420491c27837f0b55dfe18107cfd9eca39a62de3b", size = 336150 }, + { url = "https://files.pythonhosted.org/packages/92/72/f5b995baf6d38bc6211ef806e94fc1dff4acc49de809fdf7e139603d78f5/optree-0.15.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0f378d08b8a09f7e495c49cd94141c1acebc2aa7d567d7dd2cb44a707f29268", size = 364766 }, + { url = "https://files.pythonhosted.org/packages/2b/e4/9d6142910afa81a8ad3bcf67d42953c843ae1f5118c522bfc564bfa89ffa/optree-0.15.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90dae741d683cbc47cba16a1b4af3c0d5d8c1042efb7c4aec7664a4f3f07eca2", size = 400303 }, + { url = "https://files.pythonhosted.org/packages/7f/64/4791bfd4bef08f159d285c1f3fc8d8cc5dc9bdb6c50290d4c382fee7605c/optree-0.15.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:cf790dd21dcaa0857888c03233276f5513821abfe605964e825837a30a24f0d7", size = 299596 }, + { url = "https://files.pythonhosted.org/packages/e7/df/b490f1bdd65b0d798ac9b46c145cefaf7724c6e8b90fb0371cd3f7fb4c60/optree-0.15.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:21afadec56475f2a13670b8ecf7b767af4feb3ba5bd3a246cbbd8c1822e2a664", size = 346694 }, + { url = "https://files.pythonhosted.org/packages/cd/6c/4ea0616ef4e3a3fff5490ebdc8083fa8f3a3a3105ab93222e4fd97fc4f2a/optree-0.15.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a39bccc63223e040f36eb8b413fa1f94a190289eb82e7b384ed32d95d1ffd67", size = 377442 }, + { url = "https://files.pythonhosted.org/packages/99/5d/8cf3c44adf9e20ea267bd218ee829e715c1987b877b7bce74b37986997e4/optree-0.15.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06aed485ab9c94f5b45a18f956bcb89bf6bad29632421da69da268cb49adb37b", size = 413200 }, + { url = "https://files.pythonhosted.org/packages/6f/3c/1cc96fb1faaae6f5e0d34556a68aac18be5b0d8ac675b7dd236e4c82c6b2/optree-0.15.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:07e9d75867ca39cce98375249b83a2033b0313cbfa32cbd06f93f7bc15104afc", size = 308873 }, + { url = "https://files.pythonhosted.org/packages/78/22/a6f616f0d5fc23ec018d29eca217e512c99eb2774a7530007370f66c68e3/optree-0.15.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:3d237605b277d5600748c8a6f83f65e00c294b000ac8772f473fa41eb587ca15", size = 335977 }, + { url = "https://files.pythonhosted.org/packages/23/40/61e4eaed61737e39b45f887a5f13854e30ef501d6d8edd3b2fcd70c5f4e2/optree-0.15.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c82f0e88f43b5ec57b8e225175003dc6624dfa400fb56c18c0e4b4667bef805", size = 364518 }, + { url = "https://files.pythonhosted.org/packages/5b/fb/d6cbc4a7f12d585af408cc8e0a2f552d42c35da4ed0ffe16df7fa758ca2a/optree-0.15.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2245f9a9fd5c7f042f07a476695fd4f6074f85036b5ff3d004f4da121220bf56", size = 400234 }, + { url = "https://files.pythonhosted.org/packages/df/48/0da114b9deb808160a9c012f4f500bd105d74b54acfd1903b9f59c2ef3cd/optree-0.15.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:29e1fa90153908d968a2fcebf62bbbc0b434b5a75463a202c33ba3e13dc170ea", size = 299339 }, +] + +[[package]] +name = "orbax-checkpoint" +version = "0.6.4" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] +dependencies = [ + { name = "absl-py", marker = "python_full_version < '3.10'" }, + { name = "etils", version = "1.5.2", source = { registry = "https://pypi.org/simple" }, extra = ["epath", "epy"], marker = "python_full_version < '3.10'" }, + { name = "humanize", marker = "python_full_version < '3.10'" }, + { name = "jax", version = "0.4.30", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "jaxlib", version = "0.4.30", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "msgpack", marker = "python_full_version < '3.10'" }, + { name = "nest-asyncio", marker = "python_full_version < '3.10'" }, + { name = "numpy", marker = "python_full_version < '3.10'" }, + { name = "protobuf", marker = "python_full_version < '3.10'" }, + { name = "pyyaml", marker = "python_full_version < '3.10'" }, + { name = "tensorstore", version = "0.1.69", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "typing-extensions", marker = "python_full_version < '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/32/9f/6ca67c33b6a53d2484ebeb3c132a06331fbf085ce1619e3f919d36bb6a9c/orbax_checkpoint-0.6.4.tar.gz", hash = "sha256:366b4d528a7322e1b3d9ddcaed45c8515add0d2fc69c8975c30d98638543240f", size = 194820 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8d/79/0a84020557a5c5bd987f74892e58e71cf74886dc9b264ad7630a1f288543/orbax_checkpoint-0.6.4-py3-none-any.whl", hash = "sha256:b4f2608ee4d1da67f7619fc35ff9c928ecdf4ccf7546eeb43ecf38c2608b6dea", size = 270502 }, +] + +[[package]] +name = "orbax-checkpoint" +version = "0.11.13" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.12'", + "python_full_version == '3.11.*'", + "python_full_version == '3.10.*'", +] +dependencies = [ + { name = "absl-py", marker = "python_full_version >= '3.10'" }, + { name = "etils", version = "1.12.2", source = { registry = "https://pypi.org/simple" }, extra = ["epath", "epy"], marker = "python_full_version >= '3.10'" }, + { name = "humanize", marker = "python_full_version >= '3.10'" }, + { name = "jax", version = "0.5.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "msgpack", marker = "python_full_version >= '3.10'" }, + { name = "nest-asyncio", marker = "python_full_version >= '3.10'" }, + { name = "numpy", marker = "python_full_version >= '3.10'" }, + { name = "protobuf", marker = "python_full_version >= '3.10'" }, + { name = "pyyaml", marker = "python_full_version >= '3.10'" }, + { name = "simplejson", marker = "python_full_version >= '3.10'" }, + { name = "tensorstore", version = "0.1.74", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "typing-extensions", marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c3/cb/e122160888cb922caabfd67582d402e6202fc7383c64f2e05a81727cef6a/orbax_checkpoint-0.11.13.tar.gz", hash = "sha256:6ce6f4458d0755a7ae556d4da3b2e3a943d4a830aeec2f98881643f1997e11bc", size = 316151 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/27/57/700709ca012b8595230dd2a004fbe284a57e6838f966d58c956d4529a2db/orbax_checkpoint-0.11.13-py3-none-any.whl", hash = "sha256:096eb6f475857d7aa73235989cdfe5d34c425628d24be881686dfbc3b566f495", size = 442700 }, +] + +[[package]] +name = "packaging" +version = "25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469 }, +] + +[[package]] +name = "paddlepaddle" +version = "3.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "astor" }, + { name = "decorator" }, + { name = "httpx" }, + { name = "networkx", version = "3.2.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "networkx", version = "3.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "numpy" }, + { name = "opt-einsum" }, + { name = "pillow" }, + { name = "protobuf" }, + { name = "typing-extensions" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/cf/60/1a3dc2f48dc5eb82d1258e0a0d18b9e9db0ace73f077c2984c626191af2c/paddlepaddle-3.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:69321d2fed61f9c4b502843d213af0919e058f8399c3fb7da4b90ff9f9e8544d", size = 94754509 }, + { url = "https://files.pythonhosted.org/packages/eb/c2/21c77d75f47398f8eb847aa85e456b19a1cca9cebb03e9c3cedce1888944/paddlepaddle-3.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7a8a3de6238d7588224353d7412d1869772fa88d0cc0119cb7c921bee9b1869c", size = 96916011 }, + { url = "https://files.pythonhosted.org/packages/ab/07/24565a312b58fb8e78c8c4214db0cfaee44f6dec161c00756026991633d8/paddlepaddle-3.0.0-cp310-cp310-manylinux1_x86_64.whl", hash = "sha256:73b1349d91a85dae81e23aee0faf1d04f244e26c688c23e387a504437066829a", size = 192817880 }, + { url = "https://files.pythonhosted.org/packages/10/e6/0e56a48490f0fc7e6f9b671adccb0ae972f73093e2257a3a0bb278174b3c/paddlepaddle-3.0.0-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:ea8841cdbea7f26dbe548d3b129dd9764f36a4338656c9b5257cac43b382a674", size = 92043392 }, + { url = "https://files.pythonhosted.org/packages/df/1f/2bd1e792fc3ce1aae11625afe238868b291370048d32939985b09274a9d1/paddlepaddle-3.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:9fe8544bce8d034da5cdab1417782c7d53e1bef97533bcef5710dfdb59e87ca5", size = 97035297 }, + { url = "https://files.pythonhosted.org/packages/d6/ff/5fe8b6852d02e52c20e5b8f1dce672d38a60c22ecdde4f726f3e1625c7c6/paddlepaddle-3.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f69b4ec5ec881e632bf80d8d2a0ca74f87925335dc57b14bb8971e72e2d87951", size = 94763205 }, + { url = "https://files.pythonhosted.org/packages/46/24/4e07f557384d3aee30ad924a7e06273b1226876576fd4db5b10193a71427/paddlepaddle-3.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:cb4a98192079cde5b5dac1109d334c12b376b97edc8682490b5f5065c8f708d9", size = 96920695 }, + { url = "https://files.pythonhosted.org/packages/8b/ff/a8685638b8ddd1af3a43f25a2b8f05263a1bec808db990177c38c6228738/paddlepaddle-3.0.0-cp311-cp311-manylinux1_x86_64.whl", hash = "sha256:cfd73da79e2eb9325bac4a3a1a7995063c7662dde724bf452659dda88e55b76f", size = 192824195 }, + { url = "https://files.pythonhosted.org/packages/7f/1d/7229c5eb164b390ebef4c55c42980781d88c38d59cb8922474e24204a5fe/paddlepaddle-3.0.0-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:3ef99688f4d5113dcf0e026a0b225efa77975da04e8ca1d0666ebdb729d4a409", size = 92048781 }, + { url = "https://files.pythonhosted.org/packages/0a/3d/5e0e1440e3ccf1becfd6bd07ec3432e9e9fe797585038c95f00a9da0962a/paddlepaddle-3.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:215daf5c154855e9f4139844076853cabc86425fd127c390405895ae2b820d85", size = 97036460 }, + { url = "https://files.pythonhosted.org/packages/e2/5e/07c10c1a98fde7c7dcb299dc62c6c06b2951073734a9daa93851ba29711f/paddlepaddle-3.0.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:dcfebfb10deb15aa33d2a2d66d5a12d9de65461d8a40d2687e2fb3221150d0ba", size = 94826038 }, + { url = "https://files.pythonhosted.org/packages/ea/83/f3435988cc4cce3764942188ec5c5f92e858012a335642e6740fcb0c3061/paddlepaddle-3.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8677e8d42ff66f74fbca32ff32d8b64bbe3d56ed29a92d43dc418f0f168fcb69", size = 96946375 }, + { url = "https://files.pythonhosted.org/packages/01/1d/5dfdda57de184d8406d6757f764a1ecdf26923d78ec7c427cb55b085c4d4/paddlepaddle-3.0.0-cp312-cp312-manylinux1_x86_64.whl", hash = "sha256:81a7c5b10150b07521d1cd1491dca1fb76ff621b14db10e899d959f3a77935ea", size = 192856178 }, + { url = "https://files.pythonhosted.org/packages/e9/df/4254095dff1e3f87cd8a2be000e39bd1e65118ba3841466b2aeecb480c63/paddlepaddle-3.0.0-cp312-cp312-manylinux2014_aarch64.whl", hash = "sha256:ddaa996a8b0a00dbe4269da21d65052877ec3693a22ecc07b9cada3ecd116886", size = 92026407 }, + { url = "https://files.pythonhosted.org/packages/bd/ca/850a357ea6803eeeef3ec0703f15fbbe30a6dfb0c01671bfe0527cab8662/paddlepaddle-3.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:68efccd9b64233243e48d89a20d34904e2827abc3458c7dddb9e97ef8e2209f6", size = 97056269 }, + { url = "https://files.pythonhosted.org/packages/c0/21/706cf5aa1ed7e3da092ee64fe1475a0dd7cc6ed0a907de0e87f5b55e39ce/paddlepaddle-3.0.0-cp313-cp313-macosx_10_9_x86_64.whl", hash = "sha256:52c401ffe4aae56316660a33015a6fd755cda23d3d70a28b13b73d70cbdbb8cb", size = 94826114 }, + { url = "https://files.pythonhosted.org/packages/ce/02/f6a04543770dbc2edf6368789bf025e61bf934e3b20986072882801b2e85/paddlepaddle-3.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9d1051f2e208da1d439daee7c861bcb50240f09712496eb61e9ce8c618faf2f9", size = 96946877 }, + { url = "https://files.pythonhosted.org/packages/2c/7a/59d9b82f500ab72e16382503cd0d42393c8d35d2a86622926d1c2b508804/paddlepaddle-3.0.0-cp313-cp313-manylinux1_x86_64.whl", hash = "sha256:8fc4865efd3656ee99424124792cb88a642151b4d591a7d6d4a5c6afdae95959", size = 192848478 }, + { url = "https://files.pythonhosted.org/packages/5b/4a/a80b735e62c1dac0310f0dcdca51a29523cf863834f291866bd8991f270d/paddlepaddle-3.0.0-cp313-cp313-manylinux2014_aarch64.whl", hash = "sha256:bbc4d573b35d24a262e02d72696e80f5b4aee41f698671af9574deeb1a83e6f7", size = 92027573 }, + { url = "https://files.pythonhosted.org/packages/87/56/45594a67d2603fc3b3b334017de7ef94eca6cbd21b8f53700e51e61a490e/paddlepaddle-3.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:2e1292d50f80a8577407008f7321f85c8309938c0c575927950aec3c45502c2a", size = 97053969 }, + { url = "https://files.pythonhosted.org/packages/c7/c9/a3623236de7e0f0ff4d2c9b8f53d99b0591f9425fb97149720c3d9391ffa/paddlepaddle-3.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:394a942b7281a8eb87083f80a9592f31b8aec1a360464e536c1d955d3e6e0bb4", size = 94753724 }, + { url = "https://files.pythonhosted.org/packages/a4/ad/cd5c1b474dab6a0c7e35e98a58c37e8d9a84b1a9ea2b33189e8d734dee83/paddlepaddle-3.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:00bd606cdce5dbae2b9752afdc07479c5fab9df73efdf1bf577d187fd492f289", size = 96913603 }, + { url = "https://files.pythonhosted.org/packages/ef/e3/fc30d25974dc6302d1126932c00d9e8e4bf6a4018fea41679bba69c077eb/paddlepaddle-3.0.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:220f8010c30cfd7712d0b0364e4732a344779ac202888ae1045e3567e24a6213", size = 192820725 }, + { url = "https://files.pythonhosted.org/packages/42/30/4f86d091fb8b312f157b3cd23670ff27da78232153a4b341a1a7d6fdf759/paddlepaddle-3.0.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f68630572edc4eb76ab6bbbe57689cb08b961f0d08bc0fc8c969d79b4bc213e9", size = 92046927 }, + { url = "https://files.pythonhosted.org/packages/ad/ee/eef6cfb98a44e11891bda8e898a9620df1303664f45e64285edc6ac93536/paddlepaddle-3.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:4b078cee4f6da995e4d2b1c46d1d94545f31a487b02ec1c61cfbb9e7d6d082f2", size = 96937322 }, +] + +[[package]] +name = "pathspec" +version = "0.12.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191 }, +] + +[[package]] +name = "pillow" +version = "11.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/af/cb/bb5c01fcd2a69335b86c22142b2bccfc3464087efb7fd382eee5ffc7fdf7/pillow-11.2.1.tar.gz", hash = "sha256:a64dd61998416367b7ef979b73d3a85853ba9bec4c2925f74e588879a58716b6", size = 47026707 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0d/8b/b158ad57ed44d3cc54db8d68ad7c0a58b8fc0e4c7a3f995f9d62d5b464a1/pillow-11.2.1-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:d57a75d53922fc20c165016a20d9c44f73305e67c351bbc60d1adaf662e74047", size = 3198442 }, + { url = "https://files.pythonhosted.org/packages/b1/f8/bb5d956142f86c2d6cc36704943fa761f2d2e4c48b7436fd0a85c20f1713/pillow-11.2.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:127bf6ac4a5b58b3d32fc8289656f77f80567d65660bc46f72c0d77e6600cc95", size = 3030553 }, + { url = "https://files.pythonhosted.org/packages/22/7f/0e413bb3e2aa797b9ca2c5c38cb2e2e45d88654e5b12da91ad446964cfae/pillow-11.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4ba4be812c7a40280629e55ae0b14a0aafa150dd6451297562e1764808bbe61", size = 4405503 }, + { url = "https://files.pythonhosted.org/packages/f3/b4/cc647f4d13f3eb837d3065824aa58b9bcf10821f029dc79955ee43f793bd/pillow-11.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8bd62331e5032bc396a93609982a9ab6b411c05078a52f5fe3cc59234a3abd1", size = 4490648 }, + { url = "https://files.pythonhosted.org/packages/c2/6f/240b772a3b35cdd7384166461567aa6713799b4e78d180c555bd284844ea/pillow-11.2.1-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:562d11134c97a62fe3af29581f083033179f7ff435f78392565a1ad2d1c2c45c", size = 4508937 }, + { url = "https://files.pythonhosted.org/packages/f3/5e/7ca9c815ade5fdca18853db86d812f2f188212792780208bdb37a0a6aef4/pillow-11.2.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:c97209e85b5be259994eb5b69ff50c5d20cca0f458ef9abd835e262d9d88b39d", size = 4599802 }, + { url = "https://files.pythonhosted.org/packages/02/81/c3d9d38ce0c4878a77245d4cf2c46d45a4ad0f93000227910a46caff52f3/pillow-11.2.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0c3e6d0f59171dfa2e25d7116217543310908dfa2770aa64b8f87605f8cacc97", size = 4576717 }, + { url = "https://files.pythonhosted.org/packages/42/49/52b719b89ac7da3185b8d29c94d0e6aec8140059e3d8adcaa46da3751180/pillow-11.2.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cc1c3bc53befb6096b84165956e886b1729634a799e9d6329a0c512ab651e579", size = 4654874 }, + { url = "https://files.pythonhosted.org/packages/5b/0b/ede75063ba6023798267023dc0d0401f13695d228194d2242d5a7ba2f964/pillow-11.2.1-cp310-cp310-win32.whl", hash = "sha256:312c77b7f07ab2139924d2639860e084ec2a13e72af54d4f08ac843a5fc9c79d", size = 2331717 }, + { url = "https://files.pythonhosted.org/packages/ed/3c/9831da3edea527c2ed9a09f31a2c04e77cd705847f13b69ca60269eec370/pillow-11.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:9bc7ae48b8057a611e5fe9f853baa88093b9a76303937449397899385da06fad", size = 2676204 }, + { url = "https://files.pythonhosted.org/packages/01/97/1f66ff8a1503d8cbfc5bae4dc99d54c6ec1e22ad2b946241365320caabc2/pillow-11.2.1-cp310-cp310-win_arm64.whl", hash = "sha256:2728567e249cdd939f6cc3d1f049595c66e4187f3c34078cbc0a7d21c47482d2", size = 2414767 }, + { url = "https://files.pythonhosted.org/packages/68/08/3fbf4b98924c73037a8e8b4c2c774784805e0fb4ebca6c5bb60795c40125/pillow-11.2.1-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:35ca289f712ccfc699508c4658a1d14652e8033e9b69839edf83cbdd0ba39e70", size = 3198450 }, + { url = "https://files.pythonhosted.org/packages/84/92/6505b1af3d2849d5e714fc75ba9e69b7255c05ee42383a35a4d58f576b16/pillow-11.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e0409af9f829f87a2dfb7e259f78f317a5351f2045158be321fd135973fff7bf", size = 3030550 }, + { url = "https://files.pythonhosted.org/packages/3c/8c/ac2f99d2a70ff966bc7eb13dacacfaab57c0549b2ffb351b6537c7840b12/pillow-11.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4e5c5edee874dce4f653dbe59db7c73a600119fbea8d31f53423586ee2aafd7", size = 4415018 }, + { url = "https://files.pythonhosted.org/packages/1f/e3/0a58b5d838687f40891fff9cbaf8669f90c96b64dc8f91f87894413856c6/pillow-11.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b93a07e76d13bff9444f1a029e0af2964e654bfc2e2c2d46bfd080df5ad5f3d8", size = 4498006 }, + { url = "https://files.pythonhosted.org/packages/21/f5/6ba14718135f08fbfa33308efe027dd02b781d3f1d5c471444a395933aac/pillow-11.2.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:e6def7eed9e7fa90fde255afaf08060dc4b343bbe524a8f69bdd2a2f0018f600", size = 4517773 }, + { url = "https://files.pythonhosted.org/packages/20/f2/805ad600fc59ebe4f1ba6129cd3a75fb0da126975c8579b8f57abeb61e80/pillow-11.2.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:8f4f3724c068be008c08257207210c138d5f3731af6c155a81c2b09a9eb3a788", size = 4607069 }, + { url = "https://files.pythonhosted.org/packages/71/6b/4ef8a288b4bb2e0180cba13ca0a519fa27aa982875882392b65131401099/pillow-11.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a0a6709b47019dff32e678bc12c63008311b82b9327613f534e496dacaefb71e", size = 4583460 }, + { url = "https://files.pythonhosted.org/packages/62/ae/f29c705a09cbc9e2a456590816e5c234382ae5d32584f451c3eb41a62062/pillow-11.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f6b0c664ccb879109ee3ca702a9272d877f4fcd21e5eb63c26422fd6e415365e", size = 4661304 }, + { url = "https://files.pythonhosted.org/packages/6e/1a/c8217b6f2f73794a5e219fbad087701f412337ae6dbb956db37d69a9bc43/pillow-11.2.1-cp311-cp311-win32.whl", hash = "sha256:cc5d875d56e49f112b6def6813c4e3d3036d269c008bf8aef72cd08d20ca6df6", size = 2331809 }, + { url = "https://files.pythonhosted.org/packages/e2/72/25a8f40170dc262e86e90f37cb72cb3de5e307f75bf4b02535a61afcd519/pillow-11.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:0f5c7eda47bf8e3c8a283762cab94e496ba977a420868cb819159980b6709193", size = 2676338 }, + { url = "https://files.pythonhosted.org/packages/06/9e/76825e39efee61efea258b479391ca77d64dbd9e5804e4ad0fa453b4ba55/pillow-11.2.1-cp311-cp311-win_arm64.whl", hash = "sha256:4d375eb838755f2528ac8cbc926c3e31cc49ca4ad0cf79cff48b20e30634a4a7", size = 2414918 }, + { url = "https://files.pythonhosted.org/packages/c7/40/052610b15a1b8961f52537cc8326ca6a881408bc2bdad0d852edeb6ed33b/pillow-11.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:78afba22027b4accef10dbd5eed84425930ba41b3ea0a86fa8d20baaf19d807f", size = 3190185 }, + { url = "https://files.pythonhosted.org/packages/e5/7e/b86dbd35a5f938632093dc40d1682874c33dcfe832558fc80ca56bfcb774/pillow-11.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:78092232a4ab376a35d68c4e6d5e00dfd73454bd12b230420025fbe178ee3b0b", size = 3030306 }, + { url = "https://files.pythonhosted.org/packages/a4/5c/467a161f9ed53e5eab51a42923c33051bf8d1a2af4626ac04f5166e58e0c/pillow-11.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25a5f306095c6780c52e6bbb6109624b95c5b18e40aab1c3041da3e9e0cd3e2d", size = 4416121 }, + { url = "https://files.pythonhosted.org/packages/62/73/972b7742e38ae0e2ac76ab137ca6005dcf877480da0d9d61d93b613065b4/pillow-11.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c7b29dbd4281923a2bfe562acb734cee96bbb129e96e6972d315ed9f232bef4", size = 4501707 }, + { url = "https://files.pythonhosted.org/packages/e4/3a/427e4cb0b9e177efbc1a84798ed20498c4f233abde003c06d2650a6d60cb/pillow-11.2.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:3e645b020f3209a0181a418bffe7b4a93171eef6c4ef6cc20980b30bebf17b7d", size = 4522921 }, + { url = "https://files.pythonhosted.org/packages/fe/7c/d8b1330458e4d2f3f45d9508796d7caf0c0d3764c00c823d10f6f1a3b76d/pillow-11.2.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:b2dbea1012ccb784a65349f57bbc93730b96e85b42e9bf7b01ef40443db720b4", size = 4612523 }, + { url = "https://files.pythonhosted.org/packages/b3/2f/65738384e0b1acf451de5a573d8153fe84103772d139e1e0bdf1596be2ea/pillow-11.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:da3104c57bbd72948d75f6a9389e6727d2ab6333c3617f0a89d72d4940aa0443", size = 4587836 }, + { url = "https://files.pythonhosted.org/packages/6a/c5/e795c9f2ddf3debb2dedd0df889f2fe4b053308bb59a3cc02a0cd144d641/pillow-11.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:598174aef4589af795f66f9caab87ba4ff860ce08cd5bb447c6fc553ffee603c", size = 4669390 }, + { url = "https://files.pythonhosted.org/packages/96/ae/ca0099a3995976a9fce2f423166f7bff9b12244afdc7520f6ed38911539a/pillow-11.2.1-cp312-cp312-win32.whl", hash = "sha256:1d535df14716e7f8776b9e7fee118576d65572b4aad3ed639be9e4fa88a1cad3", size = 2332309 }, + { url = "https://files.pythonhosted.org/packages/7c/18/24bff2ad716257fc03da964c5e8f05d9790a779a8895d6566e493ccf0189/pillow-11.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:14e33b28bf17c7a38eede290f77db7c664e4eb01f7869e37fa98a5aa95978941", size = 2676768 }, + { url = "https://files.pythonhosted.org/packages/da/bb/e8d656c9543276517ee40184aaa39dcb41e683bca121022f9323ae11b39d/pillow-11.2.1-cp312-cp312-win_arm64.whl", hash = "sha256:21e1470ac9e5739ff880c211fc3af01e3ae505859392bf65458c224d0bf283eb", size = 2415087 }, + { url = "https://files.pythonhosted.org/packages/36/9c/447528ee3776e7ab8897fe33697a7ff3f0475bb490c5ac1456a03dc57956/pillow-11.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:fdec757fea0b793056419bca3e9932eb2b0ceec90ef4813ea4c1e072c389eb28", size = 3190098 }, + { url = "https://files.pythonhosted.org/packages/b5/09/29d5cd052f7566a63e5b506fac9c60526e9ecc553825551333e1e18a4858/pillow-11.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b0e130705d568e2f43a17bcbe74d90958e8a16263868a12c3e0d9c8162690830", size = 3030166 }, + { url = "https://files.pythonhosted.org/packages/71/5d/446ee132ad35e7600652133f9c2840b4799bbd8e4adba881284860da0a36/pillow-11.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bdb5e09068332578214cadd9c05e3d64d99e0e87591be22a324bdbc18925be0", size = 4408674 }, + { url = "https://files.pythonhosted.org/packages/69/5f/cbe509c0ddf91cc3a03bbacf40e5c2339c4912d16458fcb797bb47bcb269/pillow-11.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d189ba1bebfbc0c0e529159631ec72bb9e9bc041f01ec6d3233d6d82eb823bc1", size = 4496005 }, + { url = "https://files.pythonhosted.org/packages/f9/b3/dd4338d8fb8a5f312021f2977fb8198a1184893f9b00b02b75d565c33b51/pillow-11.2.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:191955c55d8a712fab8934a42bfefbf99dd0b5875078240943f913bb66d46d9f", size = 4518707 }, + { url = "https://files.pythonhosted.org/packages/13/eb/2552ecebc0b887f539111c2cd241f538b8ff5891b8903dfe672e997529be/pillow-11.2.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:ad275964d52e2243430472fc5d2c2334b4fc3ff9c16cb0a19254e25efa03a155", size = 4610008 }, + { url = "https://files.pythonhosted.org/packages/72/d1/924ce51bea494cb6e7959522d69d7b1c7e74f6821d84c63c3dc430cbbf3b/pillow-11.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:750f96efe0597382660d8b53e90dd1dd44568a8edb51cb7f9d5d918b80d4de14", size = 4585420 }, + { url = "https://files.pythonhosted.org/packages/43/ab/8f81312d255d713b99ca37479a4cb4b0f48195e530cdc1611990eb8fd04b/pillow-11.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fe15238d3798788d00716637b3d4e7bb6bde18b26e5d08335a96e88564a36b6b", size = 4667655 }, + { url = "https://files.pythonhosted.org/packages/94/86/8f2e9d2dc3d308dfd137a07fe1cc478df0a23d42a6c4093b087e738e4827/pillow-11.2.1-cp313-cp313-win32.whl", hash = "sha256:3fe735ced9a607fee4f481423a9c36701a39719252a9bb251679635f99d0f7d2", size = 2332329 }, + { url = "https://files.pythonhosted.org/packages/6d/ec/1179083b8d6067a613e4d595359b5fdea65d0a3b7ad623fee906e1b3c4d2/pillow-11.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:74ee3d7ecb3f3c05459ba95eed5efa28d6092d751ce9bf20e3e253a4e497e691", size = 2676388 }, + { url = "https://files.pythonhosted.org/packages/23/f1/2fc1e1e294de897df39fa8622d829b8828ddad938b0eaea256d65b84dd72/pillow-11.2.1-cp313-cp313-win_arm64.whl", hash = "sha256:5119225c622403afb4b44bad4c1ca6c1f98eed79db8d3bc6e4e160fc6339d66c", size = 2414950 }, + { url = "https://files.pythonhosted.org/packages/c4/3e/c328c48b3f0ead7bab765a84b4977acb29f101d10e4ef57a5e3400447c03/pillow-11.2.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8ce2e8411c7aaef53e6bb29fe98f28cd4fbd9a1d9be2eeea434331aac0536b22", size = 3192759 }, + { url = "https://files.pythonhosted.org/packages/18/0e/1c68532d833fc8b9f404d3a642991441d9058eccd5606eab31617f29b6d4/pillow-11.2.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:9ee66787e095127116d91dea2143db65c7bb1e232f617aa5957c0d9d2a3f23a7", size = 3033284 }, + { url = "https://files.pythonhosted.org/packages/b7/cb/6faf3fb1e7705fd2db74e070f3bf6f88693601b0ed8e81049a8266de4754/pillow-11.2.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9622e3b6c1d8b551b6e6f21873bdcc55762b4b2126633014cea1803368a9aa16", size = 4445826 }, + { url = "https://files.pythonhosted.org/packages/07/94/8be03d50b70ca47fb434a358919d6a8d6580f282bbb7af7e4aa40103461d/pillow-11.2.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63b5dff3a68f371ea06025a1a6966c9a1e1ee452fc8020c2cd0ea41b83e9037b", size = 4527329 }, + { url = "https://files.pythonhosted.org/packages/fd/a4/bfe78777076dc405e3bd2080bc32da5ab3945b5a25dc5d8acaa9de64a162/pillow-11.2.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:31df6e2d3d8fc99f993fd253e97fae451a8db2e7207acf97859732273e108406", size = 4549049 }, + { url = "https://files.pythonhosted.org/packages/65/4d/eaf9068dc687c24979e977ce5677e253624bd8b616b286f543f0c1b91662/pillow-11.2.1-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:062b7a42d672c45a70fa1f8b43d1d38ff76b63421cbbe7f88146b39e8a558d91", size = 4635408 }, + { url = "https://files.pythonhosted.org/packages/1d/26/0fd443365d9c63bc79feb219f97d935cd4b93af28353cba78d8e77b61719/pillow-11.2.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4eb92eca2711ef8be42fd3f67533765d9fd043b8c80db204f16c8ea62ee1a751", size = 4614863 }, + { url = "https://files.pythonhosted.org/packages/49/65/dca4d2506be482c2c6641cacdba5c602bc76d8ceb618fd37de855653a419/pillow-11.2.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f91ebf30830a48c825590aede79376cb40f110b387c17ee9bd59932c961044f9", size = 4692938 }, + { url = "https://files.pythonhosted.org/packages/b3/92/1ca0c3f09233bd7decf8f7105a1c4e3162fb9142128c74adad0fb361b7eb/pillow-11.2.1-cp313-cp313t-win32.whl", hash = "sha256:e0b55f27f584ed623221cfe995c912c61606be8513bfa0e07d2c674b4516d9dd", size = 2335774 }, + { url = "https://files.pythonhosted.org/packages/a5/ac/77525347cb43b83ae905ffe257bbe2cc6fd23acb9796639a1f56aa59d191/pillow-11.2.1-cp313-cp313t-win_amd64.whl", hash = "sha256:36d6b82164c39ce5482f649b437382c0fb2395eabc1e2b1702a6deb8ad647d6e", size = 2681895 }, + { url = "https://files.pythonhosted.org/packages/67/32/32dc030cfa91ca0fc52baebbba2e009bb001122a1daa8b6a79ad830b38d3/pillow-11.2.1-cp313-cp313t-win_arm64.whl", hash = "sha256:225c832a13326e34f212d2072982bb1adb210e0cc0b153e688743018c94a2681", size = 2417234 }, + { url = "https://files.pythonhosted.org/packages/21/3a/c1835d1c7cf83559e95b4f4ed07ab0bb7acc689712adfce406b3f456e9fd/pillow-11.2.1-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:7491cf8a79b8eb867d419648fff2f83cb0b3891c8b36da92cc7f1931d46108c8", size = 3198391 }, + { url = "https://files.pythonhosted.org/packages/b6/4d/dcb7a9af3fc1e8653267c38ed622605d9d1793349274b3ef7af06457e257/pillow-11.2.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8b02d8f9cb83c52578a0b4beadba92e37d83a4ef11570a8688bbf43f4ca50909", size = 3030573 }, + { url = "https://files.pythonhosted.org/packages/9d/29/530ca098c1a1eb31d4e163d317d0e24e6d2ead907991c69ca5b663de1bc5/pillow-11.2.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:014ca0050c85003620526b0ac1ac53f56fc93af128f7546623cc8e31875ab928", size = 4398677 }, + { url = "https://files.pythonhosted.org/packages/8b/ee/0e5e51db34de1690264e5f30dcd25328c540aa11d50a3bc0b540e2a445b6/pillow-11.2.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3692b68c87096ac6308296d96354eddd25f98740c9d2ab54e1549d6c8aea9d79", size = 4484986 }, + { url = "https://files.pythonhosted.org/packages/93/7d/bc723b41ce3d2c28532c47678ec988974f731b5c6fadd5b3a4fba9015e4f/pillow-11.2.1-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:f781dcb0bc9929adc77bad571b8621ecb1e4cdef86e940fe2e5b5ee24fd33b35", size = 4501897 }, + { url = "https://files.pythonhosted.org/packages/be/0b/532e31abc7389617ddff12551af625a9b03cd61d2989fa595e43c470ec67/pillow-11.2.1-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:2b490402c96f907a166615e9a5afacf2519e28295f157ec3a2bb9bd57de638cb", size = 4592618 }, + { url = "https://files.pythonhosted.org/packages/4c/f0/21ed6499a6216fef753e2e2254a19d08bff3747108ba042422383f3e9faa/pillow-11.2.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dd6b20b93b3ccc9c1b597999209e4bc5cf2853f9ee66e3fc9a400a78733ffc9a", size = 4570493 }, + { url = "https://files.pythonhosted.org/packages/68/de/17004ddb8ab855573fe1127ab0168d11378cdfe4a7ee2a792a70ff2e9ba7/pillow-11.2.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:4b835d89c08a6c2ee7781b8dd0a30209a8012b5f09c0a665b65b0eb3560b6f36", size = 4647748 }, + { url = "https://files.pythonhosted.org/packages/c7/23/82ecb486384bb3578115c509d4a00bb52f463ee700a5ca1be53da3c88c19/pillow-11.2.1-cp39-cp39-win32.whl", hash = "sha256:b10428b3416d4f9c61f94b494681280be7686bda15898a3a9e08eb66a6d92d67", size = 2331731 }, + { url = "https://files.pythonhosted.org/packages/58/bb/87efd58b3689537a623d44dbb2550ef0bb5ff6a62769707a0fe8b1a7bdeb/pillow-11.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:6ebce70c3f486acf7591a3d73431fa504a4e18a9b97ff27f5f47b7368e4b9dd1", size = 2676346 }, + { url = "https://files.pythonhosted.org/packages/80/08/dc268475b22887b816e5dcfae31bce897f524b4646bab130c2142c9b2400/pillow-11.2.1-cp39-cp39-win_arm64.whl", hash = "sha256:c27476257b2fdcd7872d54cfd119b3a9ce4610fb85c8e32b70b42e3680a29a1e", size = 2414623 }, + { url = "https://files.pythonhosted.org/packages/33/49/c8c21e4255b4f4a2c0c68ac18125d7f5460b109acc6dfdef1a24f9b960ef/pillow-11.2.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:9b7b0d4fd2635f54ad82785d56bc0d94f147096493a79985d0ab57aedd563156", size = 3181727 }, + { url = "https://files.pythonhosted.org/packages/6d/f1/f7255c0838f8c1ef6d55b625cfb286835c17e8136ce4351c5577d02c443b/pillow-11.2.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:aa442755e31c64037aa7c1cb186e0b369f8416c567381852c63444dd666fb772", size = 2999833 }, + { url = "https://files.pythonhosted.org/packages/e2/57/9968114457bd131063da98d87790d080366218f64fa2943b65ac6739abb3/pillow-11.2.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f0d3348c95b766f54b76116d53d4cb171b52992a1027e7ca50c81b43b9d9e363", size = 3437472 }, + { url = "https://files.pythonhosted.org/packages/b2/1b/e35d8a158e21372ecc48aac9c453518cfe23907bb82f950d6e1c72811eb0/pillow-11.2.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85d27ea4c889342f7e35f6d56e7e1cb345632ad592e8c51b693d7b7556043ce0", size = 3459976 }, + { url = "https://files.pythonhosted.org/packages/26/da/2c11d03b765efff0ccc473f1c4186dc2770110464f2177efaed9cf6fae01/pillow-11.2.1-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:bf2c33d6791c598142f00c9c4c7d47f6476731c31081331664eb26d6ab583e01", size = 3527133 }, + { url = "https://files.pythonhosted.org/packages/79/1a/4e85bd7cadf78412c2a3069249a09c32ef3323650fd3005c97cca7aa21df/pillow-11.2.1-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e616e7154c37669fc1dfc14584f11e284e05d1c650e1c0f972f281c4ccc53193", size = 3571555 }, + { url = "https://files.pythonhosted.org/packages/69/03/239939915216de1e95e0ce2334bf17a7870ae185eb390fab6d706aadbfc0/pillow-11.2.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:39ad2e0f424394e3aebc40168845fee52df1394a4673a6ee512d840d14ab3013", size = 2674713 }, + { url = "https://files.pythonhosted.org/packages/a4/ad/2613c04633c7257d9481ab21d6b5364b59fc5d75faafd7cb8693523945a3/pillow-11.2.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:80f1df8dbe9572b4b7abdfa17eb5d78dd620b1d55d9e25f834efdbee872d3aed", size = 3181734 }, + { url = "https://files.pythonhosted.org/packages/a4/fd/dcdda4471ed667de57bb5405bb42d751e6cfdd4011a12c248b455c778e03/pillow-11.2.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:ea926cfbc3957090becbcbbb65ad177161a2ff2ad578b5a6ec9bb1e1cd78753c", size = 2999841 }, + { url = "https://files.pythonhosted.org/packages/ac/89/8a2536e95e77432833f0db6fd72a8d310c8e4272a04461fb833eb021bf94/pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:738db0e0941ca0376804d4de6a782c005245264edaa253ffce24e5a15cbdc7bd", size = 3437470 }, + { url = "https://files.pythonhosted.org/packages/9d/8f/abd47b73c60712f88e9eda32baced7bfc3e9bd6a7619bb64b93acff28c3e/pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9db98ab6565c69082ec9b0d4e40dd9f6181dab0dd236d26f7a50b8b9bfbd5076", size = 3460013 }, + { url = "https://files.pythonhosted.org/packages/f6/20/5c0a0aa83b213b7a07ec01e71a3d6ea2cf4ad1d2c686cc0168173b6089e7/pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:036e53f4170e270ddb8797d4c590e6dd14d28e15c7da375c18978045f7e6c37b", size = 3527165 }, + { url = "https://files.pythonhosted.org/packages/58/0e/2abab98a72202d91146abc839e10c14f7cf36166f12838ea0c4db3ca6ecb/pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:14f73f7c291279bd65fda51ee87affd7c1e097709f7fdd0188957a16c264601f", size = 3571586 }, + { url = "https://files.pythonhosted.org/packages/21/2c/5e05f58658cf49b6667762cca03d6e7d85cededde2caf2ab37b81f80e574/pillow-11.2.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:208653868d5c9ecc2b327f9b9ef34e0e42a4cdd172c2988fd81d62d2bc9bc044", size = 2674751 }, +] + +[[package]] +name = "platformdirs" +version = "4.3.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b6/2d/7d512a3913d60623e7eb945c6d1b4f0bddf1d0b7ada5225274c87e5b53d1/platformdirs-4.3.7.tar.gz", hash = "sha256:eb437d586b6a0986388f0d6f74aa0cde27b48d0e3d66843640bfb6bdcdb6e351", size = 21291 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6d/45/59578566b3275b8fd9157885918fcd0c4d74162928a5310926887b856a51/platformdirs-4.3.7-py3-none-any.whl", hash = "sha256:a03875334331946f13c549dbd8f4bac7a13a50a895a0eb1e8c6a8ace80d40a94", size = 18499 }, +] + +[[package]] +name = "pluggy" +version = "1.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/96/2d/02d4312c973c6050a18b314a5ad0b3210edb65a906f868e31c111dede4a6/pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", size = 67955 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556 }, +] + +[[package]] +name = "protobuf" +version = "5.29.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/17/7d/b9dca7365f0e2c4fa7c193ff795427cfa6290147e5185ab11ece280a18e7/protobuf-5.29.4.tar.gz", hash = "sha256:4f1dfcd7997b31ef8f53ec82781ff434a28bf71d9102ddde14d076adcfc78c99", size = 424902 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9a/b2/043a1a1a20edd134563699b0e91862726a0dc9146c090743b6c44d798e75/protobuf-5.29.4-cp310-abi3-win32.whl", hash = "sha256:13eb236f8eb9ec34e63fc8b1d6efd2777d062fa6aaa68268fb67cf77f6839ad7", size = 422709 }, + { url = "https://files.pythonhosted.org/packages/79/fc/2474b59570daa818de6124c0a15741ee3e5d6302e9d6ce0bdfd12e98119f/protobuf-5.29.4-cp310-abi3-win_amd64.whl", hash = "sha256:bcefcdf3976233f8a502d265eb65ea740c989bacc6c30a58290ed0e519eb4b8d", size = 434506 }, + { url = "https://files.pythonhosted.org/packages/46/de/7c126bbb06aa0f8a7b38aaf8bd746c514d70e6a2a3f6dd460b3b7aad7aae/protobuf-5.29.4-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:307ecba1d852ec237e9ba668e087326a67564ef83e45a0189a772ede9e854dd0", size = 417826 }, + { url = "https://files.pythonhosted.org/packages/a2/b5/bade14ae31ba871a139aa45e7a8183d869efe87c34a4850c87b936963261/protobuf-5.29.4-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:aec4962f9ea93c431d5714ed1be1c93f13e1a8618e70035ba2b0564d9e633f2e", size = 319574 }, + { url = "https://files.pythonhosted.org/packages/46/88/b01ed2291aae68b708f7d334288ad5fb3e7aa769a9c309c91a0d55cb91b0/protobuf-5.29.4-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:d7d3f7d1d5a66ed4942d4fefb12ac4b14a29028b209d4bfb25c68ae172059922", size = 319672 }, + { url = "https://files.pythonhosted.org/packages/8a/b8/c3847343ebd9c7ae0b762de1e173b110689fd334ac8dcf1697ffd9316861/protobuf-5.29.4-cp39-cp39-win32.whl", hash = "sha256:fd32223020cb25a2cc100366f1dedc904e2d71d9322403224cdde5fdced0dabe", size = 422675 }, + { url = "https://files.pythonhosted.org/packages/f0/74/e23e1ab05b27ce0b55f70be90df82076a5c18924d98679110459c52bacd9/protobuf-5.29.4-cp39-cp39-win_amd64.whl", hash = "sha256:678974e1e3a9b975b8bc2447fca458db5f93a2fb6b0c8db46b6675b5b5346812", size = 434594 }, + { url = "https://files.pythonhosted.org/packages/12/fb/a586e0c973c95502e054ac5f81f88394f24ccc7982dac19c515acd9e2c93/protobuf-5.29.4-py3-none-any.whl", hash = "sha256:3fde11b505e1597f71b875ef2fc52062b6a9740e5f7c8997ce878b6009145862", size = 172551 }, +] + +[[package]] +name = "py-cpuinfo" +version = "9.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/37/a8/d832f7293ebb21690860d2e01d8115e5ff6f2ae8bbdc953f0eb0fa4bd2c7/py-cpuinfo-9.0.0.tar.gz", hash = "sha256:3cdbbf3fac90dc6f118bfd64384f309edeadd902d7c8fb17f02ffa1fc3f49690", size = 104716 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl", hash = "sha256:859625bc251f64e21f077d099d4162689c762b5d6a4c3c97553d56241c9674d5", size = 22335 }, +] + +[[package]] +name = "pycodestyle" +version = "2.13.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/04/6e/1f4a62078e4d95d82367f24e685aef3a672abfd27d1a868068fed4ed2254/pycodestyle-2.13.0.tar.gz", hash = "sha256:c8415bf09abe81d9c7f872502a6eee881fbe85d8763dd5b9924bb0a01d67efae", size = 39312 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/07/be/b00116df1bfb3e0bb5b45e29d604799f7b91dd861637e4d448b4e09e6a3e/pycodestyle-2.13.0-py2.py3-none-any.whl", hash = "sha256:35863c5974a271c7a726ed228a14a4f6daf49df369d8c50cd9a6f58a5e143ba9", size = 31424 }, +] + +[[package]] +name = "pyflakes" +version = "3.3.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/af/cc/1df338bd7ed1fa7c317081dcf29bf2f01266603b301e6858856d346a12b3/pyflakes-3.3.2.tar.gz", hash = "sha256:6dfd61d87b97fba5dcfaaf781171ac16be16453be6d816147989e7f6e6a9576b", size = 64175 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/15/40/b293a4fa769f3b02ab9e387c707c4cbdc34f073f945de0386107d4e669e6/pyflakes-3.3.2-py2.py3-none-any.whl", hash = "sha256:5039c8339cbb1944045f4ee5466908906180f13cc99cc9949348d10f82a5c32a", size = 63164 }, +] + +[[package]] +name = "pygments" +version = "2.19.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293 }, +] + +[[package]] +name = "pytest" +version = "8.3.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ae/3c/c9d525a414d506893f0cd8a8d0de7706446213181570cdbd766691164e40/pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845", size = 1450891 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/30/3d/64ad57c803f1fa1e963a7946b6e0fea4a70df53c1a7fed304586539c2bac/pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", size = 343634 }, +] + +[[package]] +name = "pytest-benchmark" +version = "5.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "py-cpuinfo" }, + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/39/d0/a8bd08d641b393db3be3819b03e2d9bb8760ca8479080a26a5f6e540e99c/pytest-benchmark-5.1.0.tar.gz", hash = "sha256:9ea661cdc292e8231f7cd4c10b0319e56a2118e2c09d9f50e1b3d150d2aca105", size = 337810 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/d6/b41653199ea09d5969d4e385df9bbfd9a100f28ca7e824ce7c0a016e3053/pytest_benchmark-5.1.0-py3-none-any.whl", hash = "sha256:922de2dfa3033c227c96da942d1878191afa135a29485fb942e85dff1c592c89", size = 44259 }, +] + +[[package]] +name = "pyyaml" +version = "6.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9b/95/a3fac87cb7158e231b5a6012e438c647e1a87f09f8e0d123acec8ab8bf71/PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086", size = 184199 }, + { url = "https://files.pythonhosted.org/packages/c7/7a/68bd47624dab8fd4afbfd3c48e3b79efe09098ae941de5b58abcbadff5cb/PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf", size = 171758 }, + { url = "https://files.pythonhosted.org/packages/49/ee/14c54df452143b9ee9f0f29074d7ca5516a36edb0b4cc40c3f280131656f/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237", size = 718463 }, + { url = "https://files.pythonhosted.org/packages/4d/61/de363a97476e766574650d742205be468921a7b532aa2499fcd886b62530/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b", size = 719280 }, + { url = "https://files.pythonhosted.org/packages/6b/4e/1523cb902fd98355e2e9ea5e5eb237cbc5f3ad5f3075fa65087aa0ecb669/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed", size = 751239 }, + { url = "https://files.pythonhosted.org/packages/b7/33/5504b3a9a4464893c32f118a9cc045190a91637b119a9c881da1cf6b7a72/PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180", size = 695802 }, + { url = "https://files.pythonhosted.org/packages/5c/20/8347dcabd41ef3a3cdc4f7b7a2aff3d06598c8779faa189cdbf878b626a4/PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68", size = 720527 }, + { url = "https://files.pythonhosted.org/packages/be/aa/5afe99233fb360d0ff37377145a949ae258aaab831bde4792b32650a4378/PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99", size = 144052 }, + { url = "https://files.pythonhosted.org/packages/b5/84/0fa4b06f6d6c958d207620fc60005e241ecedceee58931bb20138e1e5776/PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e", size = 161774 }, + { url = "https://files.pythonhosted.org/packages/f8/aa/7af4e81f7acba21a4c6be026da38fd2b872ca46226673c89a758ebdc4fd2/PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774", size = 184612 }, + { url = "https://files.pythonhosted.org/packages/8b/62/b9faa998fd185f65c1371643678e4d58254add437edb764a08c5a98fb986/PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee", size = 172040 }, + { url = "https://files.pythonhosted.org/packages/ad/0c/c804f5f922a9a6563bab712d8dcc70251e8af811fce4524d57c2c0fd49a4/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c", size = 736829 }, + { url = "https://files.pythonhosted.org/packages/51/16/6af8d6a6b210c8e54f1406a6b9481febf9c64a3109c541567e35a49aa2e7/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317", size = 764167 }, + { url = "https://files.pythonhosted.org/packages/75/e4/2c27590dfc9992f73aabbeb9241ae20220bd9452df27483b6e56d3975cc5/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85", size = 762952 }, + { url = "https://files.pythonhosted.org/packages/9b/97/ecc1abf4a823f5ac61941a9c00fe501b02ac3ab0e373c3857f7d4b83e2b6/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4", size = 735301 }, + { url = "https://files.pythonhosted.org/packages/45/73/0f49dacd6e82c9430e46f4a027baa4ca205e8b0a9dce1397f44edc23559d/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e", size = 756638 }, + { url = "https://files.pythonhosted.org/packages/22/5f/956f0f9fc65223a58fbc14459bf34b4cc48dec52e00535c79b8db361aabd/PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5", size = 143850 }, + { url = "https://files.pythonhosted.org/packages/ed/23/8da0bbe2ab9dcdd11f4f4557ccaf95c10b9811b13ecced089d43ce59c3c8/PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44", size = 161980 }, + { url = "https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", size = 183873 }, + { url = "https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", size = 173302 }, + { url = "https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", size = 739154 }, + { url = "https://files.pythonhosted.org/packages/95/0f/b8938f1cbd09739c6da569d172531567dbcc9789e0029aa070856f123984/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", size = 766223 }, + { url = "https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", size = 767542 }, + { url = "https://files.pythonhosted.org/packages/d4/00/dd137d5bcc7efea1836d6264f049359861cf548469d18da90cd8216cf05f/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", size = 731164 }, + { url = "https://files.pythonhosted.org/packages/c9/1f/4f998c900485e5c0ef43838363ba4a9723ac0ad73a9dc42068b12aaba4e4/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", size = 756611 }, + { url = "https://files.pythonhosted.org/packages/df/d1/f5a275fdb252768b7a11ec63585bc38d0e87c9e05668a139fea92b80634c/PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", size = 140591 }, + { url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", size = 156338 }, + { url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309 }, + { url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679 }, + { url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428 }, + { url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361 }, + { url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523 }, + { url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660 }, + { url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597 }, + { url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527 }, + { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446 }, + { url = "https://files.pythonhosted.org/packages/65/d8/b7a1db13636d7fb7d4ff431593c510c8b8fca920ade06ca8ef20015493c5/PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d", size = 184777 }, + { url = "https://files.pythonhosted.org/packages/0a/02/6ec546cd45143fdf9840b2c6be8d875116a64076218b61d68e12548e5839/PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f", size = 172318 }, + { url = "https://files.pythonhosted.org/packages/0e/9a/8cc68be846c972bda34f6c2a93abb644fb2476f4dcc924d52175786932c9/PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290", size = 720891 }, + { url = "https://files.pythonhosted.org/packages/e9/6c/6e1b7f40181bc4805e2e07f4abc10a88ce4648e7e95ff1abe4ae4014a9b2/PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12", size = 722614 }, + { url = "https://files.pythonhosted.org/packages/3d/32/e7bd8535d22ea2874cef6a81021ba019474ace0d13a4819c2a4bce79bd6a/PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19", size = 737360 }, + { url = "https://files.pythonhosted.org/packages/d7/12/7322c1e30b9be969670b672573d45479edef72c9a0deac3bb2868f5d7469/PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e", size = 699006 }, + { url = "https://files.pythonhosted.org/packages/82/72/04fcad41ca56491995076630c3ec1e834be241664c0c09a64c9a2589b507/PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725", size = 723577 }, + { url = "https://files.pythonhosted.org/packages/ed/5e/46168b1f2757f1fcd442bc3029cd8767d88a98c9c05770d8b420948743bb/PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631", size = 144593 }, + { url = "https://files.pythonhosted.org/packages/19/87/5124b1c1f2412bb95c59ec481eaf936cd32f0fe2a7b16b97b81c4c017a6a/PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8", size = 162312 }, +] + +[[package]] +name = "requests" +version = "2.32.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", size = 131218 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928 }, +] + +[[package]] +name = "rich" +version = "14.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown-it-py" }, + { name = "pygments" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a1/53/830aa4c3066a8ab0ae9a9955976fb770fe9c6102117c8ec4ab3ea62d89e8/rich-14.0.0.tar.gz", hash = "sha256:82f1bc23a6a21ebca4ae0c45af9bdbc492ed20231dcb63f297d6d1021a9d5725", size = 224078 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0d/9b/63f4c7ebc259242c89b3acafdb37b41d1185c07ff0011164674e9076b491/rich-14.0.0-py3-none-any.whl", hash = "sha256:1c9491e1951aac09caffd42f448ee3d04e58923ffe14993f6e83068dc395d7e0", size = 243229 }, +] + +[[package]] +name = "safetensors" +source = { editable = "." } + +[package.optional-dependencies] +all = [ + { name = "black" }, + { name = "click" }, + { name = "flake8" }, + { name = "flax", version = "0.8.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "flax", version = "0.10.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "h5py" }, + { name = "huggingface-hub" }, + { name = "hypothesis" }, + { name = "isort" }, + { name = "jax", version = "0.4.30", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "jax", version = "0.5.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "jaxlib", version = "0.4.30", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "jaxlib", version = "0.5.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "numpy" }, + { name = "paddlepaddle" }, + { name = "pytest" }, + { name = "pytest-benchmark" }, + { name = "setuptools-rust" }, + { name = "tensorflow" }, + { name = "torch" }, +] +dev = [ + { name = "black" }, + { name = "click" }, + { name = "flake8" }, + { name = "flax", version = "0.8.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "flax", version = "0.10.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "h5py" }, + { name = "huggingface-hub" }, + { name = "hypothesis" }, + { name = "isort" }, + { name = "jax", version = "0.4.30", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "jax", version = "0.5.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "jaxlib", version = "0.4.30", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "jaxlib", version = "0.5.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "numpy" }, + { name = "paddlepaddle" }, + { name = "pytest" }, + { name = "pytest-benchmark" }, + { name = "setuptools-rust" }, + { name = "tensorflow" }, + { name = "torch" }, +] +jax = [ + { name = "flax", version = "0.8.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "flax", version = "0.10.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "jax", version = "0.4.30", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "jax", version = "0.5.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "jaxlib", version = "0.4.30", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "jaxlib", version = "0.5.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "numpy" }, +] +mlx = [ + { name = "mlx" }, +] +numpy = [ + { name = "numpy" }, +] +paddlepaddle = [ + { name = "numpy" }, + { name = "paddlepaddle" }, +] +pinned-tf = [ + { name = "numpy" }, + { name = "tensorflow" }, +] +quality = [ + { name = "black" }, + { name = "click" }, + { name = "flake8" }, + { name = "isort" }, +] +tensorflow = [ + { name = "numpy" }, + { name = "tensorflow" }, +] +testing = [ + { name = "h5py" }, + { name = "huggingface-hub" }, + { name = "hypothesis" }, + { name = "numpy" }, + { name = "pytest" }, + { name = "pytest-benchmark" }, + { name = "setuptools-rust" }, +] +torch = [ + { name = "numpy" }, + { name = "torch" }, +] + +[package.metadata] +requires-dist = [ + { name = "black", marker = "extra == 'quality'", specifier = "==22.3" }, + { name = "click", marker = "extra == 'quality'", specifier = "==8.0.4" }, + { name = "flake8", marker = "extra == 'quality'", specifier = ">=3.8.3" }, + { name = "flax", marker = "extra == 'jax'", specifier = ">=0.6.3" }, + { name = "h5py", marker = "extra == 'testing'", specifier = ">=3.7.0" }, + { name = "huggingface-hub", marker = "extra == 'testing'", specifier = ">=0.12.1" }, + { name = "hypothesis", marker = "extra == 'testing'", specifier = ">=6.70.2" }, + { name = "isort", marker = "extra == 'quality'", specifier = ">=5.5.4" }, + { name = "jax", marker = "extra == 'jax'", specifier = ">=0.3.25" }, + { name = "jaxlib", marker = "extra == 'jax'", specifier = ">=0.3.25" }, + { name = "mlx", marker = "extra == 'mlx'", specifier = ">=0.0.9" }, + { name = "numpy", marker = "extra == 'numpy'", specifier = ">=1.21.6" }, + { name = "paddlepaddle", marker = "extra == 'paddlepaddle'", specifier = ">=2.4.1" }, + { name = "pytest", marker = "extra == 'testing'", specifier = ">=7.2.0" }, + { name = "pytest-benchmark", marker = "extra == 'testing'", specifier = ">=4.0.0" }, + { name = "safetensors", extras = ["all"], marker = "extra == 'dev'" }, + { name = "safetensors", extras = ["jax"], marker = "extra == 'all'" }, + { name = "safetensors", extras = ["numpy"], marker = "extra == 'all'" }, + { name = "safetensors", extras = ["numpy"], marker = "extra == 'jax'" }, + { name = "safetensors", extras = ["numpy"], marker = "extra == 'paddlepaddle'" }, + { name = "safetensors", extras = ["numpy"], marker = "extra == 'pinned-tf'" }, + { name = "safetensors", extras = ["numpy"], marker = "extra == 'tensorflow'" }, + { name = "safetensors", extras = ["numpy"], marker = "extra == 'testing'" }, + { name = "safetensors", extras = ["numpy"], marker = "extra == 'torch'" }, + { name = "safetensors", extras = ["paddlepaddle"], marker = "extra == 'all'" }, + { name = "safetensors", extras = ["pinned-tf"], marker = "extra == 'all'" }, + { name = "safetensors", extras = ["quality"], marker = "extra == 'all'" }, + { name = "safetensors", extras = ["testing"], marker = "extra == 'all'" }, + { name = "safetensors", extras = ["torch"], marker = "extra == 'all'" }, + { name = "setuptools-rust", marker = "extra == 'testing'", specifier = ">=1.5.2" }, + { name = "tensorflow", marker = "extra == 'pinned-tf'", specifier = "==2.18.0" }, + { name = "tensorflow", marker = "extra == 'tensorflow'", specifier = ">=2.11.0" }, + { name = "torch", marker = "extra == 'torch'", specifier = ">=1.10" }, +] +provides-extras = ["numpy", "torch", "tensorflow", "pinned-tf", "jax", "mlx", "paddlepaddle", "quality", "testing", "all", "dev"] + +[[package]] +name = "scipy" +version = "1.13.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] +dependencies = [ + { name = "numpy", marker = "python_full_version < '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ae/00/48c2f661e2816ccf2ecd77982f6605b2950afe60f60a52b4cbbc2504aa8f/scipy-1.13.1.tar.gz", hash = "sha256:095a87a0312b08dfd6a6155cbbd310a8c51800fc931b8c0b84003014b874ed3c", size = 57210720 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/33/59/41b2529908c002ade869623b87eecff3e11e3ce62e996d0bdcb536984187/scipy-1.13.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:20335853b85e9a49ff7572ab453794298bcf0354d8068c5f6775a0eabf350aca", size = 39328076 }, + { url = "https://files.pythonhosted.org/packages/d5/33/f1307601f492f764062ce7dd471a14750f3360e33cd0f8c614dae208492c/scipy-1.13.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:d605e9c23906d1994f55ace80e0125c587f96c020037ea6aa98d01b4bd2e222f", size = 30306232 }, + { url = "https://files.pythonhosted.org/packages/c0/66/9cd4f501dd5ea03e4a4572ecd874936d0da296bd04d1c45ae1a4a75d9c3a/scipy-1.13.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cfa31f1def5c819b19ecc3a8b52d28ffdcc7ed52bb20c9a7589669dd3c250989", size = 33743202 }, + { url = "https://files.pythonhosted.org/packages/a3/ba/7255e5dc82a65adbe83771c72f384d99c43063648456796436c9a5585ec3/scipy-1.13.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f26264b282b9da0952a024ae34710c2aff7d27480ee91a2e82b7b7073c24722f", size = 38577335 }, + { url = "https://files.pythonhosted.org/packages/49/a5/bb9ded8326e9f0cdfdc412eeda1054b914dfea952bda2097d174f8832cc0/scipy-1.13.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:eccfa1906eacc02de42d70ef4aecea45415f5be17e72b61bafcfd329bdc52e94", size = 38820728 }, + { url = "https://files.pythonhosted.org/packages/12/30/df7a8fcc08f9b4a83f5f27cfaaa7d43f9a2d2ad0b6562cced433e5b04e31/scipy-1.13.1-cp310-cp310-win_amd64.whl", hash = "sha256:2831f0dc9c5ea9edd6e51e6e769b655f08ec6db6e2e10f86ef39bd32eb11da54", size = 46210588 }, + { url = "https://files.pythonhosted.org/packages/b4/15/4a4bb1b15bbd2cd2786c4f46e76b871b28799b67891f23f455323a0cdcfb/scipy-1.13.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:27e52b09c0d3a1d5b63e1105f24177e544a222b43611aaf5bc44d4a0979e32f9", size = 39333805 }, + { url = "https://files.pythonhosted.org/packages/ba/92/42476de1af309c27710004f5cdebc27bec62c204db42e05b23a302cb0c9a/scipy-1.13.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:54f430b00f0133e2224c3ba42b805bfd0086fe488835effa33fa291561932326", size = 30317687 }, + { url = "https://files.pythonhosted.org/packages/80/ba/8be64fe225360a4beb6840f3cbee494c107c0887f33350d0a47d55400b01/scipy-1.13.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e89369d27f9e7b0884ae559a3a956e77c02114cc60a6058b4e5011572eea9299", size = 33694638 }, + { url = "https://files.pythonhosted.org/packages/36/07/035d22ff9795129c5a847c64cb43c1fa9188826b59344fee28a3ab02e283/scipy-1.13.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a78b4b3345f1b6f68a763c6e25c0c9a23a9fd0f39f5f3d200efe8feda560a5fa", size = 38569931 }, + { url = "https://files.pythonhosted.org/packages/d9/10/f9b43de37e5ed91facc0cfff31d45ed0104f359e4f9a68416cbf4e790241/scipy-1.13.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:45484bee6d65633752c490404513b9ef02475b4284c4cfab0ef946def50b3f59", size = 38838145 }, + { url = "https://files.pythonhosted.org/packages/4a/48/4513a1a5623a23e95f94abd675ed91cfb19989c58e9f6f7d03990f6caf3d/scipy-1.13.1-cp311-cp311-win_amd64.whl", hash = "sha256:5713f62f781eebd8d597eb3f88b8bf9274e79eeabf63afb4a737abc6c84ad37b", size = 46196227 }, + { url = "https://files.pythonhosted.org/packages/f2/7b/fb6b46fbee30fc7051913068758414f2721003a89dd9a707ad49174e3843/scipy-1.13.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5d72782f39716b2b3509cd7c33cdc08c96f2f4d2b06d51e52fb45a19ca0c86a1", size = 39357301 }, + { url = "https://files.pythonhosted.org/packages/dc/5a/2043a3bde1443d94014aaa41e0b50c39d046dda8360abd3b2a1d3f79907d/scipy-1.13.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:017367484ce5498445aade74b1d5ab377acdc65e27095155e448c88497755a5d", size = 30363348 }, + { url = "https://files.pythonhosted.org/packages/e7/cb/26e4a47364bbfdb3b7fb3363be6d8a1c543bcd70a7753ab397350f5f189a/scipy-1.13.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:949ae67db5fa78a86e8fa644b9a6b07252f449dcf74247108c50e1d20d2b4627", size = 33406062 }, + { url = "https://files.pythonhosted.org/packages/88/ab/6ecdc526d509d33814835447bbbeedbebdec7cca46ef495a61b00a35b4bf/scipy-1.13.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de3ade0e53bc1f21358aa74ff4830235d716211d7d077e340c7349bc3542e884", size = 38218311 }, + { url = "https://files.pythonhosted.org/packages/0b/00/9f54554f0f8318100a71515122d8f4f503b1a2c4b4cfab3b4b68c0eb08fa/scipy-1.13.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2ac65fb503dad64218c228e2dc2d0a0193f7904747db43014645ae139c8fad16", size = 38442493 }, + { url = "https://files.pythonhosted.org/packages/3e/df/963384e90733e08eac978cd103c34df181d1fec424de383cdc443f418dd4/scipy-1.13.1-cp312-cp312-win_amd64.whl", hash = "sha256:cdd7dacfb95fea358916410ec61bbc20440f7860333aee6d882bb8046264e949", size = 45910955 }, + { url = "https://files.pythonhosted.org/packages/7f/29/c2ea58c9731b9ecb30b6738113a95d147e83922986b34c685b8f6eefde21/scipy-1.13.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:436bbb42a94a8aeef855d755ce5a465479c721e9d684de76bf61a62e7c2b81d5", size = 39352927 }, + { url = "https://files.pythonhosted.org/packages/5c/c0/e71b94b20ccf9effb38d7147c0064c08c622309fd487b1b677771a97d18c/scipy-1.13.1-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:8335549ebbca860c52bf3d02f80784e91a004b71b059e3eea9678ba994796a24", size = 30324538 }, + { url = "https://files.pythonhosted.org/packages/6d/0f/aaa55b06d474817cea311e7b10aab2ea1fd5d43bc6a2861ccc9caec9f418/scipy-1.13.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d533654b7d221a6a97304ab63c41c96473ff04459e404b83275b60aa8f4b7004", size = 33732190 }, + { url = "https://files.pythonhosted.org/packages/35/f5/d0ad1a96f80962ba65e2ce1de6a1e59edecd1f0a7b55990ed208848012e0/scipy-1.13.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:637e98dcf185ba7f8e663e122ebf908c4702420477ae52a04f9908707456ba4d", size = 38612244 }, + { url = "https://files.pythonhosted.org/packages/8d/02/1165905f14962174e6569076bcc3315809ae1291ed14de6448cc151eedfd/scipy-1.13.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a014c2b3697bde71724244f63de2476925596c24285c7a637364761f8710891c", size = 38845637 }, + { url = "https://files.pythonhosted.org/packages/3e/77/dab54fe647a08ee4253963bcd8f9cf17509c8ca64d6335141422fe2e2114/scipy-1.13.1-cp39-cp39-win_amd64.whl", hash = "sha256:392e4ec766654852c25ebad4f64e4e584cf19820b980bc04960bca0b0cd6eaa2", size = 46227440 }, +] + +[[package]] +name = "scipy" +version = "1.15.2" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.12'", + "python_full_version == '3.11.*'", + "python_full_version == '3.10.*'", +] +dependencies = [ + { name = "numpy", marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b7/b9/31ba9cd990e626574baf93fbc1ac61cf9ed54faafd04c479117517661637/scipy-1.15.2.tar.gz", hash = "sha256:cd58a314d92838f7e6f755c8a2167ead4f27e1fd5c1251fd54289569ef3495ec", size = 59417316 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/95/df/ef233fff6838fe6f7840d69b5ef9f20d2b5c912a8727b21ebf876cb15d54/scipy-1.15.2-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:a2ec871edaa863e8213ea5df811cd600734f6400b4af272e1c011e69401218e9", size = 38692502 }, + { url = "https://files.pythonhosted.org/packages/5c/20/acdd4efb8a68b842968f7bc5611b1aeb819794508771ad104de418701422/scipy-1.15.2-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:6f223753c6ea76983af380787611ae1291e3ceb23917393079dcc746ba60cfb5", size = 30085508 }, + { url = "https://files.pythonhosted.org/packages/42/55/39cf96ca7126f1e78ee72a6344ebdc6702fc47d037319ad93221063e6cf4/scipy-1.15.2-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:ecf797d2d798cf7c838c6d98321061eb3e72a74710e6c40540f0e8087e3b499e", size = 22359166 }, + { url = "https://files.pythonhosted.org/packages/51/48/708d26a4ab8a1441536bf2dfcad1df0ca14a69f010fba3ccbdfc02df7185/scipy-1.15.2-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:9b18aa747da280664642997e65aab1dd19d0c3d17068a04b3fe34e2559196cb9", size = 25112047 }, + { url = "https://files.pythonhosted.org/packages/dd/65/f9c5755b995ad892020381b8ae11f16d18616208e388621dfacc11df6de6/scipy-1.15.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87994da02e73549dfecaed9e09a4f9d58a045a053865679aeb8d6d43747d4df3", size = 35536214 }, + { url = "https://files.pythonhosted.org/packages/de/3c/c96d904b9892beec978562f64d8cc43f9cca0842e65bd3cd1b7f7389b0ba/scipy-1.15.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69ea6e56d00977f355c0f84eba69877b6df084516c602d93a33812aa04d90a3d", size = 37646981 }, + { url = "https://files.pythonhosted.org/packages/3d/74/c2d8a24d18acdeae69ed02e132b9bc1bb67b7bee90feee1afe05a68f9d67/scipy-1.15.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:888307125ea0c4466287191e5606a2c910963405ce9671448ff9c81c53f85f58", size = 37230048 }, + { url = "https://files.pythonhosted.org/packages/42/19/0aa4ce80eca82d487987eff0bc754f014dec10d20de2f66754fa4ea70204/scipy-1.15.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9412f5e408b397ff5641080ed1e798623dbe1ec0d78e72c9eca8992976fa65aa", size = 40010322 }, + { url = "https://files.pythonhosted.org/packages/d0/d2/f0683b7e992be44d1475cc144d1f1eeae63c73a14f862974b4db64af635e/scipy-1.15.2-cp310-cp310-win_amd64.whl", hash = "sha256:b5e025e903b4f166ea03b109bb241355b9c42c279ea694d8864d033727205e65", size = 41233385 }, + { url = "https://files.pythonhosted.org/packages/40/1f/bf0a5f338bda7c35c08b4ed0df797e7bafe8a78a97275e9f439aceb46193/scipy-1.15.2-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:92233b2df6938147be6fa8824b8136f29a18f016ecde986666be5f4d686a91a4", size = 38703651 }, + { url = "https://files.pythonhosted.org/packages/de/54/db126aad3874601048c2c20ae3d8a433dbfd7ba8381551e6f62606d9bd8e/scipy-1.15.2-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:62ca1ff3eb513e09ed17a5736929429189adf16d2d740f44e53270cc800ecff1", size = 30102038 }, + { url = "https://files.pythonhosted.org/packages/61/d8/84da3fffefb6c7d5a16968fe5b9f24c98606b165bb801bb0b8bc3985200f/scipy-1.15.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:4c6676490ad76d1c2894d77f976144b41bd1a4052107902238047fb6a473e971", size = 22375518 }, + { url = "https://files.pythonhosted.org/packages/44/78/25535a6e63d3b9c4c90147371aedb5d04c72f3aee3a34451f2dc27c0c07f/scipy-1.15.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:a8bf5cb4a25046ac61d38f8d3c3426ec11ebc350246a4642f2f315fe95bda655", size = 25142523 }, + { url = "https://files.pythonhosted.org/packages/e0/22/4b4a26fe1cd9ed0bc2b2cb87b17d57e32ab72c346949eaf9288001f8aa8e/scipy-1.15.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a8e34cf4c188b6dd004654f88586d78f95639e48a25dfae9c5e34a6dc34547e", size = 35491547 }, + { url = "https://files.pythonhosted.org/packages/32/ea/564bacc26b676c06a00266a3f25fdfe91a9d9a2532ccea7ce6dd394541bc/scipy-1.15.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28a0d2c2075946346e4408b211240764759e0fabaeb08d871639b5f3b1aca8a0", size = 37634077 }, + { url = "https://files.pythonhosted.org/packages/43/c2/bfd4e60668897a303b0ffb7191e965a5da4056f0d98acfb6ba529678f0fb/scipy-1.15.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:42dabaaa798e987c425ed76062794e93a243be8f0f20fff6e7a89f4d61cb3d40", size = 37231657 }, + { url = "https://files.pythonhosted.org/packages/4a/75/5f13050bf4f84c931bcab4f4e83c212a36876c3c2244475db34e4b5fe1a6/scipy-1.15.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6f5e296ec63c5da6ba6fa0343ea73fd51b8b3e1a300b0a8cae3ed4b1122c7462", size = 40035857 }, + { url = "https://files.pythonhosted.org/packages/b9/8b/7ec1832b09dbc88f3db411f8cdd47db04505c4b72c99b11c920a8f0479c3/scipy-1.15.2-cp311-cp311-win_amd64.whl", hash = "sha256:597a0c7008b21c035831c39927406c6181bcf8f60a73f36219b69d010aa04737", size = 41217654 }, + { url = "https://files.pythonhosted.org/packages/4b/5d/3c78815cbab499610f26b5bae6aed33e227225a9fa5290008a733a64f6fc/scipy-1.15.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c4697a10da8f8765bb7c83e24a470da5797e37041edfd77fd95ba3811a47c4fd", size = 38756184 }, + { url = "https://files.pythonhosted.org/packages/37/20/3d04eb066b471b6e171827548b9ddb3c21c6bbea72a4d84fc5989933910b/scipy-1.15.2-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:869269b767d5ee7ea6991ed7e22b3ca1f22de73ab9a49c44bad338b725603301", size = 30163558 }, + { url = "https://files.pythonhosted.org/packages/a4/98/e5c964526c929ef1f795d4c343b2ff98634ad2051bd2bbadfef9e772e413/scipy-1.15.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:bad78d580270a4d32470563ea86c6590b465cb98f83d760ff5b0990cb5518a93", size = 22437211 }, + { url = "https://files.pythonhosted.org/packages/1d/cd/1dc7371e29195ecbf5222f9afeedb210e0a75057d8afbd942aa6cf8c8eca/scipy-1.15.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:b09ae80010f52efddb15551025f9016c910296cf70adbf03ce2a8704f3a5ad20", size = 25232260 }, + { url = "https://files.pythonhosted.org/packages/f0/24/1a181a9e5050090e0b5138c5f496fee33293c342b788d02586bc410c6477/scipy-1.15.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5a6fd6eac1ce74a9f77a7fc724080d507c5812d61e72bd5e4c489b042455865e", size = 35198095 }, + { url = "https://files.pythonhosted.org/packages/c0/53/eaada1a414c026673eb983f8b4a55fe5eb172725d33d62c1b21f63ff6ca4/scipy-1.15.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2b871df1fe1a3ba85d90e22742b93584f8d2b8e6124f8372ab15c71b73e428b8", size = 37297371 }, + { url = "https://files.pythonhosted.org/packages/e9/06/0449b744892ed22b7e7b9a1994a866e64895363572677a316a9042af1fe5/scipy-1.15.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:03205d57a28e18dfd39f0377d5002725bf1f19a46f444108c29bdb246b6c8a11", size = 36872390 }, + { url = "https://files.pythonhosted.org/packages/6a/6f/a8ac3cfd9505ec695c1bc35edc034d13afbd2fc1882a7c6b473e280397bb/scipy-1.15.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:601881dfb761311045b03114c5fe718a12634e5608c3b403737ae463c9885d53", size = 39700276 }, + { url = "https://files.pythonhosted.org/packages/f5/6f/e6e5aff77ea2a48dd96808bb51d7450875af154ee7cbe72188afb0b37929/scipy-1.15.2-cp312-cp312-win_amd64.whl", hash = "sha256:e7c68b6a43259ba0aab737237876e5c2c549a031ddb7abc28c7b47f22e202ded", size = 40942317 }, + { url = "https://files.pythonhosted.org/packages/53/40/09319f6e0f276ea2754196185f95cd191cb852288440ce035d5c3a931ea2/scipy-1.15.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:01edfac9f0798ad6b46d9c4c9ca0e0ad23dbf0b1eb70e96adb9fa7f525eff0bf", size = 38717587 }, + { url = "https://files.pythonhosted.org/packages/fe/c3/2854f40ecd19585d65afaef601e5e1f8dbf6758b2f95b5ea93d38655a2c6/scipy-1.15.2-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:08b57a9336b8e79b305a143c3655cc5bdbe6d5ece3378578888d2afbb51c4e37", size = 30100266 }, + { url = "https://files.pythonhosted.org/packages/dd/b1/f9fe6e3c828cb5930b5fe74cb479de5f3d66d682fa8adb77249acaf545b8/scipy-1.15.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:54c462098484e7466362a9f1672d20888f724911a74c22ae35b61f9c5919183d", size = 22373768 }, + { url = "https://files.pythonhosted.org/packages/15/9d/a60db8c795700414c3f681908a2b911e031e024d93214f2d23c6dae174ab/scipy-1.15.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:cf72ff559a53a6a6d77bd8eefd12a17995ffa44ad86c77a5df96f533d4e6c6bb", size = 25154719 }, + { url = "https://files.pythonhosted.org/packages/37/3b/9bda92a85cd93f19f9ed90ade84aa1e51657e29988317fabdd44544f1dd4/scipy-1.15.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9de9d1416b3d9e7df9923ab23cd2fe714244af10b763975bea9e4f2e81cebd27", size = 35163195 }, + { url = "https://files.pythonhosted.org/packages/03/5a/fc34bf1aa14dc7c0e701691fa8685f3faec80e57d816615e3625f28feb43/scipy-1.15.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb530e4794fc8ea76a4a21ccb67dea33e5e0e60f07fc38a49e821e1eae3b71a0", size = 37255404 }, + { url = "https://files.pythonhosted.org/packages/4a/71/472eac45440cee134c8a180dbe4c01b3ec247e0338b7c759e6cd71f199a7/scipy-1.15.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5ea7ed46d437fc52350b028b1d44e002646e28f3e8ddc714011aaf87330f2f32", size = 36860011 }, + { url = "https://files.pythonhosted.org/packages/01/b3/21f890f4f42daf20e4d3aaa18182dddb9192771cd47445aaae2e318f6738/scipy-1.15.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:11e7ad32cf184b74380f43d3c0a706f49358b904fa7d5345f16ddf993609184d", size = 39657406 }, + { url = "https://files.pythonhosted.org/packages/0d/76/77cf2ac1f2a9cc00c073d49e1e16244e389dd88e2490c91d84e1e3e4d126/scipy-1.15.2-cp313-cp313-win_amd64.whl", hash = "sha256:a5080a79dfb9b78b768cebf3c9dcbc7b665c5875793569f48bf0e2b1d7f68f6f", size = 40961243 }, + { url = "https://files.pythonhosted.org/packages/4c/4b/a57f8ddcf48e129e6054fa9899a2a86d1fc6b07a0e15c7eebff7ca94533f/scipy-1.15.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:447ce30cee6a9d5d1379087c9e474628dab3db4a67484be1b7dc3196bfb2fac9", size = 38870286 }, + { url = "https://files.pythonhosted.org/packages/0c/43/c304d69a56c91ad5f188c0714f6a97b9c1fed93128c691148621274a3a68/scipy-1.15.2-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:c90ebe8aaa4397eaefa8455a8182b164a6cc1d59ad53f79943f266d99f68687f", size = 30141634 }, + { url = "https://files.pythonhosted.org/packages/44/1a/6c21b45d2548eb73be9b9bff421aaaa7e85e22c1f9b3bc44b23485dfce0a/scipy-1.15.2-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:def751dd08243934c884a3221156d63e15234a3155cf25978b0a668409d45eb6", size = 22415179 }, + { url = "https://files.pythonhosted.org/packages/74/4b/aefac4bba80ef815b64f55da06f62f92be5d03b467f2ce3668071799429a/scipy-1.15.2-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:302093e7dfb120e55515936cb55618ee0b895f8bcaf18ff81eca086c17bd80af", size = 25126412 }, + { url = "https://files.pythonhosted.org/packages/b1/53/1cbb148e6e8f1660aacd9f0a9dfa2b05e9ff1cb54b4386fe868477972ac2/scipy-1.15.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7cd5b77413e1855351cdde594eca99c1f4a588c2d63711388b6a1f1c01f62274", size = 34952867 }, + { url = "https://files.pythonhosted.org/packages/2c/23/e0eb7f31a9c13cf2dca083828b97992dd22f8184c6ce4fec5deec0c81fcf/scipy-1.15.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d0194c37037707b2afa7a2f2a924cf7bac3dc292d51b6a925e5fcb89bc5c776", size = 36890009 }, + { url = "https://files.pythonhosted.org/packages/03/f3/e699e19cabe96bbac5189c04aaa970718f0105cff03d458dc5e2b6bd1e8c/scipy-1.15.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:bae43364d600fdc3ac327db99659dcb79e6e7ecd279a75fe1266669d9a652828", size = 36545159 }, + { url = "https://files.pythonhosted.org/packages/af/f5/ab3838e56fe5cc22383d6fcf2336e48c8fe33e944b9037fbf6cbdf5a11f8/scipy-1.15.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f031846580d9acccd0044efd1a90e6f4df3a6e12b4b6bd694a7bc03a89892b28", size = 39136566 }, + { url = "https://files.pythonhosted.org/packages/0a/c8/b3f566db71461cabd4b2d5b39bcc24a7e1c119535c8361f81426be39bb47/scipy-1.15.2-cp313-cp313t-win_amd64.whl", hash = "sha256:fe8a9eb875d430d81755472c5ba75e84acc980e4a8f6204d402849234d3017db", size = 40477705 }, +] + +[[package]] +name = "semantic-version" +version = "2.10.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7d/31/f2289ce78b9b473d582568c234e104d2a342fd658cc288a7553d83bb8595/semantic_version-2.10.0.tar.gz", hash = "sha256:bdabb6d336998cbb378d4b9db3a4b56a1e3235701dc05ea2690d9a997ed5041c", size = 52289 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6a/23/8146aad7d88f4fcb3a6218f41a60f6c2d4e3a72de72da1825dc7c8f7877c/semantic_version-2.10.0-py2.py3-none-any.whl", hash = "sha256:de78a3b8e0feda74cabc54aab2da702113e33ac9d9eb9d2389bcf1f58b7d9177", size = 15552 }, +] + +[[package]] +name = "setuptools" +version = "80.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/70/dc/3976b322de9d2e87ed0007cf04cc7553969b6c7b3f48a565d0333748fbcd/setuptools-80.3.1.tar.gz", hash = "sha256:31e2c58dbb67c99c289f51c16d899afedae292b978f8051efaf6262d8212f927", size = 1315082 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/53/7e/5d8af3317ddbf9519b687bd1c39d8737fde07d97f54df65553faca5cffb1/setuptools-80.3.1-py3-none-any.whl", hash = "sha256:ea8e00d7992054c4c592aeb892f6ad51fe1b4d90cc6947cc45c45717c40ec537", size = 1201172 }, +] + +[[package]] +name = "setuptools-rust" +version = "1.11.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "semantic-version" }, + { name = "setuptools" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e0/92/bf8589b1a2b6107cf9ec8daa9954c0b7620643fe1f37d31d75e572d995f5/setuptools_rust-1.11.1.tar.gz", hash = "sha256:7dabc4392252ced314b8050d63276e05fdc5d32398fc7d3cce1f6a6ac35b76c0", size = 310804 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/01/37e1376f80578882e4f2d451f57d1fb42a599832057a123f57d9f26395c8/setuptools_rust-1.11.1-py3-none-any.whl", hash = "sha256:5eaaddaed268dc24a527ffa659ce56b22d3cf17b781247b779efd611031fe8ea", size = 28120 }, +] + +[[package]] +name = "simplejson" +version = "3.20.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/af/92/51b417685abd96b31308b61b9acce7ec50d8e1de8fbc39a7fd4962c60689/simplejson-3.20.1.tar.gz", hash = "sha256:e64139b4ec4f1f24c142ff7dcafe55a22b811a74d86d66560c8815687143037d", size = 85591 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/25/c4/627214fb418cd4a17fb0230ff0b6c3bb4a85cbb48dd69c85dcc3b85df828/simplejson-3.20.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e580aa65d5f6c3bf41b9b4afe74be5d5ddba9576701c107c772d936ea2b5043a", size = 93790 }, + { url = "https://files.pythonhosted.org/packages/15/ca/56a6a2a33cbcf330c4d71af3f827c47e4e0ba791e78f2642f3d1ab02ff31/simplejson-3.20.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4a586ce4f78cec11f22fe55c5bee0f067e803aab9bad3441afe2181693b5ebb5", size = 75707 }, + { url = "https://files.pythonhosted.org/packages/a9/c8/3d92b67e03a3b6207d97202669f9454ed700b35ade9bd4428265a078fb6c/simplejson-3.20.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:74a1608f9e6e8c27a4008d70a54270868306d80ed48c9df7872f9f4b8ac87808", size = 75700 }, + { url = "https://files.pythonhosted.org/packages/74/30/20001219d6fdca4aaa3974c96dfb6955a766b4e2cc950505a5b51fd050b0/simplejson-3.20.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:03db8cb64154189a92a7786209f24e391644f3a3fa335658be2df2af1960b8d8", size = 138672 }, + { url = "https://files.pythonhosted.org/packages/21/47/50157810876c2a7ebbd6e6346ec25eda841fe061fecaa02538a7742a3d2a/simplejson-3.20.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eea7e2b7d858f6fdfbf0fe3cb846d6bd8a45446865bc09960e51f3d473c2271b", size = 146616 }, + { url = "https://files.pythonhosted.org/packages/95/60/8c97cdc93096437b0aca2745aca63c880fe2315fd7f6a6ce6edbb344a2ae/simplejson-3.20.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e66712b17d8425bb7ff8968d4c7c7fd5a2dd7bd63728b28356223c000dd2f91f", size = 134344 }, + { url = "https://files.pythonhosted.org/packages/bb/9e/da184f0e9bb3a5d7ffcde713bd41b4fe46cca56b6f24d9bd155fac56805a/simplejson-3.20.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2cc4f6486f9f515b62f5831ff1888886619b84fc837de68f26d919ba7bbdcbc", size = 138017 }, + { url = "https://files.pythonhosted.org/packages/31/db/00d1a8d9b036db98f678c8a3c69ed17d2894d1768d7a00576e787ad3e546/simplejson-3.20.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a3c2df555ee4016148fa192e2b9cd9e60bc1d40769366134882685e90aee2a1e", size = 140118 }, + { url = "https://files.pythonhosted.org/packages/52/21/57fc47eab8c1c73390b933a5ba9271f08e3e1ec83162c580357f28f5b97c/simplejson-3.20.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:78520f04b7548a5e476b5396c0847e066f1e0a4c0c5e920da1ad65e95f410b11", size = 140314 }, + { url = "https://files.pythonhosted.org/packages/ad/cc/7cfd78d1e0fa5e57350b98cfe77353b6dfa13dce21afa4060e1019223852/simplejson-3.20.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:f4bd49ecde87b0fe9f55cc971449a32832bca9910821f7072bbfae1155eaa007", size = 148544 }, + { url = "https://files.pythonhosted.org/packages/63/26/1c894a1c2bd95dc8be0cf5a2fa73b0d173105b6ca18c90cb981ff10443d0/simplejson-3.20.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7eaae2b88eb5da53caaffdfa50e2e12022553949b88c0df4f9a9663609373f72", size = 141172 }, + { url = "https://files.pythonhosted.org/packages/93/27/0717dccc10cd9988dbf1314def52ab32678a95a95328bb37cafacf499400/simplejson-3.20.1-cp310-cp310-win32.whl", hash = "sha256:e836fb88902799eac8debc2b642300748f4860a197fa3d9ea502112b6bb8e142", size = 74181 }, + { url = "https://files.pythonhosted.org/packages/5f/af/593f896573f306519332d4287b1ab8b7b888c239bbd5159f7054d7055c2d/simplejson-3.20.1-cp310-cp310-win_amd64.whl", hash = "sha256:b122a19b552b212fc3b5b96fc5ce92333d4a9ac0a800803e1f17ebb16dac4be5", size = 75738 }, + { url = "https://files.pythonhosted.org/packages/76/59/74bc90d1c051bc2432c96b34bd4e8036875ab58b4fcbe4d6a5a76985f853/simplejson-3.20.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:325b8c107253d3217e89d7b50c71015b5b31e2433e6c5bf38967b2f80630a8ca", size = 92132 }, + { url = "https://files.pythonhosted.org/packages/71/c7/1970916e0c51794fff89f76da2f632aaf0b259b87753c88a8c409623d3e1/simplejson-3.20.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:88a7baa8211089b9e58d78fbc1b0b322103f3f3d459ff16f03a36cece0d0fcf0", size = 74956 }, + { url = "https://files.pythonhosted.org/packages/c8/0d/98cc5909180463f1d75fac7180de62d4cdb4e82c4fef276b9e591979372c/simplejson-3.20.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:299b1007b8101d50d95bc0db1bf5c38dc372e85b504cf77f596462083ee77e3f", size = 74772 }, + { url = "https://files.pythonhosted.org/packages/e1/94/a30a5211a90d67725a3e8fcc1c788189f2ae2ed2b96b63ed15d0b7f5d6bb/simplejson-3.20.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:03ec618ed65caab48e81e3ed29586236a8e57daef792f1f3bb59504a7e98cd10", size = 143575 }, + { url = "https://files.pythonhosted.org/packages/ee/08/cdb6821f1058eb5db46d252de69ff7e6c53f05f1bae6368fe20d5b51d37e/simplejson-3.20.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd2cdead1d3197f0ff43373cf4730213420523ba48697743e135e26f3d179f38", size = 153241 }, + { url = "https://files.pythonhosted.org/packages/4c/2d/ca3caeea0bdc5efc5503d5f57a2dfb56804898fb196dfada121323ee0ccb/simplejson-3.20.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3466d2839fdc83e1af42e07b90bc8ff361c4e8796cd66722a40ba14e458faddd", size = 141500 }, + { url = "https://files.pythonhosted.org/packages/e1/33/d3e0779d5c58245e7370c98eb969275af6b7a4a5aec3b97cbf85f09ad328/simplejson-3.20.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d492ed8e92f3a9f9be829205f44b1d0a89af6582f0cf43e0d129fa477b93fe0c", size = 144757 }, + { url = "https://files.pythonhosted.org/packages/54/53/2d93128bb55861b2fa36c5944f38da51a0bc6d83e513afc6f7838440dd15/simplejson-3.20.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f924b485537b640dc69434565463fd6fc0c68c65a8c6e01a823dd26c9983cf79", size = 144409 }, + { url = "https://files.pythonhosted.org/packages/99/4c/dac310a98f897ad3435b4bdc836d92e78f09e38c5dbf28211ed21dc59fa2/simplejson-3.20.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:9e8eacf6a3491bf76ea91a8d46726368a6be0eb94993f60b8583550baae9439e", size = 146082 }, + { url = "https://files.pythonhosted.org/packages/ee/22/d7ba958cfed39827335b82656b1c46f89678faecda9a7677b47e87b48ee6/simplejson-3.20.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:d34d04bf90b4cea7c22d8b19091633908f14a096caa301b24c2f3d85b5068fb8", size = 154339 }, + { url = "https://files.pythonhosted.org/packages/b8/c8/b072b741129406a7086a0799c6f5d13096231bf35fdd87a0cffa789687fc/simplejson-3.20.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:69dd28d4ce38390ea4aaf212902712c0fd1093dc4c1ff67e09687c3c3e15a749", size = 147915 }, + { url = "https://files.pythonhosted.org/packages/6c/46/8347e61e9cf3db5342a42f7fd30a81b4f5cf85977f916852d7674a540907/simplejson-3.20.1-cp311-cp311-win32.whl", hash = "sha256:dfe7a9da5fd2a3499436cd350f31539e0a6ded5da6b5b3d422df016444d65e43", size = 73972 }, + { url = "https://files.pythonhosted.org/packages/01/85/b52f24859237b4e9d523d5655796d911ba3d46e242eb1959c45b6af5aedd/simplejson-3.20.1-cp311-cp311-win_amd64.whl", hash = "sha256:896a6c04d7861d507d800da7642479c3547060bf97419d9ef73d98ced8258766", size = 75595 }, + { url = "https://files.pythonhosted.org/packages/8d/eb/34c16a1ac9ba265d024dc977ad84e1659d931c0a700967c3e59a98ed7514/simplejson-3.20.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f31c4a3a7ab18467ee73a27f3e59158255d1520f3aad74315edde7a940f1be23", size = 93100 }, + { url = "https://files.pythonhosted.org/packages/41/fc/2c2c007d135894971e6814e7c0806936e5bade28f8db4dd7e2a58b50debd/simplejson-3.20.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:884e6183d16b725e113b83a6fc0230152ab6627d4d36cb05c89c2c5bccfa7bc6", size = 75464 }, + { url = "https://files.pythonhosted.org/packages/0f/05/2b5ecb33b776c34bb5cace5de5d7669f9b60e3ca13c113037b2ca86edfbd/simplejson-3.20.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:03d7a426e416fe0d3337115f04164cd9427eb4256e843a6b8751cacf70abc832", size = 75112 }, + { url = "https://files.pythonhosted.org/packages/fe/36/1f3609a2792f06cd4b71030485f78e91eb09cfd57bebf3116bf2980a8bac/simplejson-3.20.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:000602141d0bddfcff60ea6a6e97d5e10c9db6b17fd2d6c66199fa481b6214bb", size = 150182 }, + { url = "https://files.pythonhosted.org/packages/2f/b0/053fbda38b8b602a77a4f7829def1b4f316cd8deb5440a6d3ee90790d2a4/simplejson-3.20.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:af8377a8af78226e82e3a4349efdde59ffa421ae88be67e18cef915e4023a595", size = 158363 }, + { url = "https://files.pythonhosted.org/packages/d1/4b/2eb84ae867539a80822e92f9be4a7200dffba609275faf99b24141839110/simplejson-3.20.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:15c7de4c88ab2fbcb8781a3b982ef883696736134e20b1210bca43fb42ff1acf", size = 148415 }, + { url = "https://files.pythonhosted.org/packages/e0/bd/400b0bd372a5666addf2540c7358bfc3841b9ce5cdbc5cc4ad2f61627ad8/simplejson-3.20.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:455a882ff3f97d810709f7b620007d4e0aca8da71d06fc5c18ba11daf1c4df49", size = 152213 }, + { url = "https://files.pythonhosted.org/packages/50/12/143f447bf6a827ee9472693768dc1a5eb96154f8feb140a88ce6973a3cfa/simplejson-3.20.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:fc0f523ce923e7f38eb67804bc80e0a028c76d7868500aa3f59225574b5d0453", size = 150048 }, + { url = "https://files.pythonhosted.org/packages/5e/ea/dd9b3e8e8ed710a66f24a22c16a907c9b539b6f5f45fd8586bd5c231444e/simplejson-3.20.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:76461ec929282dde4a08061071a47281ad939d0202dc4e63cdd135844e162fbc", size = 151668 }, + { url = "https://files.pythonhosted.org/packages/99/af/ee52a8045426a0c5b89d755a5a70cc821815ef3c333b56fbcad33c4435c0/simplejson-3.20.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:ab19c2da8c043607bde4d4ef3a6b633e668a7d2e3d56f40a476a74c5ea71949f", size = 158840 }, + { url = "https://files.pythonhosted.org/packages/68/db/ab32869acea6b5de7d75fa0dac07a112ded795d41eaa7e66c7813b17be95/simplejson-3.20.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b2578bedaedf6294415197b267d4ef678fea336dd78ee2a6d2f4b028e9d07be3", size = 154212 }, + { url = "https://files.pythonhosted.org/packages/fa/7a/e3132d454977d75a3bf9a6d541d730f76462ebf42a96fea2621498166f41/simplejson-3.20.1-cp312-cp312-win32.whl", hash = "sha256:339f407373325a36b7fd744b688ba5bae0666b5d340ec6d98aebc3014bf3d8ea", size = 74101 }, + { url = "https://files.pythonhosted.org/packages/bc/5d/4e243e937fa3560107c69f6f7c2eed8589163f5ed14324e864871daa2dd9/simplejson-3.20.1-cp312-cp312-win_amd64.whl", hash = "sha256:627d4486a1ea7edf1f66bb044ace1ce6b4c1698acd1b05353c97ba4864ea2e17", size = 75736 }, + { url = "https://files.pythonhosted.org/packages/c4/03/0f453a27877cb5a5fff16a975925f4119102cc8552f52536b9a98ef0431e/simplejson-3.20.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:71e849e7ceb2178344998cbe5ade101f1b329460243c79c27fbfc51c0447a7c3", size = 93109 }, + { url = "https://files.pythonhosted.org/packages/74/1f/a729f4026850cabeaff23e134646c3f455e86925d2533463420635ae54de/simplejson-3.20.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b63fdbab29dc3868d6f009a59797cefaba315fd43cd32ddd998ee1da28e50e29", size = 75475 }, + { url = "https://files.pythonhosted.org/packages/e2/14/50a2713fee8ff1f8d655b1a14f4a0f1c0c7246768a1b3b3d12964a4ed5aa/simplejson-3.20.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1190f9a3ce644fd50ec277ac4a98c0517f532cfebdcc4bd975c0979a9f05e1fb", size = 75112 }, + { url = "https://files.pythonhosted.org/packages/45/86/ea9835abb646755140e2d482edc9bc1e91997ed19a59fd77ae4c6a0facea/simplejson-3.20.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1336ba7bcb722ad487cd265701ff0583c0bb6de638364ca947bb84ecc0015d1", size = 150245 }, + { url = "https://files.pythonhosted.org/packages/12/b4/53084809faede45da829fe571c65fbda8479d2a5b9c633f46b74124d56f5/simplejson-3.20.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e975aac6a5acd8b510eba58d5591e10a03e3d16c1cf8a8624ca177491f7230f0", size = 158465 }, + { url = "https://files.pythonhosted.org/packages/a9/7d/d56579468d1660b3841e1f21c14490d103e33cf911886b22652d6e9683ec/simplejson-3.20.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6a6dd11ee282937ad749da6f3b8d87952ad585b26e5edfa10da3ae2536c73078", size = 148514 }, + { url = "https://files.pythonhosted.org/packages/19/e3/874b1cca3d3897b486d3afdccc475eb3a09815bf1015b01cf7fcb52a55f0/simplejson-3.20.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab980fcc446ab87ea0879edad41a5c28f2d86020014eb035cf5161e8de4474c6", size = 152262 }, + { url = "https://files.pythonhosted.org/packages/32/84/f0fdb3625292d945c2bd13a814584603aebdb38cfbe5fe9be6b46fe598c4/simplejson-3.20.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f5aee2a4cb6b146bd17333ac623610f069f34e8f31d2f4f0c1a2186e50c594f0", size = 150164 }, + { url = "https://files.pythonhosted.org/packages/95/51/6d625247224f01eaaeabace9aec75ac5603a42f8ebcce02c486fbda8b428/simplejson-3.20.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:652d8eecbb9a3b6461b21ec7cf11fd0acbab144e45e600c817ecf18e4580b99e", size = 151795 }, + { url = "https://files.pythonhosted.org/packages/7f/d9/bb921df6b35be8412f519e58e86d1060fddf3ad401b783e4862e0a74c4c1/simplejson-3.20.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:8c09948f1a486a89251ee3a67c9f8c969b379f6ffff1a6064b41fea3bce0a112", size = 159027 }, + { url = "https://files.pythonhosted.org/packages/03/c5/5950605e4ad023a6621cf4c931b29fd3d2a9c1f36be937230bfc83d7271d/simplejson-3.20.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:cbbd7b215ad4fc6f058b5dd4c26ee5c59f72e031dfda3ac183d7968a99e4ca3a", size = 154380 }, + { url = "https://files.pythonhosted.org/packages/66/ad/b74149557c5ec1e4e4d55758bda426f5d2ec0123cd01a53ae63b8de51fa3/simplejson-3.20.1-cp313-cp313-win32.whl", hash = "sha256:ae81e482476eaa088ef9d0120ae5345de924f23962c0c1e20abbdff597631f87", size = 74102 }, + { url = "https://files.pythonhosted.org/packages/db/a9/25282fdd24493e1022f30b7f5cdf804255c007218b2bfaa655bd7ad34b2d/simplejson-3.20.1-cp313-cp313-win_amd64.whl", hash = "sha256:1b9fd15853b90aec3b1739f4471efbf1ac05066a2c7041bf8db821bb73cd2ddc", size = 75736 }, + { url = "https://files.pythonhosted.org/packages/4c/ba/d32fe890a5edaf4a8518adf043bccf7866b600123f512a6de0988cf36810/simplejson-3.20.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a8011f1dd1d676befcd4d675ebdbfdbbefd3bf350052b956ba8c699fca7d8cef", size = 93773 }, + { url = "https://files.pythonhosted.org/packages/48/c7/361e7f6695b56001a04e0a5cc623cd6c82ea2f45e872e61213e405cc8a24/simplejson-3.20.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e91703a4c5fec53e36875ae426ad785f4120bd1d93b65bed4752eeccd1789e0c", size = 75697 }, + { url = "https://files.pythonhosted.org/packages/3c/2f/d0ff0b772d4ef092876eb85c99bc591c446b0502715551dad7dfc7f7c2c0/simplejson-3.20.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e39eaa57c7757daa25bcd21f976c46be443b73dd6c3da47fe5ce7b7048ccefe2", size = 75692 }, + { url = "https://files.pythonhosted.org/packages/26/94/cab4db9530b6ca9d62f16a260e8311b04130ccd670dab75e958fcb44590e/simplejson-3.20.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ceab2ce2acdc7fbaa433a93006758db6ba9a659e80c4faa13b80b9d2318e9b17", size = 138106 }, + { url = "https://files.pythonhosted.org/packages/40/22/11c0f746bdb44c297cea8a37d8f7ccb75ea6681132aadfb9f820d9a52647/simplejson-3.20.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6d4f320c33277a5b715db5bf5b10dae10c19076bd6d66c2843e04bd12d1f1ea5", size = 146242 }, + { url = "https://files.pythonhosted.org/packages/78/e9/b7c4c26f29b41cc41ba5f0224c47adbfa7f28427418edfd58ab122f3b584/simplejson-3.20.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b6436c48e64378fa844d8c9e58a5ed0352bbcfd4028369a9b46679b7ab79d2d", size = 133866 }, + { url = "https://files.pythonhosted.org/packages/09/68/1e81ed83f38906c8859f2b973afb19302357d6003e724a6105cee0f61ec7/simplejson-3.20.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e18345c8dda5d699be8166b61f9d80aaee4545b709f1363f60813dc032dac53", size = 137444 }, + { url = "https://files.pythonhosted.org/packages/9a/6b/8d1e076c543277c1d603230eec24f4dd75ebce46d351c0679526d202981f/simplejson-3.20.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:90b573693d1526bed576f6817e2a492eaaef68f088b57d7a9e83d122bbb49e51", size = 139617 }, + { url = "https://files.pythonhosted.org/packages/d1/46/7b74803de10d4157c5cd2e89028897fa733374667bc5520a44b23b6c887a/simplejson-3.20.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:272cc767826e924a6bd369ea3dbf18e166ded29059c7a4d64d21a9a22424b5b5", size = 139725 }, + { url = "https://files.pythonhosted.org/packages/4b/8f/9991582665a7b6d95415e439bb4fbaa4faf0f77231666675a0fd1de54107/simplejson-3.20.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:51b41f284d603c4380732d7d619f8b34bd04bc4aa0ed0ed5f4ffd0539b14da44", size = 148010 }, + { url = "https://files.pythonhosted.org/packages/54/ee/3c6e91989cdf65ec75e75662d9f15cfe167a792b893806169ea5b1da6fd2/simplejson-3.20.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:6e6697a3067d281f01de0fe96fc7cba4ea870d96d7deb7bfcf85186d74456503", size = 140624 }, + { url = "https://files.pythonhosted.org/packages/9d/bd/05e13ebb7ead81c8b555f4ccc741ea7dfa0ef5c2a0c183d6a7bc50a02bca/simplejson-3.20.1-cp39-cp39-win32.whl", hash = "sha256:6dd3a1d5aca87bf947f3339b0f8e8e329f1badf548bdbff37fac63c17936da8e", size = 74148 }, + { url = "https://files.pythonhosted.org/packages/88/c9/d8bf87aaebec5a4c3ccfd5228689578e2fe77027d6114a259255d54969bf/simplejson-3.20.1-cp39-cp39-win_amd64.whl", hash = "sha256:463f1fca8fbf23d088e5850fdd0dd4d5faea8900a9f9680270bd98fd649814ca", size = 75732 }, + { url = "https://files.pythonhosted.org/packages/4b/30/00f02a0a921556dd5a6db1ef2926a1bc7a8bbbfb1c49cfed68a275b8ab2b/simplejson-3.20.1-py3-none-any.whl", hash = "sha256:8a6c1bbac39fa4a79f83cbf1df6ccd8ff7069582a9fd8db1e52cea073bc2c697", size = 57121 }, +] + +[[package]] +name = "six" +version = "1.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050 }, +] + +[[package]] +name = "sniffio" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 }, +] + +[[package]] +name = "sortedcontainers" +version = "2.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e8/c4/ba2f8066cceb6f23394729afe52f3bf7adec04bf9ed2c820b39e19299111/sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88", size = 30594 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0", size = 29575 }, +] + +[[package]] +name = "sympy" +version = "1.14.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mpmath" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/83/d3/803453b36afefb7c2bb238361cd4ae6125a569b4db67cd9e79846ba2d68c/sympy-1.14.0.tar.gz", hash = "sha256:d3d3fe8df1e5a0b42f0e7bdf50541697dbe7d23746e894990c030e2b05e72517", size = 7793921 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl", hash = "sha256:e091cc3e99d2141a0ba2847328f5479b05d94a6635cb96148ccb3f34671bd8f5", size = 6299353 }, +] + +[[package]] +name = "tensorboard" +version = "2.18.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "absl-py" }, + { name = "grpcio" }, + { name = "markdown" }, + { name = "numpy" }, + { name = "packaging" }, + { name = "protobuf" }, + { name = "setuptools" }, + { name = "six" }, + { name = "tensorboard-data-server" }, + { name = "werkzeug" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/b1/de/021c1d407befb505791764ad2cbd56ceaaa53a746baed01d2e2143f05f18/tensorboard-2.18.0-py3-none-any.whl", hash = "sha256:107ca4821745f73e2aefa02c50ff70a9b694f39f790b11e6f682f7d326745eab", size = 5503036 }, +] + +[[package]] +name = "tensorboard-data-server" +version = "0.7.2" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7a/13/e503968fefabd4c6b2650af21e110aa8466fe21432cd7c43a84577a89438/tensorboard_data_server-0.7.2-py3-none-any.whl", hash = "sha256:7e0610d205889588983836ec05dc098e80f97b7e7bbff7e994ebb78f578d0ddb", size = 2356 }, + { url = "https://files.pythonhosted.org/packages/b7/85/dabeaf902892922777492e1d253bb7e1264cadce3cea932f7ff599e53fea/tensorboard_data_server-0.7.2-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:9fe5d24221b29625dbc7328b0436ca7fc1c23de4acf4d272f1180856e32f9f60", size = 4823598 }, + { url = "https://files.pythonhosted.org/packages/73/c6/825dab04195756cf8ff2e12698f22513b3db2f64925bdd41671bfb33aaa5/tensorboard_data_server-0.7.2-py3-none-manylinux_2_31_x86_64.whl", hash = "sha256:ef687163c24185ae9754ed5650eb5bc4d84ff257aabdc33f0cc6f74d8ba54530", size = 6590363 }, +] + +[[package]] +name = "tensorflow" +version = "2.18.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "absl-py" }, + { name = "astunparse" }, + { name = "flatbuffers" }, + { name = "gast" }, + { name = "google-pasta" }, + { name = "grpcio" }, + { name = "h5py" }, + { name = "keras" }, + { name = "libclang" }, + { name = "ml-dtypes" }, + { name = "numpy" }, + { name = "opt-einsum" }, + { name = "packaging" }, + { name = "protobuf" }, + { name = "requests" }, + { name = "setuptools" }, + { name = "six" }, + { name = "tensorboard" }, + { name = "tensorflow-io-gcs-filesystem", marker = "python_full_version < '3.12'" }, + { name = "termcolor" }, + { name = "typing-extensions" }, + { name = "wrapt" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/e8/d5d54e18ff6fe67c75c3c65415c98ecd31bd0ff7613d47a1390f062993b5/tensorflow-2.18.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:8da90a9388a1f6dd00d626590d2b5810faffbb3e7367f9783d80efff882340ee", size = 239373575 }, + { url = "https://files.pythonhosted.org/packages/5a/58/99ba9d580c218fd866e6044b10915eb415f60af38c03dca6ff2df7f83337/tensorflow-2.18.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:589342fb9bdcab2e9af0f946da4ca97757677e297d934fcdc087e87db99d6353", size = 231677108 }, + { url = "https://files.pythonhosted.org/packages/d4/80/1567ccc375ccda4d28af28c960cca7f709f7c259463ac1436554697e8868/tensorflow-2.18.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1eb77fae50d699442726d1b23c7512c97cd688cc7d857b028683d4535bbf3709", size = 615262200 }, + { url = "https://files.pythonhosted.org/packages/59/63/5ca1b06cf17dda9c52927917a7911612953a7d91865b1288c7f9eac2b53b/tensorflow-2.18.0-cp310-cp310-win_amd64.whl", hash = "sha256:46f5a8b4e6273f488dc069fc3ac2211b23acd3d0437d919349c787fa341baa8a", size = 7519 }, + { url = "https://files.pythonhosted.org/packages/26/08/556c4159675c1a30e077ec2a942eeeb81b457cc35c247a5b4a59a1274f05/tensorflow-2.18.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:453cb60638a02fd26316fb36c8cbcf1569d33671f17c658ca0cf2b4626f851e7", size = 239492146 }, + { url = "https://files.pythonhosted.org/packages/0d/3d/45956345442e3a7b335df6f13d068121d8454c243f31b1f44244705ac584/tensorflow-2.18.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85f1e7369af6d329b117b52e86093cd1e0458dd5404bf5b665853f873dd00b48", size = 231839918 }, + { url = "https://files.pythonhosted.org/packages/84/76/c55967ac9968ddaede25a4dce37aba37e9030656f02c12676151ce1b6f22/tensorflow-2.18.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b8dd70fa3600bfce66ab529eebb804e1f9d7c863d2f71bc8fe9fc7a1ec3976", size = 615407268 }, + { url = "https://files.pythonhosted.org/packages/cf/24/271e77c22724f370c24c705f394b8035b4d27e4c2c6339f3f45ab9b8258e/tensorflow-2.18.0-cp311-cp311-win_amd64.whl", hash = "sha256:6e8b0f499ef0b7652480a58e358a73844932047f21c42c56f7f3bdcaf0803edc", size = 7516 }, + { url = "https://files.pythonhosted.org/packages/dc/bf/4cc283db323fd723f630e2454b2857054d2c81ff5012c1857659e72470f1/tensorflow-2.18.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:ec4133a215c59314e929e7cbe914579d3afbc7874d9fa924873ee633fe4f71d0", size = 239565465 }, + { url = "https://files.pythonhosted.org/packages/56/e4/55aaac2b15af4dad079e5af329a79d961e5206589d0e02b1e8da221472ed/tensorflow-2.18.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4822904b3559d8a9c25f0fe5fef191cfc1352ceca42ca64f2a7bc7ae0ff4a1f5", size = 231898760 }, + { url = "https://files.pythonhosted.org/packages/50/29/61ce80da0bfea3948326697dd1d832d28c863c9dacf90a27ee80fd4c1d31/tensorflow-2.18.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfdd65ea7e064064283dd78d529dd621257ee617218f63681935fd15817c6286", size = 615520727 }, + { url = "https://files.pythonhosted.org/packages/eb/f1/828bbccc84a72db960a7d116f55f3f6aec9f5658f5d32ce9db20142d5742/tensorflow-2.18.0-cp312-cp312-win_amd64.whl", hash = "sha256:a701c2d3dca5f2efcab315b2c217f140ebd3da80410744e87d77016b3aaf53cb", size = 7520 }, + { url = "https://files.pythonhosted.org/packages/25/31/52443f47e743d53ba1c9e8324e1a2eb0527df01d96d9174868c698b00d75/tensorflow-2.18.0-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:336cace378c129c20fee6292f6a541165073d153a9a4c9cf4f14478a81895776", size = 239375479 }, + { url = "https://files.pythonhosted.org/packages/8e/09/06d9c7ef90c208ae7bb27c0f149e40f52799b570ba3a283800fe2f38cece/tensorflow-2.18.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bcfd32134de8f95515b2d0ced89cdae15484b787d3a21893e9291def06c10c4e", size = 231676692 }, + { url = "https://files.pythonhosted.org/packages/49/df/c6e5ef56bed7c621763867f38aabd860aa55d7da27bccfc72f4816d9969f/tensorflow-2.18.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ada1f7290c75b34748ee7378c1b77927e4044c94b8dc72dc75e7667c4fdaeb94", size = 615262304 }, + { url = "https://files.pythonhosted.org/packages/42/c2/587259ae961e88b9c4cc2599202844b5ab8f0ba4b44dabcd090a09d99368/tensorflow-2.18.0-cp39-cp39-win_amd64.whl", hash = "sha256:f8c946df1cb384504578fac1c199a95322373b8e04abd88aa8ae01301df469ea", size = 7515 }, +] + +[[package]] +name = "tensorflow-io-gcs-filesystem" +version = "0.37.1" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/a3/12d7e7326a707919b321e2d6e4c88eb61596457940fd2b8ff3e9b7fac8a7/tensorflow_io_gcs_filesystem-0.37.1-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:249c12b830165841411ba71e08215d0e94277a49c551e6dd5d72aab54fe5491b", size = 2470224 }, + { url = "https://files.pythonhosted.org/packages/1c/55/3849a188cc15e58fefde20e9524d124a629a67a06b4dc0f6c881cb3c6e39/tensorflow_io_gcs_filesystem-0.37.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:257aab23470a0796978efc9c2bcf8b0bc80f22e6298612a4c0a50d3f4e88060c", size = 3479613 }, + { url = "https://files.pythonhosted.org/packages/e2/19/9095c69e22c879cb3896321e676c69273a549a3148c4f62aa4bc5ebdb20f/tensorflow_io_gcs_filesystem-0.37.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8febbfcc67c61e542a5ac1a98c7c20a91a5e1afc2e14b1ef0cb7c28bc3b6aa70", size = 4842078 }, + { url = "https://files.pythonhosted.org/packages/f3/48/47b7d25572961a48b1de3729b7a11e835b888e41e0203cca82df95d23b91/tensorflow_io_gcs_filesystem-0.37.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9679b36e3a80921876f31685ab6f7270f3411a4cc51bc2847e80d0e4b5291e27", size = 5085736 }, + { url = "https://files.pythonhosted.org/packages/40/9b/b2fb82d0da673b17a334f785fc19c23483165019ddc33b275ef25ca31173/tensorflow_io_gcs_filesystem-0.37.1-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:32c50ab4e29a23c1f91cd0f9ab8c381a0ab10f45ef5c5252e94965916041737c", size = 2470224 }, + { url = "https://files.pythonhosted.org/packages/5b/cc/16634e76f3647fbec18187258da3ba11184a6232dcf9073dc44579076d36/tensorflow_io_gcs_filesystem-0.37.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:b02f9c5f94fd62773954a04f69b68c4d576d076fd0db4ca25d5479f0fbfcdbad", size = 3479613 }, + { url = "https://files.pythonhosted.org/packages/de/bf/ba597d3884c77d05a78050f3c178933d69e3f80200a261df6eaa920656cd/tensorflow_io_gcs_filesystem-0.37.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6e1f2796b57e799a8ca1b75bf47c2aaa437c968408cc1a402a9862929e104cda", size = 4842079 }, + { url = "https://files.pythonhosted.org/packages/66/7f/e36ae148c2f03d61ca1bff24bc13a0fef6d6825c966abef73fc6f880a23b/tensorflow_io_gcs_filesystem-0.37.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee7c8ee5fe2fd8cb6392669ef16e71841133041fee8a330eff519ad9b36e4556", size = 5085736 }, + { url = "https://files.pythonhosted.org/packages/70/83/4422804257fe2942ae0af4ea5bcc9df59cb6cb1bd092202ef240751d16aa/tensorflow_io_gcs_filesystem-0.37.1-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:ffebb6666a7bfc28005f4fbbb111a455b5e7d6cd3b12752b7050863ecb27d5cc", size = 2470224 }, + { url = "https://files.pythonhosted.org/packages/43/9b/be27588352d7bd971696874db92d370f578715c17c0ccb27e4b13e16751e/tensorflow_io_gcs_filesystem-0.37.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:fe8dcc6d222258a080ac3dfcaaaa347325ce36a7a046277f6b3e19abc1efb3c5", size = 3479614 }, + { url = "https://files.pythonhosted.org/packages/d3/46/962f47af08bd39fc9feb280d3192825431a91a078c856d17a78ae4884eb1/tensorflow_io_gcs_filesystem-0.37.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fbb33f1745f218464a59cecd9a18e32ca927b0f4d77abd8f8671b645cc1a182f", size = 4842077 }, + { url = "https://files.pythonhosted.org/packages/f0/9b/790d290c232bce9b691391cf16e95a96e469669c56abfb1d9d0f35fa437c/tensorflow_io_gcs_filesystem-0.37.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:286389a203a5aee1a4fa2e53718c661091aa5fea797ff4fa6715ab8436b02e6c", size = 5085733 }, + { url = "https://files.pythonhosted.org/packages/12/4f/798df777498fab9dc683a658688e962f0af56454eb040c90f836fd9fa67c/tensorflow_io_gcs_filesystem-0.37.1-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:ee5da49019670ed364f3e5fb86b46420841a6c3cb52a300553c63841671b3e6d", size = 2470221 }, + { url = "https://files.pythonhosted.org/packages/7a/f9/ce6a0efde262a79361f0d67392fdf0d0406781a1ee4fc48d0d8b0553b311/tensorflow_io_gcs_filesystem-0.37.1-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:8943036bbf84e7a2be3705cb56f9c9df7c48c9e614bb941f0936c58e3ca89d6f", size = 3479613 }, + { url = "https://files.pythonhosted.org/packages/66/5f/334a011caa1eb97689274d1141df8e6b7a25e389f0390bdcd90235de9783/tensorflow_io_gcs_filesystem-0.37.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:426de1173cb81fbd62becec2012fc00322a295326d90eb6c737fab636f182aed", size = 4842075 }, + { url = "https://files.pythonhosted.org/packages/3d/cb/7dcee55fc5a7d7d8a862e12519322851cd5fe5b086f946fd71e4ae1ef281/tensorflow_io_gcs_filesystem-0.37.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0df00891669390078a003cedbdd3b8e645c718b111917535fa1d7725e95cdb95", size = 5087496 }, +] + +[[package]] +name = "tensorstore" +version = "0.1.69" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] +dependencies = [ + { name = "ml-dtypes", marker = "python_full_version < '3.10'" }, + { name = "numpy", marker = "python_full_version < '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/12/0e/03b2797d25f70b30c807bfef1aa8ce09731e7a82a406ba84bb67ddfc34df/tensorstore-0.1.69.tar.gz", hash = "sha256:150cdc7e2044b7629ea466bfc8425ab50e52c8300950dbdd4a64445a2d4fbab1", size = 6585496 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f6/34/1b0821a0389cd4a10fefde2ef29e067b619dcecf3f6df548ad59f74bb554/tensorstore-0.1.69-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:9b6bf6938a3a9ac1a415d06479496f0e3180d487be6e218d223e53203b12c208", size = 14836993 }, + { url = "https://files.pythonhosted.org/packages/47/d7/f13a89ccf22a025456b34f188ffbd1a8abf8c834b389c7b84f1a6c9aff1e/tensorstore-0.1.69-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0a030706644c501aba8def8c453a26148d1c76e11a1020a3aa6a2737d0d8f982", size = 12820268 }, + { url = "https://files.pythonhosted.org/packages/d3/2a/699156262efcbcfc2091fd0f8485c97b090938ea91637f0fe6c7cc93dc88/tensorstore-0.1.69-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b0b9dce8d35e74bfb7d1f96ef86dc6f7de6a8ce13dbb2166fbc30ec19fdbbe7", size = 16204089 }, + { url = "https://files.pythonhosted.org/packages/96/e0/bd20ddda24e36e3cb68b674a8d320b7208ab9c7b90a61b159c2471468e11/tensorstore-0.1.69-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b796eae8466fe8a4b9f5636e4ea68ead47dd50454d95f27365ffed63ab73e64", size = 17534514 }, + { url = "https://files.pythonhosted.org/packages/62/f9/af4523a5cc0aeb5aa4ffd4bb0c381ca004354022c8cb7994afd7f213f138/tensorstore-0.1.69-cp310-cp310-win_amd64.whl", hash = "sha256:26c8bbc03537d236d393e816872d2ee8166f1b9662e6dd6bc36b38588884f6b7", size = 11997600 }, + { url = "https://files.pythonhosted.org/packages/15/8b/e71ae481056d0429940ab23a7b2bb1faf2a2a63a4f2a3fd2c7738e43275b/tensorstore-0.1.69-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:760f9841e5694ceb2be2ffc93961646de8e60e147d150322f95a396c2b063785", size = 14839086 }, + { url = "https://files.pythonhosted.org/packages/5a/8c/d5ba205c47c54c71c137dddc75d9f4c16020ab05700f9f9314c958d34f0d/tensorstore-0.1.69-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:819ccd6d68cb5c1a60ac2cd1fa6f89d5797ce90b795493acf4e45a4242ae1738", size = 12820531 }, + { url = "https://files.pythonhosted.org/packages/32/a7/76deb854937fcdb1f56c18ee5ed261f6520c2ca1b22d330a4e337533d2af/tensorstore-0.1.69-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e99ed4bf3c81435e5348c2f404756499dbb4d9e2d9b18490c71db7664363058a", size = 16205478 }, + { url = "https://files.pythonhosted.org/packages/e3/3b/44b16c200637d4c55b5a26cb994af8b3af656d56dc277a761c1e1000ab97/tensorstore-0.1.69-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:172549769bf46ef454f9f9bca42eb1c9c75d8d822bbaf573b18397b53f7124b3", size = 17536793 }, + { url = "https://files.pythonhosted.org/packages/1b/88/e828b97b9971cd1b71e99b2c3b154686b5ee893982f02e8886590b380ab5/tensorstore-0.1.69-cp311-cp311-win_amd64.whl", hash = "sha256:3d702d7a3fe4043a47d8cc5abc31a937a2073503dae97f92cf2bcbad6622b1ab", size = 11997580 }, + { url = "https://files.pythonhosted.org/packages/8a/71/faf0e954dd6eb612f652c2f110cc292b1f3071b2a15179d98d9367221866/tensorstore-0.1.69-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:8e328b6c201d32339422838a97b67157470a34d2827b880c149d9102afb07e02", size = 14878020 }, + { url = "https://files.pythonhosted.org/packages/f5/ea/67e55d3dce8ff473b42063a6fea639f21b8132f8e7072330f81df2af819c/tensorstore-0.1.69-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f57f184e4fbf9175561914bd54045ca4fa75ea4be1206ebe4fe22b19b540ce5f", size = 12848724 }, + { url = "https://files.pythonhosted.org/packages/e7/9e/48339e916035472a3307eb2746f731100834715aec1023f07d0d6a7e9fbc/tensorstore-0.1.69-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:368e84a9b67f153f18cefa8d6557098c52300b44ea633cbe00a1f23b6124373a", size = 16194513 }, + { url = "https://files.pythonhosted.org/packages/bc/a9/f3dbd91a93a3f4d9c427676d5e11a9cf8b5485ff27eb13cbc57b0b937fa6/tensorstore-0.1.69-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3221a1954f1721c178b453a9bd9839c6d80a36a2f45afe43ec9d7f21de97ebd", size = 17529065 }, + { url = "https://files.pythonhosted.org/packages/00/ca/8080e4bd57028aface79b212de13d9fecdebe905e644823c5cc96e172484/tensorstore-0.1.69-cp312-cp312-win_amd64.whl", hash = "sha256:3d88bc1732cc2aa84f2ae98ed00586ce1ce9f149f885982f097248d77986d5ef", size = 11999274 }, + { url = "https://files.pythonhosted.org/packages/94/62/59cd878a73476a1e75ee96cc0b1f120bf23c590b1a4b6bdc5cb8c5418c52/tensorstore-0.1.69-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:9579ed3b3fcf13d64c5274e76b4cc987edda3134dca3532b8a0a36a9b66af486", size = 14837313 }, + { url = "https://files.pythonhosted.org/packages/ad/58/859aaae8f7e94f94235c642face4f289162761b98b3770c7aece8950597d/tensorstore-0.1.69-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:25954820b75bed339bd3df87fd35596dc63773e192d7e63918092af9d3328146", size = 12820471 }, + { url = "https://files.pythonhosted.org/packages/64/65/98983608fff396ad46bfcce48e503a88aeb74cb47a9fe38ede9d2cbacd30/tensorstore-0.1.69-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de18eefc23d75a0c438576985ca9a516ce5c1dc757a2052ce24e36c145239ff9", size = 16204805 }, + { url = "https://files.pythonhosted.org/packages/09/33/1b24d6eb58d9b50f1600eb500c020d4c87da43637d9ab1ee134e4d7d7dc0/tensorstore-0.1.69-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a645a770b6a5134e51869c215aa60bd29c565a07c0f12d1cd03352dcd9f1b6c0", size = 17537436 }, + { url = "https://files.pythonhosted.org/packages/f3/25/36e7aad6c50572abc69668b8302252667e86f6d410e45cfa36ea1a35f79b/tensorstore-0.1.69-cp39-cp39-win_amd64.whl", hash = "sha256:041eaa3b875dd692882efe1ccf2e52eb67fcc212399f30d381f2e1c1a2932597", size = 11959410 }, +] + +[[package]] +name = "tensorstore" +version = "0.1.74" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.12'", + "python_full_version == '3.11.*'", + "python_full_version == '3.10.*'", +] +dependencies = [ + { name = "ml-dtypes", marker = "python_full_version >= '3.10'" }, + { name = "numpy", marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3c/b9/ea25aba62c688a87d7d7d9cc5926d602e2f9e84fa72586825486fb180b7e/tensorstore-0.1.74.tar.gz", hash = "sha256:a062875f27283d30ce4959c408c253ecb336fce8e3f9837c064e3d30cda79203", size = 6795605 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f2/20/1e7e776dc30f2f07416223c12f9ad244ec539af5fa1fbef9320812a9a3b6/tensorstore-0.1.74-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:edfae80aceb05640ac2209a11a4b76cecd5d9c4a95c01ede8c89c8edaa90f9d5", size = 15292660 }, + { url = "https://files.pythonhosted.org/packages/76/cc/81bf2d6a4caa239d38905b439864d3a8bf06b27d6d31bb2396e3f4f5cc55/tensorstore-0.1.74-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ab985d767d53e9478987c23dc7aea8f7e8aed2ef90ec8f7f939e8b399667feb1", size = 13260438 }, + { url = "https://files.pythonhosted.org/packages/88/4c/a26c4c8b8e7573d2b552505cd46a658b9a68a80d88e9d3c68f16d10e4d62/tensorstore-0.1.74-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d16d1181c292ea065ebd203e823420c65e365d0407eea8f0a3dd82995da0cc65", size = 17041531 }, + { url = "https://files.pythonhosted.org/packages/e4/a9/3859b1b497dacf2093e196e1d4ed3b95e8553c7d7c9fe1f88216c72253a9/tensorstore-0.1.74-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f327e813152705b5297f251824a91106e17a06fd2f6b5f6e94c6401c5937da8c", size = 18392852 }, + { url = "https://files.pythonhosted.org/packages/2d/3b/b7494ea0a37dd4cd3721f104fc52d4c953354b801eb1adf08e40bc08aaa0/tensorstore-0.1.74-cp310-cp310-win_amd64.whl", hash = "sha256:e56e9690cc20463951a52a6908e18056a93ce5bcd4a881834e2b5962801a1125", size = 12429998 }, + { url = "https://files.pythonhosted.org/packages/0d/3e/d67bb3d9bb7409469d15fb90ef5756e6ac8b835af7f27c02fc542c4b4059/tensorstore-0.1.74-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:8353e619d9140ca50fc0cb5b846e07c68462dd5015b4714752a0a664e48a03d3", size = 15294582 }, + { url = "https://files.pythonhosted.org/packages/01/f4/49cb5ea8e63303fcb0a6ebf0ed546aaec63982a4abca0e9801da5e3a24e3/tensorstore-0.1.74-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a3ad1bfbb257ab84de1a5c9b79a60cebb5fbb7a411ddb1c246c21c9795789ba1", size = 13261395 }, + { url = "https://files.pythonhosted.org/packages/ad/7b/9c12d4687e6ff19222f12719286c13a546f1714e5dbed75d52a4267534ed/tensorstore-0.1.74-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3ad9daf4c757db41ad091a1a5502807baeb848be0937986d8766049c39c8466", size = 17042621 }, + { url = "https://files.pythonhosted.org/packages/b5/07/cf0dc4540a78bc715fbcf4417c5dc708f3d12ed1664bf117f22463f411fc/tensorstore-0.1.74-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a35364804e7d71bf5e86d2dae4de04c90249b61ff71448b9713b4e72b2389bd", size = 18393581 }, + { url = "https://files.pythonhosted.org/packages/ac/42/edf004c5a101e021f052ea3564250d773d7cf6458f92934456ffa967383f/tensorstore-0.1.74-cp311-cp311-win_amd64.whl", hash = "sha256:15dcb6ce282e32d005caad34d595b0be070947578448a2861c63fdd608fc7394", size = 12431849 }, + { url = "https://files.pythonhosted.org/packages/a1/14/2e6d1cad744af9e9a1a78d881a908a859ad95b61b15de10397069f55fbd8/tensorstore-0.1.74-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:7218722ee5d74e4d01f357917d3b1b7b1d6b1c068aa73e3d801cb3d58fc45116", size = 15334307 }, + { url = "https://files.pythonhosted.org/packages/b2/ac/8d572b8c6d689eb50db0252e9d35ee6278a6aed481b64d7e025cf51e32c4/tensorstore-0.1.74-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a6926554a8633d0210bdba619d3996fff6a6af4214237fbca626e6ddfcc8ea39", size = 13288669 }, + { url = "https://files.pythonhosted.org/packages/9d/6c/3e76d614ad70b61670686d91abaa3ddee6b01255bf2b40f050beb15b7970/tensorstore-0.1.74-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d584e468eb4ef8195f5d21a9da4780cf96c6074b87ef219b43a89efce3d503ca", size = 17031720 }, + { url = "https://files.pythonhosted.org/packages/31/f3/09d7c3ad7c9517f89b5be9b4460b83333e98dce1c9ab0a52464ded0bab67/tensorstore-0.1.74-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0af2225431d59f8a2bb4db4c1519252f10ee407e6550875d78212d3d34ee743", size = 18378829 }, + { url = "https://files.pythonhosted.org/packages/a7/f2/45ece38705280ed9ebf4ccaf084ed1e76e35b1eeec8c510e589978ac8dcd/tensorstore-0.1.74-cp312-cp312-win_amd64.whl", hash = "sha256:4e35f3679873cdc488aae20b9ae2cea4589c7b147a80edb07eb3f09eba47d43d", size = 12432300 }, + { url = "https://files.pythonhosted.org/packages/fb/e9/a08c6a6eb7d6b4b26053d4575196a06c6fccf4e89f9bc625f81e7c91bb5d/tensorstore-0.1.74-cp313-cp313-macosx_10_14_x86_64.whl", hash = "sha256:f7d2c80de9ab352ca14aeca798d6650c5670725e6f8eac73f4fcc8f3147ca614", size = 15334469 }, + { url = "https://files.pythonhosted.org/packages/9a/a9/64b90c6e66e0b8043e641090144c6614b0c78d9a719b9110d953d13a516d/tensorstore-0.1.74-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ceef7d2dcfd1caf61356f7eeb9a37896b4825b4be2750b00615cf5fb1ae47a8b", size = 13288791 }, + { url = "https://files.pythonhosted.org/packages/62/e8/226cfc25d7eac00e783ff2ee4994830c4a42cd8690e207c4a8b93210f3d9/tensorstore-0.1.74-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e71637002a806bc1b0f0f05556d1c33493a43f3ab35f9632b3d48855677d93dc", size = 17031815 }, + { url = "https://files.pythonhosted.org/packages/9a/09/dce8a0942d84f6bb039b5ea3e8bc6a479b1a9535cd216b0d42dd03c4f761/tensorstore-0.1.74-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c799edf9000aee68d6676e3d2f73d4e1a56fc817c47e150732f6d3bd2b1ef46d", size = 18378091 }, + { url = "https://files.pythonhosted.org/packages/a6/23/5218575d25de9d8debfb3faf290a1e3b9a7b6be9e77ba07ff3a63a0bc899/tensorstore-0.1.74-cp313-cp313-win_amd64.whl", hash = "sha256:5da86437ffa1ee0f0c590c38daa2f4b548890ce66b1f470ac98714cb0eabdbf5", size = 12432635 }, +] + +[[package]] +name = "termcolor" +version = "3.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ca/6c/3d75c196ac07ac8749600b60b03f4f6094d54e132c4d94ebac6ee0e0add0/termcolor-3.1.0.tar.gz", hash = "sha256:6a6dd7fbee581909eeec6a756cff1d7f7c376063b14e4a298dc4980309e55970", size = 14324 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4f/bd/de8d508070629b6d84a30d01d57e4a65c69aa7f5abe7560b8fad3b50ea59/termcolor-3.1.0-py3-none-any.whl", hash = "sha256:591dd26b5c2ce03b9e43f391264626557873ce1d379019786f99b0c2bee140aa", size = 7684 }, +] + +[[package]] +name = "tomli" +version = "2.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/18/87/302344fed471e44a87289cf4967697d07e532f2421fdaf868a303cbae4ff/tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff", size = 17175 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/43/ca/75707e6efa2b37c77dadb324ae7d9571cb424e61ea73fad7c56c2d14527f/tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249", size = 131077 }, + { url = "https://files.pythonhosted.org/packages/c7/16/51ae563a8615d472fdbffc43a3f3d46588c264ac4f024f63f01283becfbb/tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6", size = 123429 }, + { url = "https://files.pythonhosted.org/packages/f1/dd/4f6cd1e7b160041db83c694abc78e100473c15d54620083dbd5aae7b990e/tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a", size = 226067 }, + { url = "https://files.pythonhosted.org/packages/a9/6b/c54ede5dc70d648cc6361eaf429304b02f2871a345bbdd51e993d6cdf550/tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee", size = 236030 }, + { url = "https://files.pythonhosted.org/packages/1f/47/999514fa49cfaf7a92c805a86c3c43f4215621855d151b61c602abb38091/tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e", size = 240898 }, + { url = "https://files.pythonhosted.org/packages/73/41/0a01279a7ae09ee1573b423318e7934674ce06eb33f50936655071d81a24/tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4", size = 229894 }, + { url = "https://files.pythonhosted.org/packages/55/18/5d8bc5b0a0362311ce4d18830a5d28943667599a60d20118074ea1b01bb7/tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106", size = 245319 }, + { url = "https://files.pythonhosted.org/packages/92/a3/7ade0576d17f3cdf5ff44d61390d4b3febb8a9fc2b480c75c47ea048c646/tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8", size = 238273 }, + { url = "https://files.pythonhosted.org/packages/72/6f/fa64ef058ac1446a1e51110c375339b3ec6be245af9d14c87c4a6412dd32/tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff", size = 98310 }, + { url = "https://files.pythonhosted.org/packages/6a/1c/4a2dcde4a51b81be3530565e92eda625d94dafb46dbeb15069df4caffc34/tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b", size = 108309 }, + { url = "https://files.pythonhosted.org/packages/52/e1/f8af4c2fcde17500422858155aeb0d7e93477a0d59a98e56cbfe75070fd0/tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea", size = 132762 }, + { url = "https://files.pythonhosted.org/packages/03/b8/152c68bb84fc00396b83e7bbddd5ec0bd3dd409db4195e2a9b3e398ad2e3/tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8", size = 123453 }, + { url = "https://files.pythonhosted.org/packages/c8/d6/fc9267af9166f79ac528ff7e8c55c8181ded34eb4b0e93daa767b8841573/tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192", size = 233486 }, + { url = "https://files.pythonhosted.org/packages/5c/51/51c3f2884d7bab89af25f678447ea7d297b53b5a3b5730a7cb2ef6069f07/tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222", size = 242349 }, + { url = "https://files.pythonhosted.org/packages/ab/df/bfa89627d13a5cc22402e441e8a931ef2108403db390ff3345c05253935e/tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77", size = 252159 }, + { url = "https://files.pythonhosted.org/packages/9e/6e/fa2b916dced65763a5168c6ccb91066f7639bdc88b48adda990db10c8c0b/tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6", size = 237243 }, + { url = "https://files.pythonhosted.org/packages/b4/04/885d3b1f650e1153cbb93a6a9782c58a972b94ea4483ae4ac5cedd5e4a09/tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd", size = 259645 }, + { url = "https://files.pythonhosted.org/packages/9c/de/6b432d66e986e501586da298e28ebeefd3edc2c780f3ad73d22566034239/tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e", size = 244584 }, + { url = "https://files.pythonhosted.org/packages/1c/9a/47c0449b98e6e7d1be6cbac02f93dd79003234ddc4aaab6ba07a9a7482e2/tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98", size = 98875 }, + { url = "https://files.pythonhosted.org/packages/ef/60/9b9638f081c6f1261e2688bd487625cd1e660d0a85bd469e91d8db969734/tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4", size = 109418 }, + { url = "https://files.pythonhosted.org/packages/04/90/2ee5f2e0362cb8a0b6499dc44f4d7d48f8fff06d28ba46e6f1eaa61a1388/tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7", size = 132708 }, + { url = "https://files.pythonhosted.org/packages/c0/ec/46b4108816de6b385141f082ba99e315501ccd0a2ea23db4a100dd3990ea/tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c", size = 123582 }, + { url = "https://files.pythonhosted.org/packages/a0/bd/b470466d0137b37b68d24556c38a0cc819e8febe392d5b199dcd7f578365/tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13", size = 232543 }, + { url = "https://files.pythonhosted.org/packages/d9/e5/82e80ff3b751373f7cead2815bcbe2d51c895b3c990686741a8e56ec42ab/tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281", size = 241691 }, + { url = "https://files.pythonhosted.org/packages/05/7e/2a110bc2713557d6a1bfb06af23dd01e7dde52b6ee7dadc589868f9abfac/tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272", size = 251170 }, + { url = "https://files.pythonhosted.org/packages/64/7b/22d713946efe00e0adbcdfd6d1aa119ae03fd0b60ebed51ebb3fa9f5a2e5/tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140", size = 236530 }, + { url = "https://files.pythonhosted.org/packages/38/31/3a76f67da4b0cf37b742ca76beaf819dca0ebef26d78fc794a576e08accf/tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2", size = 258666 }, + { url = "https://files.pythonhosted.org/packages/07/10/5af1293da642aded87e8a988753945d0cf7e00a9452d3911dd3bb354c9e2/tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744", size = 243954 }, + { url = "https://files.pythonhosted.org/packages/5b/b9/1ed31d167be802da0fc95020d04cd27b7d7065cc6fbefdd2f9186f60d7bd/tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec", size = 98724 }, + { url = "https://files.pythonhosted.org/packages/c7/32/b0963458706accd9afcfeb867c0f9175a741bf7b19cd424230714d722198/tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69", size = 109383 }, + { url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc", size = 14257 }, +] + +[[package]] +name = "toolz" +version = "1.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8a/0b/d80dfa675bf592f636d1ea0b835eab4ec8df6e9415d8cfd766df54456123/toolz-1.0.0.tar.gz", hash = "sha256:2c86e3d9a04798ac556793bced838816296a2f085017664e4995cb40a1047a02", size = 66790 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/03/98/eb27cc78ad3af8e302c9d8ff4977f5026676e130d28dd7578132a457170c/toolz-1.0.0-py3-none-any.whl", hash = "sha256:292c8f1c4e7516bf9086f8850935c799a874039c8bcf959d47b600e4c44a6236", size = 56383 }, +] + +[[package]] +name = "torch" +version = "2.7.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "filelock" }, + { name = "fsspec" }, + { name = "jinja2" }, + { name = "networkx", version = "3.2.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "networkx", version = "3.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "nvidia-cublas-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, + { name = "nvidia-cuda-cupti-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, + { name = "nvidia-cuda-nvrtc-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, + { name = "nvidia-cuda-runtime-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, + { name = "nvidia-cudnn-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, + { name = "nvidia-cufft-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, + { name = "nvidia-cufile-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, + { name = "nvidia-curand-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, + { name = "nvidia-cusolver-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, + { name = "nvidia-cusparse-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, + { name = "nvidia-cusparselt-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, + { name = "nvidia-nccl-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, + { name = "nvidia-nvjitlink-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, + { name = "nvidia-nvtx-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, + { name = "setuptools", marker = "python_full_version >= '3.12'" }, + { name = "sympy" }, + { name = "triton", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, + { name = "typing-extensions" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/46/c2/3fb87940fa160d956ee94d644d37b99a24b9c05a4222bf34f94c71880e28/torch-2.7.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:c9afea41b11e1a1ab1b258a5c31afbd646d6319042bfe4f231b408034b51128b", size = 99158447 }, + { url = "https://files.pythonhosted.org/packages/cc/2c/91d1de65573fce563f5284e69d9c56b57289625cffbbb6d533d5d56c36a5/torch-2.7.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:0b9960183b6e5b71239a3e6c883d8852c304e691c0b2955f7045e8a6d05b9183", size = 865164221 }, + { url = "https://files.pythonhosted.org/packages/7f/7e/1b1cc4e0e7cc2666cceb3d250eef47a205f0821c330392cf45eb08156ce5/torch-2.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:2ad79d0d8c2a20a37c5df6052ec67c2078a2c4e9a96dd3a8b55daaff6d28ea29", size = 212521189 }, + { url = "https://files.pythonhosted.org/packages/dc/0b/b2b83f30b8e84a51bf4f96aa3f5f65fdf7c31c591cc519310942339977e2/torch-2.7.0-cp310-none-macosx_11_0_arm64.whl", hash = "sha256:34e0168ed6de99121612d72224e59b2a58a83dae64999990eada7260c5dd582d", size = 68559462 }, + { url = "https://files.pythonhosted.org/packages/40/da/7378d16cc636697f2a94f791cb496939b60fb8580ddbbef22367db2c2274/torch-2.7.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:2b7813e904757b125faf1a9a3154e1d50381d539ced34da1992f52440567c156", size = 99159397 }, + { url = "https://files.pythonhosted.org/packages/0e/6b/87fcddd34df9f53880fa1f0c23af7b6b96c935856473faf3914323588c40/torch-2.7.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:fd5cfbb4c3bbadd57ad1b27d56a28008f8d8753733411a140fcfb84d7f933a25", size = 865183681 }, + { url = "https://files.pythonhosted.org/packages/13/85/6c1092d4b06c3db1ed23d4106488750917156af0b24ab0a2d9951830b0e9/torch-2.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:58df8d5c2eeb81305760282b5069ea4442791a6bbf0c74d9069b7b3304ff8a37", size = 212520100 }, + { url = "https://files.pythonhosted.org/packages/aa/3f/85b56f7e2abcfa558c5fbf7b11eb02d78a4a63e6aeee2bbae3bb552abea5/torch-2.7.0-cp311-none-macosx_11_0_arm64.whl", hash = "sha256:0a8d43caa342b9986101ec5feb5bbf1d86570b5caa01e9cb426378311258fdde", size = 68569377 }, + { url = "https://files.pythonhosted.org/packages/aa/5e/ac759f4c0ab7c01feffa777bd68b43d2ac61560a9770eeac074b450f81d4/torch-2.7.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:36a6368c7ace41ad1c0f69f18056020b6a5ca47bedaca9a2f3b578f5a104c26c", size = 99013250 }, + { url = "https://files.pythonhosted.org/packages/9c/58/2d245b6f1ef61cf11dfc4aceeaacbb40fea706ccebac3f863890c720ab73/torch-2.7.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:15aab3e31c16feb12ae0a88dba3434a458874636f360c567caa6a91f6bfba481", size = 865042157 }, + { url = "https://files.pythonhosted.org/packages/44/80/b353c024e6b624cd9ce1d66dcb9d24e0294680f95b369f19280e241a0159/torch-2.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:f56d4b2510934e072bab3ab8987e00e60e1262fb238176168f5e0c43a1320c6d", size = 212482262 }, + { url = "https://files.pythonhosted.org/packages/ee/8d/b2939e5254be932db1a34b2bd099070c509e8887e0c5a90c498a917e4032/torch-2.7.0-cp312-none-macosx_11_0_arm64.whl", hash = "sha256:30b7688a87239a7de83f269333651d8e582afffce6f591fff08c046f7787296e", size = 68574294 }, + { url = "https://files.pythonhosted.org/packages/14/24/720ea9a66c29151b315ea6ba6f404650834af57a26b2a04af23ec246b2d5/torch-2.7.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:868ccdc11798535b5727509480cd1d86d74220cfdc42842c4617338c1109a205", size = 99015553 }, + { url = "https://files.pythonhosted.org/packages/4b/27/285a8cf12bd7cd71f9f211a968516b07dcffed3ef0be585c6e823675ab91/torch-2.7.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:9b52347118116cf3dff2ab5a3c3dd97c719eb924ac658ca2a7335652076df708", size = 865046389 }, + { url = "https://files.pythonhosted.org/packages/74/c8/2ab2b6eadc45554af8768ae99668c5a8a8552e2012c7238ded7e9e4395e1/torch-2.7.0-cp313-cp313-win_amd64.whl", hash = "sha256:434cf3b378340efc87c758f250e884f34460624c0523fe5c9b518d205c91dd1b", size = 212490304 }, + { url = "https://files.pythonhosted.org/packages/28/fd/74ba6fde80e2b9eef4237fe668ffae302c76f0e4221759949a632ca13afa/torch-2.7.0-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:edad98dddd82220465b106506bb91ee5ce32bd075cddbcf2b443dfaa2cbd83bf", size = 68856166 }, + { url = "https://files.pythonhosted.org/packages/cb/b4/8df3f9fe6bdf59e56a0e538592c308d18638eb5f5dc4b08d02abb173c9f0/torch-2.7.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:2a885fc25afefb6e6eb18a7d1e8bfa01cc153e92271d980a49243b250d5ab6d9", size = 99091348 }, + { url = "https://files.pythonhosted.org/packages/9d/f5/0bd30e9da04c3036614aa1b935a9f7e505a9e4f1f731b15e165faf8a4c74/torch-2.7.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:176300ff5bc11a5f5b0784e40bde9e10a35c4ae9609beed96b4aeb46a27f5fae", size = 865104023 }, + { url = "https://files.pythonhosted.org/packages/d1/b7/2235d0c3012c596df1c8d39a3f4afc1ee1b6e318d469eda4c8bb68566448/torch-2.7.0-cp313-cp313t-win_amd64.whl", hash = "sha256:d0ca446a93f474985d81dc866fcc8dccefb9460a29a456f79d99c29a78a66993", size = 212750916 }, + { url = "https://files.pythonhosted.org/packages/90/48/7e6477cf40d48cc0a61fa0d41ee9582b9a316b12772fcac17bc1a40178e7/torch-2.7.0-cp313-none-macosx_11_0_arm64.whl", hash = "sha256:27f5007bdf45f7bb7af7f11d1828d5c2487e030690afb3d89a651fd7036a390e", size = 68575074 }, + { url = "https://files.pythonhosted.org/packages/57/6a/36775d1b553a443ba1453e1bfeae903ef20d94c95ab31aa09225bf52fda1/torch-2.7.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:e362efaa5b3078e5f75c33efc05005b9b46de0d2e899519d5b4cad0e050ed0f7", size = 99197389 }, + { url = "https://files.pythonhosted.org/packages/a3/6c/3a8b4296b6490333c5133b57e34972b13e7c71470165a9aeffe87146165e/torch-2.7.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:fc1ed9258cbfce69970ff508ea60881818d414d098a800b7695ba36f570d34b0", size = 865155206 }, + { url = "https://files.pythonhosted.org/packages/52/1b/b0cffd683414ea162ab462270ff5028b5be8e9bc6a17447960bf4d7e11c2/torch-2.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:87b0802cab44659fcb6bcf5678d58fa4a8b48561cde8fb2d317edf0b6990e1bb", size = 212406320 }, + { url = "https://files.pythonhosted.org/packages/85/11/571d6363d1aaee3033af46b40798a0238b24522e9b291b676446943cc8a9/torch-2.7.0-cp39-none-macosx_11_0_arm64.whl", hash = "sha256:ccd7509141713997861b7a947ef0a717143cd7e9240addd168f38ba8fd23fd56", size = 68560465 }, +] + +[[package]] +name = "tqdm" +version = "4.67.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a8/4b/29b4ef32e036bb34e4ab51796dd745cdba7ed47ad142a9f4a1eb8e0c744d/tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2", size = 169737 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl", hash = "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2", size = 78540 }, +] + +[[package]] +name = "treescope" +version = "0.1.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy", marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/26/27/80ad254da167e0055d5679aefd224ab08844a4cd55aeee7ef72c999d5fc6/treescope-0.1.9.tar.gz", hash = "sha256:ba6cdbdc9c5b52691d5f3bb4c5d5c7daa5627119acac8640b46d37e6aabe63a6", size = 544385 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e4/09/b7e7bc5f21313d227e4fb98d2037646457ec06746327c5dd8ffed75e41e1/treescope-0.1.9-py3-none-any.whl", hash = "sha256:68677013a9f0228212fccf835f3fb037be07ae8b4c5f6f58eefab11198f83cf7", size = 182162 }, +] + +[[package]] +name = "triton" +version = "3.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "setuptools" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/04/d54d3a6d077c646624dc9461b0059e23fd5d30e0dbe67471e3654aec81f9/triton-3.3.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fad99beafc860501d7fcc1fb7045d9496cbe2c882b1674640304949165a916e7", size = 156441993 }, + { url = "https://files.pythonhosted.org/packages/3c/c5/4874a81131cc9e934d88377fbc9d24319ae1fb540f3333b4e9c696ebc607/triton-3.3.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3161a2bf073d6b22c4e2f33f951f3e5e3001462b2570e6df9cd57565bdec2984", size = 156528461 }, + { url = "https://files.pythonhosted.org/packages/11/53/ce18470914ab6cfbec9384ee565d23c4d1c55f0548160b1c7b33000b11fd/triton-3.3.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b68c778f6c4218403a6bd01be7484f6dc9e20fe2083d22dd8aef33e3b87a10a3", size = 156504509 }, + { url = "https://files.pythonhosted.org/packages/7d/74/4bf2702b65e93accaa20397b74da46fb7a0356452c1bb94dbabaf0582930/triton-3.3.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:47bc87ad66fa4ef17968299acacecaab71ce40a238890acc6ad197c3abe2b8f1", size = 156516468 }, + { url = "https://files.pythonhosted.org/packages/0a/93/f28a696fa750b9b608baa236f8225dd3290e5aff27433b06143adc025961/triton-3.3.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ce4700fc14032af1e049005ae94ba908e71cd6c2df682239aed08e49bc71b742", size = 156580729 }, + { url = "https://files.pythonhosted.org/packages/f0/9c/315d25590fc309e2d28bb67953526238fac5d54548a16ceca992c76441bc/triton-3.3.0-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1f41403bfa0cbb3e24fd958ca7fee04e9681e55e539296db9aca30c42acae693", size = 156439372 }, +] + +[[package]] +name = "typing-extensions" +version = "4.13.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f6/37/23083fcd6e35492953e8d2aaaa68b860eb422b34627b13f2ce3eb6106061/typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef", size = 106967 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8b/54/b1ae86c0973cc6f0210b53d508ca3641fb6d0c56823f288d108bc7ab3cc8/typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c", size = 45806 }, +] + +[[package]] +name = "urllib3" +version = "2.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8a/78/16493d9c386d8e60e442a35feac5e00f0913c0f4b7c217c11e8ec2ff53e0/urllib3-2.4.0.tar.gz", hash = "sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466", size = 390672 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6b/11/cc635220681e93a0183390e26485430ca2c7b5f9d33b15c74c2861cb8091/urllib3-2.4.0-py3-none-any.whl", hash = "sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813", size = 128680 }, +] + +[[package]] +name = "werkzeug" +version = "3.1.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9f/69/83029f1f6300c5fb2471d621ab06f6ec6b3324685a2ce0f9777fd4a8b71e/werkzeug-3.1.3.tar.gz", hash = "sha256:60723ce945c19328679790e3282cc758aa4a6040e4bb330f53d30fa546d44746", size = 806925 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/52/24/ab44c871b0f07f491e5d2ad12c9bd7358e527510618cb1b803a88e986db1/werkzeug-3.1.3-py3-none-any.whl", hash = "sha256:54b78bf3716d19a65be4fceccc0d1d7b89e608834989dfae50ea87564639213e", size = 224498 }, +] + +[[package]] +name = "wheel" +version = "0.45.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8a/98/2d9906746cdc6a6ef809ae6338005b3f21bb568bea3165cfc6a243fdc25c/wheel-0.45.1.tar.gz", hash = "sha256:661e1abd9198507b1409a20c02106d9670b2576e916d58f520316666abca6729", size = 107545 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0b/2c/87f3254fd8ffd29e4c02732eee68a83a1d3c346ae39bc6822dcbcb697f2b/wheel-0.45.1-py3-none-any.whl", hash = "sha256:708e7481cc80179af0e556bbf0cc00b8444c7321e2700b8d8580231d13017248", size = 72494 }, +] + +[[package]] +name = "wrapt" +version = "1.17.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c3/fc/e91cc220803d7bc4db93fb02facd8461c37364151b8494762cc88b0fbcef/wrapt-1.17.2.tar.gz", hash = "sha256:41388e9d4d1522446fe79d3213196bd9e3b301a336965b9e27ca2788ebd122f3", size = 55531 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/d1/1daec934997e8b160040c78d7b31789f19b122110a75eca3d4e8da0049e1/wrapt-1.17.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3d57c572081fed831ad2d26fd430d565b76aa277ed1d30ff4d40670b1c0dd984", size = 53307 }, + { url = "https://files.pythonhosted.org/packages/1b/7b/13369d42651b809389c1a7153baa01d9700430576c81a2f5c5e460df0ed9/wrapt-1.17.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b5e251054542ae57ac7f3fba5d10bfff615b6c2fb09abeb37d2f1463f841ae22", size = 38486 }, + { url = "https://files.pythonhosted.org/packages/62/bf/e0105016f907c30b4bd9e377867c48c34dc9c6c0c104556c9c9126bd89ed/wrapt-1.17.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:80dd7db6a7cb57ffbc279c4394246414ec99537ae81ffd702443335a61dbf3a7", size = 38777 }, + { url = "https://files.pythonhosted.org/packages/27/70/0f6e0679845cbf8b165e027d43402a55494779295c4b08414097b258ac87/wrapt-1.17.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a6e821770cf99cc586d33833b2ff32faebdbe886bd6322395606cf55153246c", size = 83314 }, + { url = "https://files.pythonhosted.org/packages/0f/77/0576d841bf84af8579124a93d216f55d6f74374e4445264cb378a6ed33eb/wrapt-1.17.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b60fb58b90c6d63779cb0c0c54eeb38941bae3ecf7a73c764c52c88c2dcb9d72", size = 74947 }, + { url = "https://files.pythonhosted.org/packages/90/ec/00759565518f268ed707dcc40f7eeec38637d46b098a1f5143bff488fe97/wrapt-1.17.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b870b5df5b71d8c3359d21be8f0d6c485fa0ebdb6477dda51a1ea54a9b558061", size = 82778 }, + { url = "https://files.pythonhosted.org/packages/f8/5a/7cffd26b1c607b0b0c8a9ca9d75757ad7620c9c0a9b4a25d3f8a1480fafc/wrapt-1.17.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4011d137b9955791f9084749cba9a367c68d50ab8d11d64c50ba1688c9b457f2", size = 81716 }, + { url = "https://files.pythonhosted.org/packages/7e/09/dccf68fa98e862df7e6a60a61d43d644b7d095a5fc36dbb591bbd4a1c7b2/wrapt-1.17.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:1473400e5b2733e58b396a04eb7f35f541e1fb976d0c0724d0223dd607e0f74c", size = 74548 }, + { url = "https://files.pythonhosted.org/packages/b7/8e/067021fa3c8814952c5e228d916963c1115b983e21393289de15128e867e/wrapt-1.17.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3cedbfa9c940fdad3e6e941db7138e26ce8aad38ab5fe9dcfadfed9db7a54e62", size = 81334 }, + { url = "https://files.pythonhosted.org/packages/4b/0d/9d4b5219ae4393f718699ca1c05f5ebc0c40d076f7e65fd48f5f693294fb/wrapt-1.17.2-cp310-cp310-win32.whl", hash = "sha256:582530701bff1dec6779efa00c516496968edd851fba224fbd86e46cc6b73563", size = 36427 }, + { url = "https://files.pythonhosted.org/packages/72/6a/c5a83e8f61aec1e1aeef939807602fb880e5872371e95df2137142f5c58e/wrapt-1.17.2-cp310-cp310-win_amd64.whl", hash = "sha256:58705da316756681ad3c9c73fd15499aa4d8c69f9fd38dc8a35e06c12468582f", size = 38774 }, + { url = "https://files.pythonhosted.org/packages/cd/f7/a2aab2cbc7a665efab072344a8949a71081eed1d2f451f7f7d2b966594a2/wrapt-1.17.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ff04ef6eec3eee8a5efef2401495967a916feaa353643defcc03fc74fe213b58", size = 53308 }, + { url = "https://files.pythonhosted.org/packages/50/ff/149aba8365fdacef52b31a258c4dc1c57c79759c335eff0b3316a2664a64/wrapt-1.17.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4db983e7bca53819efdbd64590ee96c9213894272c776966ca6306b73e4affda", size = 38488 }, + { url = "https://files.pythonhosted.org/packages/65/46/5a917ce85b5c3b490d35c02bf71aedaa9f2f63f2d15d9949cc4ba56e8ba9/wrapt-1.17.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9abc77a4ce4c6f2a3168ff34b1da9b0f311a8f1cfd694ec96b0603dff1c79438", size = 38776 }, + { url = "https://files.pythonhosted.org/packages/ca/74/336c918d2915a4943501c77566db41d1bd6e9f4dbc317f356b9a244dfe83/wrapt-1.17.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b929ac182f5ace000d459c59c2c9c33047e20e935f8e39371fa6e3b85d56f4a", size = 83776 }, + { url = "https://files.pythonhosted.org/packages/09/99/c0c844a5ccde0fe5761d4305485297f91d67cf2a1a824c5f282e661ec7ff/wrapt-1.17.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f09b286faeff3c750a879d336fb6d8713206fc97af3adc14def0cdd349df6000", size = 75420 }, + { url = "https://files.pythonhosted.org/packages/b4/b0/9fc566b0fe08b282c850063591a756057c3247b2362b9286429ec5bf1721/wrapt-1.17.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a7ed2d9d039bd41e889f6fb9364554052ca21ce823580f6a07c4ec245c1f5d6", size = 83199 }, + { url = "https://files.pythonhosted.org/packages/9d/4b/71996e62d543b0a0bd95dda485219856def3347e3e9380cc0d6cf10cfb2f/wrapt-1.17.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:129a150f5c445165ff941fc02ee27df65940fcb8a22a61828b1853c98763a64b", size = 82307 }, + { url = "https://files.pythonhosted.org/packages/39/35/0282c0d8789c0dc9bcc738911776c762a701f95cfe113fb8f0b40e45c2b9/wrapt-1.17.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1fb5699e4464afe5c7e65fa51d4f99e0b2eadcc176e4aa33600a3df7801d6662", size = 75025 }, + { url = "https://files.pythonhosted.org/packages/4f/6d/90c9fd2c3c6fee181feecb620d95105370198b6b98a0770cba090441a828/wrapt-1.17.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9a2bce789a5ea90e51a02dfcc39e31b7f1e662bc3317979aa7e5538e3a034f72", size = 81879 }, + { url = "https://files.pythonhosted.org/packages/8f/fa/9fb6e594f2ce03ef03eddbdb5f4f90acb1452221a5351116c7c4708ac865/wrapt-1.17.2-cp311-cp311-win32.whl", hash = "sha256:4afd5814270fdf6380616b321fd31435a462019d834f83c8611a0ce7484c7317", size = 36419 }, + { url = "https://files.pythonhosted.org/packages/47/f8/fb1773491a253cbc123c5d5dc15c86041f746ed30416535f2a8df1f4a392/wrapt-1.17.2-cp311-cp311-win_amd64.whl", hash = "sha256:acc130bc0375999da18e3d19e5a86403667ac0c4042a094fefb7eec8ebac7cf3", size = 38773 }, + { url = "https://files.pythonhosted.org/packages/a1/bd/ab55f849fd1f9a58ed7ea47f5559ff09741b25f00c191231f9f059c83949/wrapt-1.17.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d5e2439eecc762cd85e7bd37161d4714aa03a33c5ba884e26c81559817ca0925", size = 53799 }, + { url = "https://files.pythonhosted.org/packages/53/18/75ddc64c3f63988f5a1d7e10fb204ffe5762bc663f8023f18ecaf31a332e/wrapt-1.17.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fc7cb4c1c744f8c05cd5f9438a3caa6ab94ce8344e952d7c45a8ed59dd88392", size = 38821 }, + { url = "https://files.pythonhosted.org/packages/48/2a/97928387d6ed1c1ebbfd4efc4133a0633546bec8481a2dd5ec961313a1c7/wrapt-1.17.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8fdbdb757d5390f7c675e558fd3186d590973244fab0c5fe63d373ade3e99d40", size = 38919 }, + { url = "https://files.pythonhosted.org/packages/73/54/3bfe5a1febbbccb7a2f77de47b989c0b85ed3a6a41614b104204a788c20e/wrapt-1.17.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bb1d0dbf99411f3d871deb6faa9aabb9d4e744d67dcaaa05399af89d847a91d", size = 88721 }, + { url = "https://files.pythonhosted.org/packages/25/cb/7262bc1b0300b4b64af50c2720ef958c2c1917525238d661c3e9a2b71b7b/wrapt-1.17.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d18a4865f46b8579d44e4fe1e2bcbc6472ad83d98e22a26c963d46e4c125ef0b", size = 80899 }, + { url = "https://files.pythonhosted.org/packages/2a/5a/04cde32b07a7431d4ed0553a76fdb7a61270e78c5fd5a603e190ac389f14/wrapt-1.17.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc570b5f14a79734437cb7b0500376b6b791153314986074486e0b0fa8d71d98", size = 89222 }, + { url = "https://files.pythonhosted.org/packages/09/28/2e45a4f4771fcfb109e244d5dbe54259e970362a311b67a965555ba65026/wrapt-1.17.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6d9187b01bebc3875bac9b087948a2bccefe464a7d8f627cf6e48b1bbae30f82", size = 86707 }, + { url = "https://files.pythonhosted.org/packages/c6/d2/dcb56bf5f32fcd4bd9aacc77b50a539abdd5b6536872413fd3f428b21bed/wrapt-1.17.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9e8659775f1adf02eb1e6f109751268e493c73716ca5761f8acb695e52a756ae", size = 79685 }, + { url = "https://files.pythonhosted.org/packages/80/4e/eb8b353e36711347893f502ce91c770b0b0929f8f0bed2670a6856e667a9/wrapt-1.17.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e8b2816ebef96d83657b56306152a93909a83f23994f4b30ad4573b00bd11bb9", size = 87567 }, + { url = "https://files.pythonhosted.org/packages/17/27/4fe749a54e7fae6e7146f1c7d914d28ef599dacd4416566c055564080fe2/wrapt-1.17.2-cp312-cp312-win32.whl", hash = "sha256:468090021f391fe0056ad3e807e3d9034e0fd01adcd3bdfba977b6fdf4213ea9", size = 36672 }, + { url = "https://files.pythonhosted.org/packages/15/06/1dbf478ea45c03e78a6a8c4be4fdc3c3bddea5c8de8a93bc971415e47f0f/wrapt-1.17.2-cp312-cp312-win_amd64.whl", hash = "sha256:ec89ed91f2fa8e3f52ae53cd3cf640d6feff92ba90d62236a81e4e563ac0e991", size = 38865 }, + { url = "https://files.pythonhosted.org/packages/ce/b9/0ffd557a92f3b11d4c5d5e0c5e4ad057bd9eb8586615cdaf901409920b14/wrapt-1.17.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6ed6ffac43aecfe6d86ec5b74b06a5be33d5bb9243d055141e8cabb12aa08125", size = 53800 }, + { url = "https://files.pythonhosted.org/packages/c0/ef/8be90a0b7e73c32e550c73cfb2fa09db62234227ece47b0e80a05073b375/wrapt-1.17.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:35621ae4c00e056adb0009f8e86e28eb4a41a4bfa8f9bfa9fca7d343fe94f998", size = 38824 }, + { url = "https://files.pythonhosted.org/packages/36/89/0aae34c10fe524cce30fe5fc433210376bce94cf74d05b0d68344c8ba46e/wrapt-1.17.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a604bf7a053f8362d27eb9fefd2097f82600b856d5abe996d623babd067b1ab5", size = 38920 }, + { url = "https://files.pythonhosted.org/packages/3b/24/11c4510de906d77e0cfb5197f1b1445d4fec42c9a39ea853d482698ac681/wrapt-1.17.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cbabee4f083b6b4cd282f5b817a867cf0b1028c54d445b7ec7cfe6505057cf8", size = 88690 }, + { url = "https://files.pythonhosted.org/packages/71/d7/cfcf842291267bf455b3e266c0c29dcb675b5540ee8b50ba1699abf3af45/wrapt-1.17.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49703ce2ddc220df165bd2962f8e03b84c89fee2d65e1c24a7defff6f988f4d6", size = 80861 }, + { url = "https://files.pythonhosted.org/packages/d5/66/5d973e9f3e7370fd686fb47a9af3319418ed925c27d72ce16b791231576d/wrapt-1.17.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8112e52c5822fc4253f3901b676c55ddf288614dc7011634e2719718eaa187dc", size = 89174 }, + { url = "https://files.pythonhosted.org/packages/a7/d3/8e17bb70f6ae25dabc1aaf990f86824e4fd98ee9cadf197054e068500d27/wrapt-1.17.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9fee687dce376205d9a494e9c121e27183b2a3df18037f89d69bd7b35bcf59e2", size = 86721 }, + { url = "https://files.pythonhosted.org/packages/6f/54/f170dfb278fe1c30d0ff864513cff526d624ab8de3254b20abb9cffedc24/wrapt-1.17.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:18983c537e04d11cf027fbb60a1e8dfd5190e2b60cc27bc0808e653e7b218d1b", size = 79763 }, + { url = "https://files.pythonhosted.org/packages/4a/98/de07243751f1c4a9b15c76019250210dd3486ce098c3d80d5f729cba029c/wrapt-1.17.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:703919b1633412ab54bcf920ab388735832fdcb9f9a00ae49387f0fe67dad504", size = 87585 }, + { url = "https://files.pythonhosted.org/packages/f9/f0/13925f4bd6548013038cdeb11ee2cbd4e37c30f8bfd5db9e5a2a370d6e20/wrapt-1.17.2-cp313-cp313-win32.whl", hash = "sha256:abbb9e76177c35d4e8568e58650aa6926040d6a9f6f03435b7a522bf1c487f9a", size = 36676 }, + { url = "https://files.pythonhosted.org/packages/bf/ae/743f16ef8c2e3628df3ddfd652b7d4c555d12c84b53f3d8218498f4ade9b/wrapt-1.17.2-cp313-cp313-win_amd64.whl", hash = "sha256:69606d7bb691b50a4240ce6b22ebb319c1cfb164e5f6569835058196e0f3a845", size = 38871 }, + { url = "https://files.pythonhosted.org/packages/3d/bc/30f903f891a82d402ffb5fda27ec1d621cc97cb74c16fea0b6141f1d4e87/wrapt-1.17.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:4a721d3c943dae44f8e243b380cb645a709ba5bd35d3ad27bc2ed947e9c68192", size = 56312 }, + { url = "https://files.pythonhosted.org/packages/8a/04/c97273eb491b5f1c918857cd26f314b74fc9b29224521f5b83f872253725/wrapt-1.17.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:766d8bbefcb9e00c3ac3b000d9acc51f1b399513f44d77dfe0eb026ad7c9a19b", size = 40062 }, + { url = "https://files.pythonhosted.org/packages/4e/ca/3b7afa1eae3a9e7fefe499db9b96813f41828b9fdb016ee836c4c379dadb/wrapt-1.17.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e496a8ce2c256da1eb98bd15803a79bee00fc351f5dfb9ea82594a3f058309e0", size = 40155 }, + { url = "https://files.pythonhosted.org/packages/89/be/7c1baed43290775cb9030c774bc53c860db140397047cc49aedaf0a15477/wrapt-1.17.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d615e4fe22f4ad3528448c193b218e077656ca9ccb22ce2cb20db730f8d306", size = 113471 }, + { url = "https://files.pythonhosted.org/packages/32/98/4ed894cf012b6d6aae5f5cc974006bdeb92f0241775addad3f8cd6ab71c8/wrapt-1.17.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a5aaeff38654462bc4b09023918b7f21790efb807f54c000a39d41d69cf552cb", size = 101208 }, + { url = "https://files.pythonhosted.org/packages/ea/fd/0c30f2301ca94e655e5e057012e83284ce8c545df7661a78d8bfca2fac7a/wrapt-1.17.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a7d15bbd2bc99e92e39f49a04653062ee6085c0e18b3b7512a4f2fe91f2d681", size = 109339 }, + { url = "https://files.pythonhosted.org/packages/75/56/05d000de894c4cfcb84bcd6b1df6214297b8089a7bd324c21a4765e49b14/wrapt-1.17.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e3890b508a23299083e065f435a492b5435eba6e304a7114d2f919d400888cc6", size = 110232 }, + { url = "https://files.pythonhosted.org/packages/53/f8/c3f6b2cf9b9277fb0813418e1503e68414cd036b3b099c823379c9575e6d/wrapt-1.17.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:8c8b293cd65ad716d13d8dd3624e42e5a19cc2a2f1acc74b30c2c13f15cb61a6", size = 100476 }, + { url = "https://files.pythonhosted.org/packages/a7/b1/0bb11e29aa5139d90b770ebbfa167267b1fc548d2302c30c8f7572851738/wrapt-1.17.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c82b8785d98cdd9fed4cac84d765d234ed3251bd6afe34cb7ac523cb93e8b4f", size = 106377 }, + { url = "https://files.pythonhosted.org/packages/6a/e1/0122853035b40b3f333bbb25f1939fc1045e21dd518f7f0922b60c156f7c/wrapt-1.17.2-cp313-cp313t-win32.whl", hash = "sha256:13e6afb7fe71fe7485a4550a8844cc9ffbe263c0f1a1eea569bc7091d4898555", size = 37986 }, + { url = "https://files.pythonhosted.org/packages/09/5e/1655cf481e079c1f22d0cabdd4e51733679932718dc23bf2db175f329b76/wrapt-1.17.2-cp313-cp313t-win_amd64.whl", hash = "sha256:eaf675418ed6b3b31c7a989fd007fa7c3be66ce14e5c3b27336383604c9da85c", size = 40750 }, + { url = "https://files.pythonhosted.org/packages/8a/f4/6ed2b8f6f1c832933283974839b88ec7c983fd12905e01e97889dadf7559/wrapt-1.17.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:99039fa9e6306880572915728d7f6c24a86ec57b0a83f6b2491e1d8ab0235b9a", size = 53308 }, + { url = "https://files.pythonhosted.org/packages/a2/a9/712a53f8f4f4545768ac532619f6e56d5d0364a87b2212531685e89aeef8/wrapt-1.17.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2696993ee1eebd20b8e4ee4356483c4cb696066ddc24bd70bcbb80fa56ff9061", size = 38489 }, + { url = "https://files.pythonhosted.org/packages/fa/9b/e172c8f28a489a2888df18f953e2f6cb8d33b1a2e78c9dfc52d8bf6a5ead/wrapt-1.17.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:612dff5db80beef9e649c6d803a8d50c409082f1fedc9dbcdfde2983b2025b82", size = 38776 }, + { url = "https://files.pythonhosted.org/packages/cf/cb/7a07b51762dcd59bdbe07aa97f87b3169766cadf240f48d1cbe70a1be9db/wrapt-1.17.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62c2caa1585c82b3f7a7ab56afef7b3602021d6da34fbc1cf234ff139fed3cd9", size = 83050 }, + { url = "https://files.pythonhosted.org/packages/a5/51/a42757dd41032afd6d8037617aa3bc6803ba971850733b24dfb7d5c627c4/wrapt-1.17.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c958bcfd59bacc2d0249dcfe575e71da54f9dcf4a8bdf89c4cb9a68a1170d73f", size = 74718 }, + { url = "https://files.pythonhosted.org/packages/bf/bb/d552bfe47db02fcfc950fc563073a33500f8108efa5f7b41db2f83a59028/wrapt-1.17.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc78a84e2dfbc27afe4b2bd7c80c8db9bca75cc5b85df52bfe634596a1da846b", size = 82590 }, + { url = "https://files.pythonhosted.org/packages/77/99/77b06b3c3c410dbae411105bf22496facf03a5496bfaca8fbcf9da381889/wrapt-1.17.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ba0f0eb61ef00ea10e00eb53a9129501f52385c44853dbd6c4ad3f403603083f", size = 81462 }, + { url = "https://files.pythonhosted.org/packages/2d/21/cf0bd85ae66f92600829ea1de8e1da778e5e9f6e574ccbe74b66db0d95db/wrapt-1.17.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1e1fe0e6ab7775fd842bc39e86f6dcfc4507ab0ffe206093e76d61cde37225c8", size = 74309 }, + { url = "https://files.pythonhosted.org/packages/6d/16/112d25e9092398a0dd6fec50ab7ac1b775a0c19b428f049785096067ada9/wrapt-1.17.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c86563182421896d73858e08e1db93afdd2b947a70064b813d515d66549e15f9", size = 81081 }, + { url = "https://files.pythonhosted.org/packages/2b/49/364a615a0cc0872685646c495c7172e4fc7bf1959e3b12a1807a03014e05/wrapt-1.17.2-cp39-cp39-win32.whl", hash = "sha256:f393cda562f79828f38a819f4788641ac7c4085f30f1ce1a68672baa686482bb", size = 36423 }, + { url = "https://files.pythonhosted.org/packages/00/ad/5d2c1b34ba3202cd833d9221833e74d6500ce66730974993a8dc9a94fb8c/wrapt-1.17.2-cp39-cp39-win_amd64.whl", hash = "sha256:36ccae62f64235cf8ddb682073a60519426fdd4725524ae38874adf72b5f2aeb", size = 38772 }, + { url = "https://files.pythonhosted.org/packages/2d/82/f56956041adef78f849db6b289b282e72b55ab8045a75abad81898c28d19/wrapt-1.17.2-py3-none-any.whl", hash = "sha256:b18f2d1533a71f069c7f82d524a52599053d4c7166e9dd374ae2136b7f40f7c8", size = 23594 }, +] + +[[package]] +name = "zipp" +version = "3.21.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3f/50/bad581df71744867e9468ebd0bcd6505de3b275e06f202c2cb016e3ff56f/zipp-3.21.0.tar.gz", hash = "sha256:2c9958f6430a2040341a52eb608ed6dd93ef4392e02ffe219417c1b28b5dd1f4", size = 24545 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/1a/7e4798e9339adc931158c9d69ecc34f5e6791489d469f5e50ec15e35f458/zipp-3.21.0-py3-none-any.whl", hash = "sha256:ac1bbe05fd2991f160ebce24ffbac5f6d11d83dc90891255885223d42b3cd931", size = 9630 }, +] From 2c3cf41ccb52d16e9b2c3ee392a4b9353d167448 Mon Sep 17 00:00:00 2001 From: Luca Vivona Date: Fri, 9 May 2025 02:57:51 -0400 Subject: [PATCH 13/37] fix typo in serialize_file doc-string (#594) * fix typo in serialize_file doc-string * update __init__.pyi serialize_file --- bindings/python/py_src/safetensors/__init__.pyi | 6 +++--- bindings/python/src/lib.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/bindings/python/py_src/safetensors/__init__.pyi b/bindings/python/py_src/safetensors/__init__.pyi index 7781229f..fa74b755 100644 --- a/bindings/python/py_src/safetensors/__init__.pyi +++ b/bindings/python/py_src/safetensors/__init__.pyi @@ -36,7 +36,7 @@ def serialize(tensor_dict, metadata=None): @staticmethod def serialize_file(tensor_dict, filename, metadata=None): """ - Serializes raw data. + Serializes raw data into file. Args: tensor_dict (`Dict[str, Dict[Any]]`): @@ -48,8 +48,8 @@ def serialize_file(tensor_dict, filename, metadata=None): The optional purely text annotations Returns: - (`bytes`): - The serialized content. + (`NoneType`): + On success return None. """ pass diff --git a/bindings/python/src/lib.rs b/bindings/python/src/lib.rs index e16d7fdd..be499d5d 100644 --- a/bindings/python/src/lib.rs +++ b/bindings/python/src/lib.rs @@ -127,7 +127,7 @@ fn serialize<'b>( Ok(pybytes) } -/// Serializes raw data. +/// Serializes raw data into file. /// /// Args: /// tensor_dict (`Dict[str, Dict[Any]]`): @@ -139,8 +139,8 @@ fn serialize<'b>( /// The optional purely text annotations /// /// Returns: -/// (`bytes`): -/// The serialized content. +/// (`NoneType`): +/// On success return None #[pyfunction] #[pyo3(signature = (tensor_dict, filename, metadata=None))] fn serialize_file( From c7c2edc8e853134208b339bd2c15d869f73b46f6 Mon Sep 17 00:00:00 2001 From: cychester <40726077+cyc4188@users.noreply.github.com> Date: Fri, 9 May 2025 14:59:18 +0800 Subject: [PATCH 14/37] Remove useless code (#597) --- bindings/python/src/lib.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/bindings/python/src/lib.rs b/bindings/python/src/lib.rs index be499d5d..be8e94e0 100644 --- a/bindings/python/src/lib.rs +++ b/bindings/python/src/lib.rs @@ -14,7 +14,6 @@ use safetensors::View; use std::borrow::Cow; use std::collections::HashMap; use std::fs::File; -use std::iter::FromIterator; use std::ops::Bound; use std::path::PathBuf; use std::sync::Arc; @@ -120,8 +119,7 @@ fn serialize<'b>( metadata: Option>, ) -> PyResult> { let tensors = prepare(tensor_dict)?; - let metadata_map = metadata.map(HashMap::from_iter); - let out = safetensors::tensor::serialize(&tensors, &metadata_map) + let out = safetensors::tensor::serialize(&tensors, &metadata) .map_err(|e| SafetensorError::new_err(format!("Error while serializing: {e:?}")))?; let pybytes = PyBytes::new(py, &out); Ok(pybytes) From c7b18fb2f674a6d35f6a6cec4377061488b9c5c0 Mon Sep 17 00:00:00 2001 From: Nicolas Patry Date: Fri, 9 May 2025 09:03:12 +0200 Subject: [PATCH 15/37] Early bailing when keys mismatch (faster). (#602) * Early bailing when keys mismatch (faster). * Add a few comments. * NIT. * Small fix. --- bindings/python/py_src/safetensors/torch.py | 71 ++++++++++++++++++--- 1 file changed, 61 insertions(+), 10 deletions(-) diff --git a/bindings/python/py_src/safetensors/torch.py b/bindings/python/py_src/safetensors/torch.py index c3477aad..4b6acbca 100644 --- a/bindings/python/py_src/safetensors/torch.py +++ b/bindings/python/py_src/safetensors/torch.py @@ -128,7 +128,10 @@ def _remove_duplicate_names( def save_model( - model: torch.nn.Module, filename: str, metadata: Optional[Dict[str, str]] = None, force_contiguous: bool = True + model: torch.nn.Module, + filename: str, + metadata: Optional[Dict[str, str]] = None, + force_contiguous: bool = True, ): """ Saves a given torch model to specified filename. @@ -174,7 +177,10 @@ def save_model( def load_model( - model: torch.nn.Module, filename: Union[str, os.PathLike], strict: bool = True, device: Union[str, int] = "cpu" + model: torch.nn.Module, + filename: Union[str, os.PathLike], + strict: bool = True, + device: Union[str, int] = "cpu", ) -> Tuple[List[str], List[str]]: """ Loads a given filename onto a torch model. @@ -202,23 +208,68 @@ def load_model( state_dict = load_file(filename, device=device) model_state_dict = model.state_dict() to_removes = _remove_duplicate_names(model_state_dict, preferred_names=state_dict.keys()) - missing, unexpected = model.load_state_dict(state_dict, strict=False) - missing = set(missing) - for to_remove_group in to_removes.values(): + + reverse_to_remove = {} + for key, to_remove_group in to_removes.items(): for to_remove in to_remove_group: - if to_remove not in missing: - unexpected.append(to_remove) - else: - missing.remove(to_remove) - if strict and (missing or unexpected): + reverse_to_remove[to_remove] = key + + # We iterate on the model, so we'll add keys we find missing + # here + missing = set() + # We start with all keys on disk declared as unexpected, we'll + # slowly remove them when we find them + unexpected = set(state_dict.keys()) + # Some keys can be invalid too. + invalid = set() + + for k, mv in model_state_dict.items(): + actual_k = reverse_to_remove.get(k, None) + if actual_k is not None: + look_k = actual_k + else: + look_k = k + v = state_dict.get(look_k, None) + if v is None: + missing.add(k) + else: + # We can actually check for the shapes while we're at it. + # For the device, it's trickier given torch's internals + # There might be some Meta device for faster initiation + if v.dtype != mv.dtype or v.shape != mv.shape: + invalid.add(k) + if actual_k is None: + unexpected.remove(k) + + missing = set(missing) + unexpected = set(unexpected) + if strict and (missing or unexpected or invalid): missing_keys = ", ".join([f'"{k}"' for k in sorted(missing)]) unexpected_keys = ", ".join([f'"{k}"' for k in sorted(unexpected)]) + invalid_keys = ", ".join([f'"{k}"' for k in sorted(invalid)]) error = f"Error(s) in loading state_dict for {model.__class__.__name__}:" if missing: error += f"\n Missing key(s) in state_dict: {missing_keys}" if unexpected: error += f"\n Unexpected key(s) in state_dict: {unexpected_keys}" + if invalid: + error += f"\n Invalid key(s) in state_dict: {invalid_keys}, mismatched dtypes or shape." + del state_dict raise RuntimeError(error) + + torch_missing, torch_unexpected = model.load_state_dict(state_dict, strict=False) + # Sanity check that the work we've done matches + # Pytorch internal loading. + torch_missing = set(torch_missing) + torch_unexpected = set(torch_unexpected) + for to_remove_group in to_removes.values(): + for to_remove in to_remove_group: + if to_remove not in torch_missing: + torch_unexpected.add(to_remove) + else: + torch_missing.remove(to_remove) + assert torch_missing == missing, f"{torch_missing} != {missing}" + assert torch_unexpected == unexpected, f"{torch_unexpected} != {unexpected}" return missing, unexpected From f6f9755793b7a38be0ae30de86db5f9772146fd6 Mon Sep 17 00:00:00 2001 From: Nicolas Patry Date: Fri, 9 May 2025 09:46:35 +0200 Subject: [PATCH 16/37] Fixing the ml_dtypes potentially missing. (#605) Co-authored-by: Daniel Bershatsky --- bindings/python/src/lib.rs | 35 ++++++++++++++----- bindings/python/tests/test_flax_comparison.py | 9 +++++ 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/bindings/python/src/lib.rs b/bindings/python/src/lib.rs index be8e94e0..2765dc09 100644 --- a/bindings/python/src/lib.rs +++ b/bindings/python/src/lib.rs @@ -1057,15 +1057,32 @@ fn create_tensor<'a>( .bind(py), false, ), - _ => ( - NUMPY_MODULE - .get() - .ok_or_else(|| { - SafetensorError::new_err(format!("Could not find module {framework:?}",)) - })? - .bind(py), - true, - ), + frame => { + // Attempt to load the frameworks + // Those are needed to prepare the ml dtypes + // like bfloat16 + match frame { + Framework::Tensorflow => { + let _ = PyModule::import(py, intern!(py, "tensorflow")); + } + Framework::Flax => { + let _ = PyModule::import(py, intern!(py, "flax")); + } + _ => {} + }; + + ( + NUMPY_MODULE + .get() + .ok_or_else(|| { + SafetensorError::new_err( + format!("Could not find module {framework:?}",), + ) + })? + .bind(py), + true, + ) + } }; let dtype: PyObject = get_pydtype(module, dtype, is_numpy)?; let count: usize = shape.iter().product(); diff --git a/bindings/python/tests/test_flax_comparison.py b/bindings/python/tests/test_flax_comparison.py index c54241ad..ff091a32 100644 --- a/bindings/python/tests/test_flax_comparison.py +++ b/bindings/python/tests/test_flax_comparison.py @@ -1,5 +1,6 @@ import platform import unittest +import sys if platform.system() != "Windows": @@ -66,3 +67,11 @@ def test_deserialization_safe_open(self): for k, v in weights.items(): tv = flax_weights[k] self.assertTrue(jnp.allclose(v, tv)) + + def test_loading_without_ml_dtype(self): + # This does not work as we cannot unload + # modules, copy this into its own file to test. + # https://github.com/huggingface/safetensors/issues/598 + sys.modules.pop("ml_dtypes", None) + with safe_open(self.sf_filename, framework="flax") as f: + f.get_tensor("test3") From bca53e3e178b9e1279c8d32302cdbbdcd4ce4842 Mon Sep 17 00:00:00 2001 From: Nicolas Patry Date: Fri, 9 May 2025 10:05:54 +0200 Subject: [PATCH 17/37] Adding the License to wheels. (#606) * Adding the License to wheels. * Adding the License without path traversal. --- bindings/python/LICENSE | 201 +++++++++++++++++++++++++++++++++ bindings/python/pyproject.toml | 2 +- 2 files changed, 202 insertions(+), 1 deletion(-) create mode 100644 bindings/python/LICENSE diff --git a/bindings/python/LICENSE b/bindings/python/LICENSE new file mode 100644 index 00000000..261eeb9e --- /dev/null +++ b/bindings/python/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/bindings/python/pyproject.toml b/bindings/python/pyproject.toml index f68234a1..1409126a 100644 --- a/bindings/python/pyproject.toml +++ b/bindings/python/pyproject.toml @@ -19,9 +19,9 @@ classifiers = [ "Topic :: Scientific/Engineering :: Artificial Intelligence", "Typing :: Typed", ] +license = { file = "LICENSE" } dynamic = [ 'description', - 'license', 'readme', 'version', ] From e1e3395897c3bf6e8e520c9781c4005babbdfa2e Mon Sep 17 00:00:00 2001 From: Nicolas Patry Date: Sun, 15 Jun 2025 09:08:43 +0000 Subject: [PATCH 18/37] Adding a public API for metadata. (#618) * Adding a public API for metadata. * Validate doesn't need to be public. --- safetensors/src/tensor.rs | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/safetensors/src/tensor.rs b/safetensors/src/tensor.rs index 1da1278c..a5100349 100644 --- a/safetensors/src/tensor.rs +++ b/safetensors/src/tensor.rs @@ -314,8 +314,9 @@ impl<'data> SafeTensors<'data> { // if !string.starts_with('{') { // return Err(SafeTensorError::InvalidHeaderStart); // } - let metadata: Metadata = serde_json::from_str(string) + let metadata: HashMetadata = serde_json::from_str(string) .map_err(|_| SafeTensorError::InvalidHeaderDeserialization)?; + let metadata: Metadata = metadata.try_into()?; let buffer_end = metadata.validate()?; if buffer_end + 8 + n != buffer_len { return Err(SafeTensorError::MetadataIncompleteBuffer); @@ -442,12 +443,9 @@ struct HashMetadata { tensors: HashMap, } -impl<'de> Deserialize<'de> for Metadata { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - let hashdata: HashMetadata = HashMetadata::deserialize(deserializer)?; +impl TryFrom for Metadata { + type Error = SafeTensorError; + fn try_from(hashdata: HashMetadata) -> Result { let (metadata, tensors) = (hashdata.metadata, hashdata.tensors); let mut tensors: Vec<_> = tensors.into_iter().collect(); // We need to sort by offsets @@ -455,7 +453,19 @@ impl<'de> Deserialize<'de> for Metadata { // Than we expect (Not aligned ordered, but purely name ordered, // or actually any order). tensors.sort_by(|(_, left), (_, right)| left.data_offsets.cmp(&right.data_offsets)); - Metadata::new(metadata, tensors).map_err(serde::de::Error::custom) + Metadata::new(metadata, tensors) + } +} + +impl<'de> Deserialize<'de> for Metadata { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let hashdata: HashMetadata = HashMetadata::deserialize(deserializer)?; + + let metadata: Metadata = hashdata.try_into().map_err(serde::de::Error::custom)?; + Ok(metadata) } } @@ -487,7 +497,10 @@ impl Serialize for Metadata { } impl Metadata { - fn new( + /// Creates a new metadata structure. + /// May fail if there is incorrect data in the Tensor Info. + /// Notably the tensors need to be ordered by increasing data_offsets. + pub fn new( metadata: Option>, tensors: Vec<(String, TensorInfo)>, ) -> Result { @@ -507,7 +520,7 @@ impl Metadata { tensors, index_map, }; - // metadata.validate()?; + metadata.validate()?; Ok(metadata) } @@ -1249,7 +1262,7 @@ mod tests { Err(SafeTensorError::TensorInvalidInfo) => { // Yes we have the correct error } - _ => panic!("This should not be able to be deserialized"), + something => panic!("This should not be able to be deserialized got {something:?}"), } } From 1e2ccaa741013ae9a12dd8515aca0607004c52e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81rp=C3=A1d=20Goretity=20=EF=A3=BF?= Date: Sun, 15 Jun 2025 11:09:20 +0200 Subject: [PATCH 19/37] Update dependencies and replace deprecated `black_box()` with its std equivalent (#614) --- bindings/python/Cargo.toml | 2 +- safetensors/Cargo.toml | 8 ++++---- safetensors/benches/benchmark.rs | 3 ++- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/bindings/python/Cargo.toml b/bindings/python/Cargo.toml index 301cc9e7..c1440f20 100644 --- a/bindings/python/Cargo.toml +++ b/bindings/python/Cargo.toml @@ -10,7 +10,7 @@ name = "safetensors_rust" crate-type = ["cdylib"] [dependencies] -pyo3 = { version = "0.24", features = ["abi3", "abi3-py38"] } +pyo3 = { version = "0.25", features = ["abi3", "abi3-py38"] } memmap2 = "0.9" serde_json = "1.0" diff --git a/safetensors/Cargo.toml b/safetensors/Cargo.toml index dd303d65..139a99de 100644 --- a/safetensors/Cargo.toml +++ b/safetensors/Cargo.toml @@ -2,7 +2,7 @@ name = "safetensors" version = "0.5.3-dev.0" edition = "2021" -rust-version = "1.74" +rust-version = "1.80" homepage = "https://github.com/huggingface/safetensors" repository = "https://github.com/huggingface/safetensors" documentation = "https://docs.rs/safetensors/" @@ -22,14 +22,14 @@ exclude = [ "rust-toolchain", "target/*", "Cargo.lock"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -hashbrown = { version = "0.15.2", features = ["serde"], optional = true } +hashbrown = { version = "0.15.4", features = ["serde"], optional = true } serde = { version = "1.0", default-features = false, features = ["derive"] } serde_json = { version = "1.0", default-features = false } [dev-dependencies] -criterion = "0.5" +criterion = "0.6" memmap2 = "0.9" -proptest = "1.4" +proptest = "1.7" [features] default = ["std"] diff --git a/safetensors/benches/benchmark.rs b/safetensors/benches/benchmark.rs index 8bb490a4..a8b7bc37 100644 --- a/safetensors/benches/benchmark.rs +++ b/safetensors/benches/benchmark.rs @@ -1,6 +1,7 @@ -use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use criterion::{criterion_group, criterion_main, Criterion}; use safetensors::tensor::*; use std::collections::HashMap; +use std::hint::black_box; // Returns a sample data of size 2_MB fn get_sample_data() -> (Vec, Vec, Dtype) { From 30122417236e0deafa35001bc8f92dbd34c18c77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81rp=C3=A1d=20Goretity=20=EF=A3=BF?= Date: Sun, 15 Jun 2025 11:11:36 +0200 Subject: [PATCH 20/37] Better error handling through improved `Display` and `Error` impls (#616) * Better error handling: reliable `Display` impls and more useful `Error` impls * Reliable `Display` impls and improved error formatting in Python bindings * Remove some remaining instances of unwarranted `{:?}` formtting --------- Co-authored-by: Nicolas Patry --- bindings/python/src/lib.rs | 100 +++++++++++++++++++++---------------- safetensors/src/slice.rs | 33 +++++++++--- safetensors/src/tensor.rs | 87 ++++++++++++++++++++++++++++---- 3 files changed, 159 insertions(+), 61 deletions(-) diff --git a/bindings/python/src/lib.rs b/bindings/python/src/lib.rs index 2765dc09..28c95121 100644 --- a/bindings/python/src/lib.rs +++ b/bindings/python/src/lib.rs @@ -49,20 +49,20 @@ impl View for &PyView<'_> { fn prepare(tensor_dict: HashMap>) -> PyResult> { let mut tensors = HashMap::with_capacity(tensor_dict.len()); - for (tensor_name, tensor_desc) in &tensor_dict { + for (tensor_name, tensor_desc) in tensor_dict { let shape: Vec = tensor_desc .get_item("shape")? - .ok_or_else(|| SafetensorError::new_err(format!("Missing `shape` in {tensor_desc:?}")))? + .ok_or_else(|| SafetensorError::new_err(format!("Missing `shape` in {tensor_desc}")))? .extract()?; let pydata: PyBound = tensor_desc.get_item("data")?.ok_or_else(|| { - SafetensorError::new_err(format!("Missing `data` in {tensor_desc:?}")) + SafetensorError::new_err(format!("Missing `data` in {tensor_desc}")) })?; // Make sure it's extractable first. let data: &[u8] = pydata.extract()?; let data_len = data.len(); let data: PyBound = pydata.extract()?; let pydtype = tensor_desc.get_item("dtype")?.ok_or_else(|| { - SafetensorError::new_err(format!("Missing `dtype` in {tensor_desc:?}")) + SafetensorError::new_err(format!("Missing `dtype` in {tensor_desc}")) })?; let dtype: String = pydtype.extract()?; let dtype = match dtype.as_ref() { @@ -94,7 +94,7 @@ fn prepare(tensor_dict: HashMap>) -> PyResult( ) -> PyResult> { let tensors = prepare(tensor_dict)?; let out = safetensors::tensor::serialize(&tensors, &metadata) - .map_err(|e| SafetensorError::new_err(format!("Error while serializing: {e:?}")))?; + .map_err(|e| SafetensorError::new_err(format!("Error while serializing: {e}")))?; let pybytes = PyBytes::new(py, &out); Ok(pybytes) } @@ -147,8 +147,10 @@ fn serialize_file( metadata: Option>, ) -> PyResult<()> { let tensors = prepare(tensor_dict)?; + safetensors::tensor::serialize_to_file(&tensors, &metadata, filename.as_path()) - .map_err(|e| SafetensorError::new_err(format!("Error while serializing: {e:?}")))?; + .map_err(|e| SafetensorError::new_err(format!("Error while serializing: {e}")))?; + Ok(()) } @@ -166,14 +168,14 @@ fn serialize_file( #[pyo3(signature = (bytes))] fn deserialize(py: Python, bytes: &[u8]) -> PyResult)>> { let safetensor = SafeTensors::deserialize(bytes) - .map_err(|e| SafetensorError::new_err(format!("Error while deserializing: {e:?}")))?; + .map_err(|e| SafetensorError::new_err(format!("Error while deserializing: {e}")))?; let tensors = safetensor.tensors(); let mut items = Vec::with_capacity(tensors.len()); for (tensor_name, tensor) in tensors { let pyshape: PyObject = PyList::new(py, tensor.shape().iter())?.into(); - let pydtype: PyObject = format!("{:?}", tensor.dtype()).into_pyobject(py)?.into(); + let pydtype: PyObject = tensor.dtype().to_string().into_pyobject(py)?.into(); let pydata: PyObject = PyByteArray::new(py, tensor.data()).into(); @@ -233,6 +235,18 @@ enum Framework { Mlx, } +impl fmt::Display for Framework { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(match *self { + Framework::Pytorch => "pytorch", + Framework::Numpy => "numpy", + Framework::Tensorflow => "tensorflow", + Framework::Flax => "flax", + Framework::Mlx => "mlx", + }) + } +} + impl<'source> FromPyObject<'source> for Framework { fn extract_bound(ob: &PyBound<'source, PyAny>) -> PyResult { let name: String = ob.extract()?; @@ -272,12 +286,28 @@ enum Device { Anonymous(usize), } + +impl fmt::Display for Device { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + Device::Cpu => write!(f, "cpu"), + Device::Mps => write!(f, "mps"), + Device::Cuda(index) => write!(f, "cuda:{index}"), + Device::Npu(index) => write!(f, "npu:{index}"), + Device::Xpu(index) => write!(f, "xpu:{index}"), + Device::Xla(index) => write!(f, "xla:{index}"), + Device::Mlu(index) => write!(f, "mlu:{index}"), + Device::Hpu(index) => write!(f, "hpu:{index}"), + Device::Anonymous(index) => write!(f, "{index}"), + } + } +} + /// Parsing the device index. fn parse_device(name: &str) -> PyResult { let tokens: Vec<_> = name.split(':').collect(); - if tokens.len() == 2 { - let device: usize = tokens[1].parse()?; - Ok(device) + if let Ok([_, token]) = <[_; 2]>::try_from(tokens) { + Ok(token.parse()?) } else { Err(SafetensorError::new_err(format!( "device {name} is invalid" @@ -288,7 +318,7 @@ fn parse_device(name: &str) -> PyResult { impl<'source> FromPyObject<'source> for Device { fn extract_bound(ob: &PyBound<'source, PyAny>) -> PyResult { if let Ok(name) = ob.extract::() { - match &name[..] { + match name.as_str() { "cpu" => Ok(Device::Cpu), "cuda" => Ok(Device::Cuda(0)), "mps" => Ok(Device::Mps), @@ -321,17 +351,7 @@ impl<'py> IntoPyObject<'py> for Device { type Error = std::convert::Infallible; fn into_pyobject(self, py: Python<'py>) -> Result { - match self { - Device::Cpu => "cpu".into_pyobject(py).map(|x| x.into_any()), - Device::Cuda(n) => format!("cuda:{n}").into_pyobject(py).map(|x| x.into_any()), - Device::Mps => "mps".into_pyobject(py).map(|x| x.into_any()), - Device::Npu(n) => format!("npu:{n}").into_pyobject(py).map(|x| x.into_any()), - Device::Xpu(n) => format!("xpu:{n}").into_pyobject(py).map(|x| x.into_any()), - Device::Xla(n) => format!("xla:{n}").into_pyobject(py).map(|x| x.into_any()), - Device::Mlu(n) => format!("mlu:{n}").into_pyobject(py).map(|x| x.into_any()), - Device::Hpu(n) => format!("hpu:{n}").into_pyobject(py).map(|x| x.into_any()), - Device::Anonymous(n) => n.into_pyobject(py).map(|x| x.into_any()), - } + self.to_string().into_pyobject(py).map(pyo3::BoundObject::into_any) } } @@ -397,13 +417,13 @@ struct Open { impl Open { fn new(filename: PathBuf, framework: Framework, device: Option) -> PyResult { let file = File::open(&filename).map_err(|_| { - PyFileNotFoundError::new_err(format!("No such file or directory: {filename:?}")) + PyFileNotFoundError::new_err(format!("No such file or directory: {}", filename.display())) })?; let device = device.unwrap_or(Device::Cpu); if device != Device::Cpu && framework != Framework::Pytorch { return Err(SafetensorError::new_err(format!( - "Device {device:?} is not support for framework {framework:?}", + "Device {device} is not supported for framework {framework}", ))); } @@ -412,7 +432,7 @@ impl Open { let buffer = unsafe { MmapOptions::new().map_copy_read_only(&file)? }; let (n, metadata) = SafeTensors::read_metadata(&buffer).map_err(|e| { - SafetensorError::new_err(format!("Error while deserializing header: {e:?}")) + SafetensorError::new_err(format!("Error while deserializing header: {e}")) })?; let offset = n + 8; @@ -446,7 +466,7 @@ impl Open { let py_filename: PyObject = filename .to_str() .ok_or_else(|| { - SafetensorError::new_err(format!("Path {filename:?} is not a string")) + SafetensorError::new_err(format!("Path {} is not valid UTF-8", filename.display())) })? .into_pyobject(py)? .into(); @@ -519,8 +539,7 @@ impl Open { /// (`List[str]`): /// The name of the tensors contained in that file pub fn offset_keys(&self) -> PyResult> { - let keys: Vec = self.metadata.offset_keys(); - Ok(keys) + Ok(self.metadata.offset_keys()) } /// Returns a full tensor @@ -823,11 +842,7 @@ impl fmt::Display for Disp { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "[")?; for (i, item) in self.0.iter().enumerate() { - if i != self.0.len() - 1 { - write!(f, "{item}, ")?; - } else { - write!(f, "{item}")?; - } + write!(f, "{prefix}{item}", prefix = if i == 0 { "" } else { ", " })?; } write!(f, "]") } @@ -872,9 +887,7 @@ impl PySafeSlice { /// dtype = tslice.get_dtype() # "F32" /// ``` pub fn get_dtype(&self, py: Python) -> PyResult { - let dtype = self.info.dtype; - let dtype: PyObject = format!("{:?}", dtype).into_pyobject(py)?.into(); - Ok(dtype) + Ok(self.info.dtype.to_string().into_pyobject(py)?.into()) } pub fn __getitem__(&self, slices: &PyBound<'_, PyAny>) -> PyResult { @@ -904,7 +917,7 @@ impl PySafeSlice { let tensor = TensorView::new(self.info.dtype, self.info.shape.clone(), data) .map_err(|e| { - SafetensorError::new_err(format!("Error preparing tensor view: {e:?}")) + SafetensorError::new_err(format!("Error preparing tensor view: {e}")) })?; let slices: Vec = slices .into_iter() @@ -915,10 +928,9 @@ impl PySafeSlice { let iterator = tensor.sliced_data(&slices).map_err(|e| { SafetensorError::new_err(format!( - "Error during slicing {} with shape {:?}: {:?}", + "Error during slicing {} with shape {:?}: {e}", Disp(slices), self.info.shape, - e )) })?; let newshape = iterator.newshape(); @@ -1052,7 +1064,7 @@ fn create_tensor<'a>( TORCH_MODULE .get() .ok_or_else(|| { - SafetensorError::new_err(format!("Could not find module {framework:?}",)) + SafetensorError::new_err(format!("Could not find module {framework}",)) })? .bind(py), false, @@ -1076,7 +1088,7 @@ fn create_tensor<'a>( .get() .ok_or_else(|| { SafetensorError::new_err( - format!("Could not find module {framework:?}",), + format!("Could not find module {framework}",), ) })? .bind(py), @@ -1198,7 +1210,7 @@ fn get_pydtype(module: &PyBound<'_, PyModule>, dtype: Dtype, is_numpy: bool) -> Dtype::F8_E5M2 => module.getattr(intern!(py, "float8_e5m2"))?.into(), dtype => { return Err(SafetensorError::new_err(format!( - "Dtype not understood: {dtype:?}" + "Dtype not understood: {dtype}" ))) } }; diff --git a/safetensors/src/slice.rs b/safetensors/src/slice.rs index 9f9ee8d3..485f0828 100644 --- a/safetensors/src/slice.rs +++ b/safetensors/src/slice.rs @@ -1,9 +1,10 @@ //! Module handling lazy loading via iterating on slices on the original buffer. -use crate::lib::{String, ToString, Vec}; +use crate::lib::Vec; use crate::tensor::TensorView; use core::ops::{ Bound, Range, RangeBounds, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive, }; +use core::fmt::Display; /// Error representing invalid slicing attempt #[derive(Debug)] @@ -22,6 +23,25 @@ pub enum InvalidSlice { }, } +impl Display for InvalidSlice { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match *self { + InvalidSlice::TooManySlices => { + write!(f, "more slicing indexes than dimensions in tensor") + } + InvalidSlice::SliceOutOfRange { dim_index, asked, dim_size } => { + write!(f, "index {asked} out of bounds for tensor dimension #{dim_index} of size {dim_size}") + } + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for InvalidSlice {} + +#[cfg(not(feature = "std"))] +impl core::error::Error for InvalidSlice {} + #[derive(Debug, Clone)] /// Generic structure used to index a slice of the tensor pub enum TensorIndexer { @@ -29,19 +49,18 @@ pub enum TensorIndexer { Select(usize), /// This is a regular slice, purely indexing a chunk of the tensor Narrow(Bound, Bound), - //IndexSelect(Tensor), } -fn display_bound(bound: &Bound) -> String { +fn display_bound(bound: &Bound) -> &dyn Display { match bound { - Bound::Unbounded => "".to_string(), - Bound::Excluded(n) => format!("{n}"), - Bound::Included(n) => format!("{n}"), + Bound::Unbounded => &"", + Bound::Excluded(n) => n, + Bound::Included(n) => n, } } /// Intended for Python users mostly or at least for its conventions -impl core::fmt::Display for TensorIndexer { +impl Display for TensorIndexer { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { TensorIndexer::Select(n) => { diff --git a/safetensors/src/tensor.rs b/safetensors/src/tensor.rs index a5100349..9546b5b5 100644 --- a/safetensors/src/tensor.rs +++ b/safetensors/src/tensor.rs @@ -2,6 +2,8 @@ use crate::lib::{Cow, HashMap, String, ToString, Vec}; use crate::slice::{InvalidSlice, SliceIterator, TensorIndexer}; use serde::{ser::SerializeMap, Deserialize, Deserializer, Serialize, Serializer}; +use core::fmt::Display; +use core::str::Utf8Error; #[cfg(feature = "std")] use std::io::Write; @@ -12,11 +14,11 @@ const MAX_HEADER_SIZE: usize = 100_000_000; #[derive(Debug)] pub enum SafeTensorError { /// The header is an invalid UTF-8 string and cannot be read. - InvalidHeader, + InvalidHeader(Utf8Error), /// The header's first byte is not the expected `{`. InvalidHeaderStart, /// The header does contain a valid string, but it is not valid JSON. - InvalidHeaderDeserialization, + InvalidHeaderDeserialization(serde_json::Error), /// The header is large than 100Mo which is considered too large (Might evolve in the future). HeaderTooLarge, /// The header is smaller than 8 bytes @@ -58,17 +60,60 @@ impl From for SafeTensorError { } } -impl core::fmt::Display for SafeTensorError { +impl Display for SafeTensorError { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!(f, "{self:?}") + use SafeTensorError::*; + + match self { + InvalidHeader(error) => write!(f, "invalid UTF-8 in header: {error}"), + InvalidHeaderStart => write!(f, "invalid start character in header, must be `{{`"), + InvalidHeaderDeserialization(error) => write!(f, "invalid JSON in header: {error}"), + JsonError(error) => write!(f, "JSON error: {error}"), + HeaderTooLarge => write!(f, "header too large"), + HeaderTooSmall => write!(f, "header too small"), + InvalidHeaderLength => write!(f, "invalid header length"), + TensorNotFound(name) => write!(f, "tensor `{name}` not found"), + TensorInvalidInfo => write!(f, "invalid shape, data type, or offset for tensor"), + InvalidOffset(name) => write!(f, "invalid offset for tensor `{name}`"), + #[cfg(feature = "std")] + IoError(error) => write!(f, "I/O error: {error}"), + InvalidTensorView(dtype, shape, n_bytes) => { + write!(f, "tensor of type {dtype} and shape (")?; + for (i, &dim) in shape.iter().enumerate() { + write!(f, "{sep}{dim}", sep = if i == 0 { "" } else { ", " })?; + } + write!(f, ") can't be created from {n_bytes} bytes") + } + MetadataIncompleteBuffer => write!(f, "incomplete metadata, file not fully covered"), + ValidationOverflow => write!(f, "overflow computing buffer size from shape and/or element type"), + } } } #[cfg(not(feature = "std"))] -impl core::error::Error for SafeTensorError {} +impl core::error::Error for SafeTensorError { + fn source(&self) -> Option<&(dyn core::error::Error + 'static)> { + match self { + SafeTensorError::InvalidHeader(source) => Some(source), + SafeTensorError::JsonError(source) => Some(source), + SafeTensorError::InvalidHeaderDeserialization(source) => Some(source), + _ => None, + } + } +} #[cfg(feature = "std")] -impl std::error::Error for SafeTensorError {} +impl std::error::Error for SafeTensorError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + SafeTensorError::InvalidHeader(source) => Some(source), + SafeTensorError::JsonError(source) => Some(source), + SafeTensorError::InvalidHeaderDeserialization(source) => Some(source), + SafeTensorError::IoError(source) => Some(source), + _ => None, + } + } +} struct PreparedData { n: u64, @@ -308,14 +353,14 @@ impl<'data> SafeTensors<'data> { return Err(SafeTensorError::InvalidHeaderLength); } let string = - core::str::from_utf8(&buffer[8..stop]).map_err(|_| SafeTensorError::InvalidHeader)?; + core::str::from_utf8(&buffer[8..stop]).map_err(SafeTensorError::InvalidHeader)?; // Assert the string starts with { // NOTE: Add when we move to 0.4.0 // if !string.starts_with('{') { // return Err(SafeTensorError::InvalidHeaderStart); // } let metadata: HashMetadata = serde_json::from_str(string) - .map_err(|_| SafeTensorError::InvalidHeaderDeserialization)?; + .map_err(SafeTensorError::InvalidHeaderDeserialization)?; let metadata: Metadata = metadata.try_into()?; let buffer_end = metadata.validate()?; if buffer_end + 8 + n != buffer_len { @@ -739,6 +784,28 @@ impl Dtype { } } +impl Display for Dtype { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.write_str(match *self { + Dtype::BOOL => "BOOL", + Dtype::I8 => "I8", + Dtype::U8 => "U8", + Dtype::F8_E5M2 => "F8_E5M2", + Dtype::F8_E4M3 => "F8_E4M3", + Dtype::I16 => "I16", + Dtype::U16 => "U16", + Dtype::I32 => "I32", + Dtype::U32 => "U32", + Dtype::I64 => "I64", + Dtype::U64 => "U64", + Dtype::F16 => "F16", + Dtype::BF16 => "BF16", + Dtype::F32 => "F32", + Dtype::F64 => "F64", + }) + } +} + #[cfg(test)] mod tests { use super::*; @@ -1204,7 +1271,7 @@ mod tests { fn test_invalid_header_non_utf8() { let serialized = b"\x01\x00\x00\x00\x00\x00\x00\x00\xff"; match SafeTensors::deserialize(serialized) { - Err(SafeTensorError::InvalidHeader) => { + Err(SafeTensorError::InvalidHeader(_)) => { // Yes we have the correct error } _ => panic!("This should not be able to be deserialized"), @@ -1215,7 +1282,7 @@ mod tests { fn test_invalid_header_not_json() { let serialized = b"\x01\x00\x00\x00\x00\x00\x00\x00{"; match SafeTensors::deserialize(serialized) { - Err(SafeTensorError::InvalidHeaderDeserialization) => { + Err(SafeTensorError::InvalidHeaderDeserialization(_)) => { // Yes we have the correct error } _ => panic!("This should not be able to be deserialized"), From 573305dc90aac0468dec3e26e76c02bec8da9e34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81rp=C3=A1d=20Goretity=20=EF=A3=BF?= Date: Sun, 15 Jun 2025 11:13:37 +0200 Subject: [PATCH 21/37] Do not force `&Option` in public API; use `Option<&T>` instead (#617) Co-authored-by: Nicolas Patry --- bindings/python/src/lib.rs | 4 ++-- safetensors/benches/benchmark.rs | 4 ++-- safetensors/src/tensor.rs | 25 ++++++++++++------------- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/bindings/python/src/lib.rs b/bindings/python/src/lib.rs index 28c95121..7886da2f 100644 --- a/bindings/python/src/lib.rs +++ b/bindings/python/src/lib.rs @@ -119,7 +119,7 @@ fn serialize<'b>( metadata: Option>, ) -> PyResult> { let tensors = prepare(tensor_dict)?; - let out = safetensors::tensor::serialize(&tensors, &metadata) + let out = safetensors::tensor::serialize(&tensors, metadata) .map_err(|e| SafetensorError::new_err(format!("Error while serializing: {e}")))?; let pybytes = PyBytes::new(py, &out); Ok(pybytes) @@ -148,7 +148,7 @@ fn serialize_file( ) -> PyResult<()> { let tensors = prepare(tensor_dict)?; - safetensors::tensor::serialize_to_file(&tensors, &metadata, filename.as_path()) + safetensors::tensor::serialize_to_file(&tensors, metadata, filename.as_path()) .map_err(|e| SafetensorError::new_err(format!("Error while serializing: {e}")))?; Ok(()) diff --git a/safetensors/benches/benchmark.rs b/safetensors/benches/benchmark.rs index a8b7bc37..46c1a50a 100644 --- a/safetensors/benches/benchmark.rs +++ b/safetensors/benches/benchmark.rs @@ -26,7 +26,7 @@ pub fn bench_serialize(c: &mut Criterion) { c.bench_function("Serialize 10_MB", |b| { b.iter(|| { - let _serialized = serialize(black_box(&metadata), black_box(&None)); + let _serialized = serialize(black_box(&metadata), black_box(None)); }) }); } @@ -42,7 +42,7 @@ pub fn bench_deserialize(c: &mut Criterion) { metadata.insert(format!("weight{i}"), tensor); } - let out = serialize(&metadata, &None).unwrap(); + let out = serialize(&metadata, None).unwrap(); c.bench_function("Deserialize 10_MB", |b| { b.iter(|| { diff --git a/safetensors/src/tensor.rs b/safetensors/src/tensor.rs index 9546b5b5..f97a8c92 100644 --- a/safetensors/src/tensor.rs +++ b/safetensors/src/tensor.rs @@ -215,8 +215,7 @@ pub trait View { fn prepare + Ord + core::fmt::Display, V: View, I: IntoIterator>( data: I, - data_info: &Option>, - // ) -> Result<(Metadata, Vec<&'hash TensorView<'data>>, usize), SafeTensorError> { + data_info: Option>, ) -> Result<(PreparedData, Vec), SafeTensorError> { // Make sure we're sorting by descending dtype alignment // Then by name @@ -241,7 +240,7 @@ fn prepare + Ord + core::fmt::Display, V: View, I: IntoIterator, >( data: I, - data_info: &Option>, + data_info: Option>, ) -> Result, SafeTensorError> { let ( PreparedData { @@ -296,7 +295,7 @@ pub fn serialize_to_file< I: IntoIterator, >( data: I, - data_info: &Option>, + data_info: Option>, filename: &std::path::Path, ) -> Result<(), SafeTensorError> { let ( @@ -910,7 +909,7 @@ mod tests { let data: Vec = (0..data_size(&metadata)).map(|x| x as u8).collect(); let before = SafeTensors { metadata, data: &data }; let tensors = before.tensors(); - let bytes = serialize(tensors.iter().map(|(name, view)| (name.to_string(), view)), &None).unwrap(); + let bytes = serialize(tensors.iter().map(|(name, view)| (name.to_string(), view)), None).unwrap(); let after = SafeTensors::deserialize(&bytes).unwrap(); @@ -936,7 +935,7 @@ mod tests { let metadata: HashMap = [("attn.0".to_string(), attn_0)].into_iter().collect(); - let out = serialize(&metadata, &None).unwrap(); + let out = serialize(&metadata, None).unwrap(); assert_eq!( out, [ @@ -954,7 +953,7 @@ mod tests { fn test_empty() { let tensors: HashMap = HashMap::new(); - let out = serialize(&tensors, &None).unwrap(); + let out = serialize(&tensors, None).unwrap(); assert_eq!( out, [8, 0, 0, 0, 0, 0, 0, 0, 123, 125, 32, 32, 32, 32, 32, 32] @@ -966,7 +965,7 @@ mod tests { .into_iter() .collect(), ); - let out = serialize(&tensors, &metadata).unwrap(); + let out = serialize(&tensors, metadata).unwrap(); assert_eq!( out, [ @@ -990,7 +989,7 @@ mod tests { // Smaller string to force misalignment compared to previous test. [("attn0".to_string(), attn_0)].into_iter().collect(); - let out = serialize(&metadata, &None).unwrap(); + let out = serialize(&metadata, None).unwrap(); assert_eq!( out, [ @@ -1023,7 +1022,7 @@ mod tests { let metadata: HashMap = [("attn.0".to_string(), attn_0)].into_iter().collect(); - let out = serialize(&metadata, &None).unwrap(); + let out = serialize(&metadata, None).unwrap(); let parsed = SafeTensors::deserialize(&out).unwrap(); let out_buffer: Vec = parsed @@ -1109,7 +1108,7 @@ mod tests { let filename = format!("./out_{model_id}.safetensors"); - let out = serialize(&metadata, &None).unwrap(); + let out = serialize(&metadata, None).unwrap(); std::fs::write(&filename, out).unwrap(); let raw = std::fs::read(&filename).unwrap(); let _deserialized = SafeTensors::deserialize(&raw).unwrap(); @@ -1118,7 +1117,7 @@ mod tests { // File api #[cfg(feature = "std")] { - serialize_to_file(&metadata, &None, std::path::Path::new(&filename)).unwrap(); + serialize_to_file(&metadata, None, std::path::Path::new(&filename)).unwrap(); let raw = std::fs::read(&filename).unwrap(); let _deserialized = SafeTensors::deserialize(&raw).unwrap(); std::fs::remove_file(&filename).unwrap(); From faaeaf01d66a4cde87a475d9d5c0a694ac2ca5a3 Mon Sep 17 00:00:00 2001 From: Nicolas Patry Date: Sun, 15 Jun 2025 10:07:05 +0000 Subject: [PATCH 22/37] Adding support for MXFP4,6. (#611) * Adding support for MXFP4,6. * More rejections. * Adding support when torch 2.8 will get release. Some nasty bits with _x2 dtype.. * Rebased. * Rebasing after some changes. --- README.md | 2 + bindings/python/py_src/safetensors/torch.py | 4 + bindings/python/src/lib.rs | 55 ++++-- bindings/python/src/view.rs | 143 ++++++++++++++++ bindings/python/tests/test_pt_comparison.py | 37 +++++ safetensors/benches/benchmark.rs | 4 +- safetensors/src/slice.rs | 82 ++++++++- safetensors/src/tensor.rs | 175 +++++++++++++++----- 8 files changed, 442 insertions(+), 60 deletions(-) create mode 100644 bindings/python/src/view.rs diff --git a/README.md b/README.md index 4fd32c4f..89c61066 100644 --- a/README.md +++ b/README.md @@ -103,6 +103,7 @@ Notes: - Endianness: Little-endian. moment. - Order: 'C' or row-major. + - Notes: Some smaller than 1 byte dtypes appeared, which make alignment tricky. Non traditional APIs might be required for those. ### Yet another format ? @@ -162,6 +163,7 @@ This is my very personal and probably biased view: moment. - Order: 'C' or row-major. This seems to have won. We can add that information later if needed. - Stride: No striding, all tensors need to be packed before being serialized. I have yet to see a case where it seems useful to have a strided tensor stored in serialized format. + - Sub 1 bytes dtypes: Dtypes can now have lower than 1 byte size, this makes alignment&adressing tricky. For now, the library will simply error out whenever an operation triggers an non aligned read. Trickier API may be created later for those non standard ops. ### Benefits diff --git a/bindings/python/py_src/safetensors/torch.py b/bindings/python/py_src/safetensors/torch.py index 4b6acbca..568d4aa7 100644 --- a/bindings/python/py_src/safetensors/torch.py +++ b/bindings/python/py_src/safetensors/torch.py @@ -397,6 +397,8 @@ def load(data: bytes) -> Dict[str, torch.Tensor]: # torch.float8 formats require 2.1; we do not support these dtypes on earlier versions _float8_e4m3fn = getattr(torch, "float8_e4m3fn", None) _float8_e5m2 = getattr(torch, "float8_e5m2", None) +_float8_e8m0 = getattr(torch, "float8_e8m0fnu", None) +_float4_e2m1_x2 = getattr(torch, "float4_e2m1fn_x2", None) _SIZE = { torch.int64: 8, @@ -411,6 +413,8 @@ def load(data: bytes) -> Dict[str, torch.Tensor]: torch.float64: 8, _float8_e4m3fn: 1, _float8_e5m2: 1, + _float8_e8m0: 1, + _float4_e2m1_x2: 1, } _TYPES = { diff --git a/bindings/python/src/lib.rs b/bindings/python/src/lib.rs index 7886da2f..b5b0cc68 100644 --- a/bindings/python/src/lib.rs +++ b/bindings/python/src/lib.rs @@ -50,20 +50,20 @@ impl View for &PyView<'_> { fn prepare(tensor_dict: HashMap>) -> PyResult> { let mut tensors = HashMap::with_capacity(tensor_dict.len()); for (tensor_name, tensor_desc) in tensor_dict { - let shape: Vec = tensor_desc + let mut shape: Vec = tensor_desc .get_item("shape")? .ok_or_else(|| SafetensorError::new_err(format!("Missing `shape` in {tensor_desc}")))? .extract()?; - let pydata: PyBound = tensor_desc.get_item("data")?.ok_or_else(|| { - SafetensorError::new_err(format!("Missing `data` in {tensor_desc}")) - })?; + let pydata: PyBound = tensor_desc + .get_item("data")? + .ok_or_else(|| SafetensorError::new_err(format!("Missing `data` in {tensor_desc}")))?; // Make sure it's extractable first. let data: &[u8] = pydata.extract()?; let data_len = data.len(); let data: PyBound = pydata.extract()?; - let pydtype = tensor_desc.get_item("dtype")?.ok_or_else(|| { - SafetensorError::new_err(format!("Missing `dtype` in {tensor_desc}")) - })?; + let pydtype = tensor_desc + .get_item("dtype")? + .ok_or_else(|| SafetensorError::new_err(format!("Missing `dtype` in {tensor_desc}")))?; let dtype: String = pydtype.extract()?; let dtype = match dtype.as_ref() { "bool" => Dtype::BOOL, @@ -81,6 +81,8 @@ fn prepare(tensor_dict: HashMap>) -> PyResult Dtype::BF16, "float8_e4m3fn" => Dtype::F8_E4M3, "float8_e5m2" => Dtype::F8_E5M2, + "float8_e8m0fnu" => Dtype::F8_E8M0, + "float4_e2m1fn_x2" => Dtype::F4, dtype_str => { return Err(SafetensorError::new_err(format!( "dtype {dtype_str} is not covered", @@ -88,6 +90,11 @@ fn prepare(tensor_dict: HashMap>) -> PyResult) -> fmt::Result { match *self { @@ -351,7 +357,9 @@ impl<'py> IntoPyObject<'py> for Device { type Error = std::convert::Infallible; fn into_pyobject(self, py: Python<'py>) -> Result { - self.to_string().into_pyobject(py).map(pyo3::BoundObject::into_any) + self.to_string() + .into_pyobject(py) + .map(pyo3::BoundObject::into_any) } } @@ -417,7 +425,10 @@ struct Open { impl Open { fn new(filename: PathBuf, framework: Framework, device: Option) -> PyResult { let file = File::open(&filename).map_err(|_| { - PyFileNotFoundError::new_err(format!("No such file or directory: {}", filename.display())) + PyFileNotFoundError::new_err(format!( + "No such file or directory: {}", + filename.display() + )) })?; let device = device.unwrap_or(Device::Cpu); @@ -466,7 +477,10 @@ impl Open { let py_filename: PyObject = filename .to_str() .ok_or_else(|| { - SafetensorError::new_err(format!("Path {} is not valid UTF-8", filename.display())) + SafetensorError::new_err(format!( + "Path {} is not valid UTF-8", + filename.display() + )) })? .into_pyobject(py)? .into(); @@ -596,7 +610,16 @@ impl Open { ] .into_py_dict(py)?; let view_kwargs = [(intern!(py, "dtype"), dtype)].into_py_dict(py)?; - let shape = info.shape.to_vec(); + let mut shape = info.shape.to_vec(); + if info.dtype == Dtype::F4 { + let n = shape.len(); + if shape[n - 1] % 2 != 0 { + return Err(SafetensorError::new_err(format!( + "f4_x2 dtype requires that the last dim be divisible by 2 in torch: got {shape:?}", + ))); + } + shape[n - 1] /= 2; + } let shape: PyObject = shape.into_pyobject(py)?.into(); let start = (info.data_offsets.0 + self.offset) as isize; @@ -627,6 +650,7 @@ impl Open { Dtype::BF16 => Some(Dtype::F16), Dtype::F8_E5M2 => Some(Dtype::U8), Dtype::F8_E4M3 => Some(Dtype::U8), + Dtype::F8_E8M0 => Some(Dtype::U8), _ => None, }; if let Some(intermediary_dtype) = intermediary_dtype { @@ -999,6 +1023,7 @@ impl PySafeSlice { Dtype::BF16 => Some(Dtype::F16), Dtype::F8_E5M2 => Some(Dtype::U8), Dtype::F8_E4M3 => Some(Dtype::U8), + Dtype::F8_E8M0 => Some(Dtype::U8), _ => None, }; if let Some(intermediary_dtype) = intermediary_dtype { @@ -1087,9 +1112,7 @@ fn create_tensor<'a>( NUMPY_MODULE .get() .ok_or_else(|| { - SafetensorError::new_err( - format!("Could not find module {framework}",), - ) + SafetensorError::new_err(format!("Could not find module {framework}",)) })? .bind(py), true, @@ -1208,6 +1231,8 @@ fn get_pydtype(module: &PyBound<'_, PyModule>, dtype: Dtype, is_numpy: bool) -> } Dtype::F8_E4M3 => module.getattr(intern!(py, "float8_e4m3fn"))?.into(), Dtype::F8_E5M2 => module.getattr(intern!(py, "float8_e5m2"))?.into(), + Dtype::F8_E8M0 => module.getattr(intern!(py, "float8_e8m0fnu"))?.into(), + Dtype::F4 => module.getattr(intern!(py, "float4_e2m1fn_x2"))?.into(), dtype => { return Err(SafetensorError::new_err(format!( "Dtype not understood: {dtype}" diff --git a/bindings/python/src/view.rs b/bindings/python/src/view.rs new file mode 100644 index 00000000..cf0ea392 --- /dev/null +++ b/bindings/python/src/view.rs @@ -0,0 +1,143 @@ +use crate::SafetensorError; +#[cfg(feature = "py311")] +use pyo3::buffer::PyBuffer; +use pyo3::prelude::*; +#[cfg(feature = "py38")] +use pyo3::types::PyBytes; +use pyo3::types::PyDict; +use pyo3::Bound as PyBound; +use safetensors::{Dtype, View}; +use std::borrow::Cow; +use std::collections::HashMap; + +#[cfg(feature = "py38")] +pub struct PyView<'a> { + shape: Vec, + dtype: Dtype, + data: PyBound<'a, PyBytes>, + data_len: usize, +} + +#[cfg(feature = "py311")] +pub struct PyView<'a> { + shape: Vec, + dtype: Dtype, + data: PyBuffer, + data_len: usize, + // Kept to keep the GIL open while we hold the buffer + _py: Python<'a>, +} + +impl View for &PyView<'_> { + #[cfg(feature = "py38")] + fn data(&self) -> std::borrow::Cow<[u8]> { + Cow::Borrowed(self.data.as_bytes()) + } + #[cfg(feature = "py311")] + fn data(&self) -> std::borrow::Cow<[u8]> { + // We already checked this in the Python side. + assert!(self.data.is_c_contiguous()); + // XXX: Ideally we could have at least readonly tensors + // assert!(self.data.readonly()); + // SAFETY: + // This is actually totally unsafe, PyBuffer is not immutable and could be changed from + // under us. + // This is made safer because we're still hanging to the GIL while treating + // this structure + Cow::Borrowed(unsafe { + std::slice::from_raw_parts(self.data.buf_ptr() as *const u8, self.data.item_count()) + }) + } + fn shape(&self) -> &[usize] { + &self.shape + } + fn dtype(&self) -> Dtype { + self.dtype + } + fn data_len(&self) -> usize { + self.data_len + } +} + +pub fn prepare(tensor_dict: HashMap>) -> PyResult> { + let mut tensors = HashMap::with_capacity(tensor_dict.len()); + for (tensor_name, tensor_desc) in &tensor_dict { + let mut shape: Vec = tensor_desc + .get_item("shape")? + .ok_or_else(|| SafetensorError::new_err(format!("Missing `shape` in {tensor_desc:?}")))? + .extract()?; + let pydata: PyBound = tensor_desc.get_item("data")?.ok_or_else(|| { + SafetensorError::new_err(format!("Missing `data` in {tensor_desc:?}")) + })?; + + let pydtype = tensor_desc.get_item("dtype")?.ok_or_else(|| { + SafetensorError::new_err(format!("Missing `dtype` in {tensor_desc:?}")) + })?; + let dtype: String = pydtype.extract()?; + let dtype = match dtype.as_ref() { + "bool" => Dtype::BOOL, + "int8" => Dtype::I8, + "uint8" => Dtype::U8, + "int16" => Dtype::I16, + "uint16" => Dtype::U16, + "int32" => Dtype::I32, + "uint32" => Dtype::U32, + "int64" => Dtype::I64, + "uint64" => Dtype::U64, + "float16" => Dtype::F16, + "float32" => Dtype::F32, + "float64" => Dtype::F64, + "bfloat16" => Dtype::BF16, + "float8_e4m3fn" => Dtype::F8_E4M3, + "float8_e5m2" => Dtype::F8_E5M2, + "float8_e8m0fnu" => Dtype::E8M0, + "float4_e2m1fn_x2" => Dtype::F4, + dtype_str => { + return Err(SafetensorError::new_err(format!( + "dtype {dtype_str} is not covered", + ))); + } + }; + if dtype == Dtype::F4 { + let n = shape.len(); + shape[n - 1] *= 2; + } + + #[cfg(feature = "py311")] + let tensor = { + let data: PyBuffer = pydata.extract()?; + if !data.is_c_contiguous() { + return Err(SafetensorError::new_err("Python buffer is not contiguous")); + } + // XXX Ideally this would be true. + // if !data.readonly() { + // return Err(SafetensorError::new_err("Python buffer is not readonly")); + // } + let data_len = data.item_count(); + let py = pydata.py(); + PyView { + shape, + dtype, + data, + data_len, + _py: py, + } + }; + + #[cfg(feature = "py38")] + let tensor = { + let data: &[u8] = pydata.extract()?; + let data_len = data.len(); + let data: PyBound = pydata.extract()?; + PyView { + shape, + dtype, + data, + data_len, + } + }; + + tensors.insert(tensor_name.to_string(), tensor); + } + Ok(tensors) +} diff --git a/bindings/python/tests/test_pt_comparison.py b/bindings/python/tests/test_pt_comparison.py index 36529295..a87f50aa 100644 --- a/bindings/python/tests/test_pt_comparison.py +++ b/bindings/python/tests/test_pt_comparison.py @@ -2,6 +2,7 @@ import unittest import torch +from packaging.version import Version from safetensors import safe_open from safetensors.torch import load, load_file, save, save_file @@ -64,6 +65,7 @@ def test_odd_dtype(self): "test2": torch.randn((2, 2), dtype=torch.float16), "test3": torch.zeros((2, 2), dtype=torch.bool), } + # Modify bool to have both values. data["test3"][0, 0] = True local = "./tests/data/out_safe_pt_mmap_small.safetensors" @@ -92,6 +94,27 @@ def test_odd_dtype_fp8(self): self.assertEqual(reloaded["test2"].dtype, torch.float8_e5m2) self.assertEqual(reloaded["test2"].item(), -0.5) + def test_odd_dtype_fp4(self): + if Version(torch.__version__) <= Version("2.7"): + return # torch.float4 requires 2.8 + + test1 = torch.tensor([0.0], dtype=torch.float8_e8m0fnu) + test2 = torch.empty(2, 2, device="cpu", dtype=torch.float4_e2m1fn_x2) + data = { + "test1": test1, + "test2": test2, + } + local = "./tests/data/out_safe_pt_mmap_fp4.safetensors" + + save_file(data, local) + reloaded = load_file(local) + # note: PyTorch doesn't implement torch.equal for float8 so we just compare the single element + self.assertEqual(reloaded["test1"].dtype, torch.float8_e8m0fnu) + self.assertEqual(reloaded["test1"], test1) + self.assertEqual(reloaded["test2"].dtype, torch.float4_e2m1fn_x2) + # TODO RuntimeError: "eq_cpu" not implemented for 'Float4_e2m1fn_x2' + # self.assertEqual(reloaded["test2"], test2) + def test_zero_sized(self): data = { "test": torch.zeros((2, 0), dtype=torch.float), @@ -157,6 +180,20 @@ def test_gpu(self): reloaded = load_file(local) self.assertTrue(torch.equal(torch.arange(4).view((2, 2)), reloaded["test"])) + @unittest.skipIf(not torch.cuda.is_available(), "Cuda is not available") + def test_gpu_default_device(self): + data = { + "test": torch.arange(4).view((2, 2)).to("cuda:0"), + } + local = "./tests/data/out_safe_pt_mmap_small.safetensors" + save_file(data, local) + with torch.device("cuda:0"): + reloaded = load_file(local) + assert reloaded["test"].device == torch.device("cpu") + reloaded = load_file(local, device="cuda:0") + assert reloaded["test"].device == torch.device("cuda:0") + self.assertTrue(torch.equal(torch.arange(4).view((2, 2)), reloaded["test"])) + @unittest.skipIf(not npu_present, "Npu is not available") def test_npu(self): data = { diff --git a/safetensors/benches/benchmark.rs b/safetensors/benches/benchmark.rs index 46c1a50a..e2a821e8 100644 --- a/safetensors/benches/benchmark.rs +++ b/safetensors/benches/benchmark.rs @@ -7,7 +7,9 @@ use std::hint::black_box; fn get_sample_data() -> (Vec, Vec, Dtype) { let shape = vec![1000, 500]; let dtype = Dtype::F32; - let n: usize = shape.iter().product::() * dtype.size(); // 4 + let nbits = shape.iter().product::() * dtype.bitsize(); + assert!(nbits % 8 == 0); + let n: usize = nbits / 8; // 4 let data = vec![0; n]; (data, shape, dtype) diff --git a/safetensors/src/slice.rs b/safetensors/src/slice.rs index 485f0828..0e145666 100644 --- a/safetensors/src/slice.rs +++ b/safetensors/src/slice.rs @@ -1,10 +1,10 @@ //! Module handling lazy loading via iterating on slices on the original buffer. use crate::lib::Vec; use crate::tensor::TensorView; +use core::fmt::Display; use core::ops::{ Bound, Range, RangeBounds, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive, }; -use core::fmt::Display; /// Error representing invalid slicing attempt #[derive(Debug)] @@ -21,6 +21,9 @@ pub enum InvalidSlice { /// The dimension size we shouldn't go over. dim_size: usize, }, + /// For smaller than 1 byte dtypes, some slices will happen outside of the byte boundary, some special care has to be taken + /// and standard functions will fail + MisalignedSlice, } impl Display for InvalidSlice { @@ -29,9 +32,16 @@ impl Display for InvalidSlice { InvalidSlice::TooManySlices => { write!(f, "more slicing indexes than dimensions in tensor") } - InvalidSlice::SliceOutOfRange { dim_index, asked, dim_size } => { + InvalidSlice::SliceOutOfRange { + dim_index, + asked, + dim_size, + } => { write!(f, "index {asked} out of bounds for tensor dimension #{dim_index} of size {dim_size}") } + InvalidSlice::MisalignedSlice => { + write!(f, "The slice is slicing for subbytes dtypes, and the slice does not end up at a byte boundary, this is invalid.") + } } } } @@ -276,7 +286,7 @@ impl<'data> SliceIterator<'data> { let mut newshape = Vec::with_capacity(view.shape().len()); // Minimum span is the span of 1 item; - let mut span = view.dtype().size(); + let mut span = view.dtype().bitsize(); let mut indices = vec![]; // Everything is row major. for (i, &shape) in view.shape().iter().enumerate().rev() { @@ -324,15 +334,24 @@ impl<'data> SliceIterator<'data> { if start == 0 && stop == shape { // We haven't started to slice yet, just increase the span } else { - let offset = start * span; - let small_span = stop * span - offset; + if start * span % 8 != 0 { + return Err(InvalidSlice::MisalignedSlice); + } + let offset = (start * span) / 8; + if stop * span % 8 != 0 { + return Err(InvalidSlice::MisalignedSlice); + } + let small_span = (stop * span) / 8 - offset; indices.push((offset, offset + small_span)); } } else { let capacity = (stop - start) * indices.len(); let mut newindices = Vec::with_capacity(capacity); for n in start..stop { - let offset = n * span; + if n * span % 8 != 0 { + return Err(InvalidSlice::MisalignedSlice); + } + let offset = (n * span) / 8; for (old_start, old_stop) in &indices { newindices.push((old_start + offset, old_stop + offset)); } @@ -415,6 +434,57 @@ mod tests { assert_eq!(iterator.newshape(), vec![1, 1, 3]); } + #[test] + fn test_fp4_simple() { + let data: Vec = vec![0u8, 1u8]; + + let attn_0 = TensorView::new(Dtype::F4, vec![1, 2, 2], &data).unwrap(); + + let iterator = SliceIterator::new( + &attn_0, + &[TensorIndexer::Narrow(Bound::Unbounded, Bound::Unbounded)], + ) + .unwrap(); + assert_eq!(iterator.remaining_byte_len(), 2); + assert_eq!(iterator.newshape(), vec![1, 2, 2]); + + let iterator = SliceIterator::new( + &attn_0, + &[ + TensorIndexer::Narrow(Bound::Unbounded, Bound::Unbounded), + TensorIndexer::Narrow(Bound::Included(0), Bound::Excluded(1)), + ], + ) + .unwrap(); + assert_eq!(iterator.remaining_byte_len(), 1); + assert_eq!(iterator.newshape(), vec![1, 1, 2]); + } + + #[test] + fn test_fp4_misaligned() { + let data: Vec = vec![0u8]; + + let attn_0 = TensorView::new(Dtype::F4, vec![1, 2], &data).unwrap(); + + let iterator = SliceIterator::new( + &attn_0, + &[TensorIndexer::Narrow(Bound::Unbounded, Bound::Unbounded)], + ) + .unwrap(); + assert_eq!(iterator.remaining_byte_len(), 1); + assert_eq!(iterator.newshape(), vec![1, 2]); + + let iterator = SliceIterator::new( + &attn_0, + &[ + TensorIndexer::Narrow(Bound::Unbounded, Bound::Unbounded), + TensorIndexer::Narrow(Bound::Included(0), Bound::Excluded(1)), + ], + ); + + assert_eq!(iterator, Err(InvalidSlice::MisalignedSlice)); + } + #[test] fn test_dummy() { let data: Vec = vec![0.0f32, 1.0, 2.0, 3.0, 4.0, 5.0] diff --git a/safetensors/src/tensor.rs b/safetensors/src/tensor.rs index f97a8c92..6f28d465 100644 --- a/safetensors/src/tensor.rs +++ b/safetensors/src/tensor.rs @@ -1,9 +1,9 @@ //! Module Containing the most important structures use crate::lib::{Cow, HashMap, String, ToString, Vec}; use crate::slice::{InvalidSlice, SliceIterator, TensorIndexer}; -use serde::{ser::SerializeMap, Deserialize, Deserializer, Serialize, Serializer}; use core::fmt::Display; use core::str::Utf8Error; +use serde::{ser::SerializeMap, Deserialize, Deserializer, Serialize, Serializer}; #[cfg(feature = "std")] use std::io::Write; @@ -45,6 +45,9 @@ pub enum SafeTensorError { /// The metadata contains information (shape or shape * dtype size) which lead to an /// arithmetic overflow. This is most likely an error in the file. ValidationOverflow, + /// For smaller than 1 byte dtypes, some slices will happen outside of the byte boundary, some special care has to be taken + /// and standard functions will fail + MisalignedSlice, } #[cfg(feature = "std")] @@ -86,6 +89,7 @@ impl Display for SafeTensorError { } MetadataIncompleteBuffer => write!(f, "incomplete metadata, file not fully covered"), ValidationOverflow => write!(f, "overflow computing buffer size from shape and/or element type"), + MisalignedSlice => write!(f, "The slice is slicing for subbytes dtypes, and the slice does not end up at a byte boundary, this is invalid.") } } } @@ -358,8 +362,8 @@ impl<'data> SafeTensors<'data> { // if !string.starts_with('{') { // return Err(SafeTensorError::InvalidHeaderStart); // } - let metadata: HashMetadata = serde_json::from_str(string) - .map_err(SafeTensorError::InvalidHeaderDeserialization)?; + let metadata: HashMetadata = + serde_json::from_str(string).map_err(SafeTensorError::InvalidHeaderDeserialization)?; let metadata: Metadata = metadata.try_into()?; let buffer_end = metadata.validate()?; if buffer_end + 8 + n != buffer_len { @@ -587,10 +591,17 @@ impl Metadata { .cloned() .try_fold(1usize, usize::checked_mul) .ok_or(SafeTensorError::ValidationOverflow)?; - let nbytes = nelements - .checked_mul(info.dtype.size()) + let nbits = nelements + .checked_mul(info.dtype.bitsize()) + .ok_or(SafeTensorError::ValidationOverflow)?; + + if nbits % 8 != 0 { + return Err(SafeTensorError::MisalignedSlice); + } + let size = nbits + .checked_div(8) .ok_or(SafeTensorError::ValidationOverflow)?; - if (e - s) != nbytes { + if (e - s) != size { return Err(SafeTensorError::TensorInvalidInfo); } } @@ -679,7 +690,11 @@ impl<'data> TensorView<'data> { ) -> Result { let n = data.len(); let n_elements: usize = shape.iter().product(); - if n != n_elements * dtype.size() { + let size = (n_elements * dtype.bitsize()) + .checked_div(8) + .ok_or(SafeTensorError::ValidationOverflow)?; + + if n != size { Err(SafeTensorError::InvalidTensorView(dtype, shape, n)) } else { Ok(Self { dtype, shape, data }) @@ -728,6 +743,14 @@ pub struct TensorInfo { pub enum Dtype { /// Boolan type BOOL, + /// MXF4 _ + F4, + /// MXF6 _ + #[allow(non_camel_case_types)] + F6_E2M3, + /// MXF6 _ + #[allow(non_camel_case_types)] + F6_E3M2, /// Unsigned byte U8, /// Signed byte @@ -738,6 +761,9 @@ pub enum Dtype { /// FP8 _ #[allow(non_camel_case_types)] F8_E4M3, + /// F8_E8M0 _ + #[allow(non_camel_case_types)] + F8_E8M0, /// Signed integer (16-bit) I16, /// Unsigned integer (16-bit) @@ -761,36 +787,52 @@ pub enum Dtype { } impl Dtype { - /// Gives out the size (in bytes) of 1 element of this dtype. - pub fn size(&self) -> usize { + /// Gives out the size (in bits) of 1 element of this dtype. + pub fn bitsize(&self) -> usize { match self { - Dtype::BOOL => 1, - Dtype::U8 => 1, - Dtype::I8 => 1, - Dtype::F8_E5M2 => 1, - Dtype::F8_E4M3 => 1, - Dtype::I16 => 2, - Dtype::U16 => 2, - Dtype::I32 => 4, - Dtype::U32 => 4, - Dtype::I64 => 8, - Dtype::U64 => 8, - Dtype::F16 => 2, - Dtype::BF16 => 2, - Dtype::F32 => 4, - Dtype::F64 => 8, + Dtype::F4 => 4, + Dtype::F6_E3M2 => 6, + Dtype::F6_E2M3 => 6, + Dtype::BOOL => 8, + Dtype::U8 => 8, + Dtype::I8 => 8, + Dtype::F8_E5M2 => 8, + Dtype::F8_E4M3 => 8, + Dtype::F8_E8M0 => 8, + Dtype::I16 => 16, + Dtype::U16 => 16, + Dtype::I32 => 32, + Dtype::U32 => 32, + Dtype::I64 => 64, + Dtype::U64 => 64, + Dtype::F16 => 16, + Dtype::BF16 => 16, + Dtype::F32 => 32, + Dtype::F64 => 64, } } + /// Gives out the size (in bytes) of 1 element of this dtype. + #[deprecated( + since = "0.6.0", + note = "Use `bitsize` instead as some elements have smaller than a full byte of width" + )] + pub fn size(&self) -> usize { + self.bitsize() / 8 + } } impl Display for Dtype { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.write_str(match *self { + Dtype::F4 => "F4", + Dtype::F6_E2M3 => "F6_E2M3", + Dtype::F6_E3M2 => "F6_E3M2", Dtype::BOOL => "BOOL", Dtype::I8 => "I8", Dtype::U8 => "U8", Dtype::F8_E5M2 => "F8_E5M2", Dtype::F8_E4M3 => "F8_E4M3", + Dtype::F8_E8M0 => "F8_E8M0", Dtype::I16 => "I16", Dtype::U16 => "U16", Dtype::I32 => "I32", @@ -821,6 +863,11 @@ mod tests { fn arbitrary_dtype() -> impl Strategy { prop_oneof![ Just(Dtype::BOOL), + Just(Dtype::F4), + Just(Dtype::F6_E3M2), + Just(Dtype::F6_E2M3), + Just(Dtype::F8_E5M2), + Just(Dtype::F8_E4M3), Just(Dtype::U8), Just(Dtype::I8), Just(Dtype::I16), @@ -851,33 +898,41 @@ mod tests { prop::collection::vec(arbitrary_shape(), size), ) }) - .prop_map(|(dtypes, shapes)| { + .prop_filter_map("Misaligned slices", |(dtypes, shapes)| { // Returns a valid metadata object for a random (length, dtypes, shapes) triple. let mut start = 0; let tensors: Vec = dtypes .iter() .zip(shapes) - .map(|(dtype, shape)| { + .flat_map(|(dtype, shape)| { // This cannot overflow because the size of // the vector and elements are so small. - let length: usize = shape.iter().product(); - let end = start + length * dtype.size(); + let bitlength: usize = shape.iter().product::() * dtype.bitsize(); + if bitlength % 8 != 0 { + return None; + } + let length = bitlength.div_ceil(8); + let end = start + length; let tensor = TensorInfo { dtype: *dtype, shape, data_offsets: (start, end), }; start = end; - tensor + Some(tensor) }) .collect(); let index_map = (0..tensors.len()) .map(|index| (format!("t.{index}"), index)) .collect(); - Metadata { - metadata: None, - tensors, - index_map, + if tensors.is_empty() { + None + } else { + Some(Metadata { + metadata: None, + tensors, + index_map, + }) } }) } @@ -918,7 +973,7 @@ mod tests { for name in before.names() { let tensor_before = before.tensor(name).unwrap(); let tensor_after = after.tensor(name).unwrap(); - assert_eq!(tensor_after.data().as_ptr() as usize % tensor_after.dtype().size(), 0); + assert_eq!(tensor_after.data().as_ptr() as usize % tensor_after.dtype().bitsize().div_ceil(8), 0); assert_eq!(tensor_before, tensor_after); } } @@ -949,6 +1004,40 @@ mod tests { let _parsed = SafeTensors::deserialize(&out).unwrap(); } + #[test] + fn test_serialization_fp4() { + let data: Vec = vec![0u8]; + let shape = vec![1, 2]; + let attn_0 = TensorView::new(Dtype::F4, shape, &data).unwrap(); + let metadata: HashMap = + [("attn.0".to_string(), attn_0)].into_iter().collect(); + + let out = serialize(&metadata, None).unwrap(); + assert_eq!( + out, + [ + 64, 0, 0, 0, 0, 0, 0, 0, 123, 34, 97, 116, 116, 110, 46, 48, 34, 58, 123, 34, 100, + 116, 121, 112, 101, 34, 58, 34, 70, 52, 34, 44, 34, 115, 104, 97, 112, 101, 34, 58, + 91, 49, 44, 50, 93, 44, 34, 100, 97, 116, 97, 95, 111, 102, 102, 115, 101, 116, + 115, 34, 58, 91, 48, 44, 49, 93, 125, 125, 32, 32, 32, 32, 0 + ] + ); + let parsed = SafeTensors::deserialize(&out).unwrap(); + let tensors: HashMap<_, _> = parsed.tensors().into_iter().collect(); + assert_eq!(tensors, metadata); + } + + #[test] + fn test_serialization_fp4_misaligned() { + let data: Vec = vec![0u8, 1u8]; + let shape = vec![1, 3]; + let attn_0 = TensorView::new(Dtype::F4, shape, &data); + assert!(matches!( + attn_0, + Err(SafeTensorError::InvalidTensorView(Dtype::F4, _shape, _size)) + )); + } + #[test] fn test_empty() { let tensors: HashMap = HashMap::new(); @@ -1005,7 +1094,10 @@ mod tests { ); let parsed = SafeTensors::deserialize(&out).unwrap(); let tensor = parsed.tensor("attn0").unwrap(); - assert_eq!(tensor.data().as_ptr() as usize % tensor.dtype().size(), 0); + assert_eq!( + tensor.data().as_ptr() as usize % tensor.dtype().bitsize().div_ceil(8), + 0 + ); } #[test] @@ -1090,17 +1182,24 @@ mod tests { tensors_desc.push(("ln_f.bias".to_string(), vec![768])); let dtype = Dtype::F32; - let n: usize = tensors_desc + let nbits: usize = tensors_desc .iter() .map(|(_, shape)| shape.iter().product::()) .sum::() - * dtype.size(); // 4 + * dtype.bitsize(); + if nbits % 8 != 0 { + panic!("Misaligned slice"); + } + let n = nbits + .checked_div(8) + .ok_or(SafeTensorError::ValidationOverflow) + .unwrap(); // 4 let all_data = vec![0; n]; let mut metadata = HashMap::with_capacity(tensors_desc.len()); let mut offset = 0; for (name, shape) in tensors_desc { let n: usize = shape.iter().product(); - let buffer = &all_data[offset..offset + n * dtype.size()]; + let buffer = &all_data[offset..offset + (n * dtype.bitsize()) / 8]; let tensor = TensorView::new(dtype, shape, buffer).unwrap(); metadata.insert(name, tensor); offset += n; From fa6a19c6438ab60085417d6acba4f5fa29f4c859 Mon Sep 17 00:00:00 2001 From: Nicolas Patry Date: Sun, 15 Jun 2025 10:12:27 +0000 Subject: [PATCH 23/37] Bumping version because of breaking changes. (#619) --- bindings/python/Cargo.toml | 2 +- safetensors/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bindings/python/Cargo.toml b/bindings/python/Cargo.toml index c1440f20..646312bf 100644 --- a/bindings/python/Cargo.toml +++ b/bindings/python/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "safetensors-python" -version = "0.5.3-dev.0" +version = "0.6.0-dev.0" edition = "2021" rust-version = "1.74" diff --git a/safetensors/Cargo.toml b/safetensors/Cargo.toml index 139a99de..68ebac64 100644 --- a/safetensors/Cargo.toml +++ b/safetensors/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "safetensors" -version = "0.5.3-dev.0" +version = "0.6.0-dev.0" edition = "2021" rust-version = "1.80" homepage = "https://github.com/huggingface/safetensors" From 98f07e3bf3548ec7c1275cb409cebeed66aaf4e7 Mon Sep 17 00:00:00 2001 From: Nicolas Patry Date: Sun, 15 Jun 2025 10:27:13 +0000 Subject: [PATCH 24/37] Adding data_len as public API for metadata (to fetch the size of the (#620) data buffer). --- safetensors/src/tensor.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/safetensors/src/tensor.rs b/safetensors/src/tensor.rs index 6f28d465..e2a1b0ff 100644 --- a/safetensors/src/tensor.rs +++ b/safetensors/src/tensor.rs @@ -629,6 +629,15 @@ impl Metadata { index_vec.into_iter().map(|a| a.0.clone()).collect() } + /// Gives the size of the content buffer in bytes. + pub fn data_len(&self) -> usize { + if let Some(tensor) = self.tensors.last() { + tensor.data_offsets.1 + } else { + 0 + } + } + /// Gives back the tensor metadata pub fn metadata(&self) -> &Option> { &self.metadata From f6938215f779363ae626577d5863cf4a2ae1e798 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81rp=C3=A1d=20Goretity=20=EF=A3=BF?= Date: Mon, 16 Jun 2025 08:22:52 +0200 Subject: [PATCH 25/37] Simplify code and make it more robust (#615) * Simplify code and make it more robust * Remove extraneous empty line * Address review comments --------- Co-authored-by: Nicolas Patry --- safetensors/src/slice.rs | 2 +- safetensors/src/tensor.rs | 169 +++++++++++++++++++++----------------- 2 files changed, 95 insertions(+), 76 deletions(-) diff --git a/safetensors/src/slice.rs b/safetensors/src/slice.rs index 0e145666..2dc1a62a 100644 --- a/safetensors/src/slice.rs +++ b/safetensors/src/slice.rs @@ -378,7 +378,7 @@ impl<'data> SliceIterator<'data> { pub fn remaining_byte_len(&self) -> usize { self.indices .iter() - .map(|(start, stop)| (stop - start)) + .map(|(start, stop)| stop - start) .sum() } diff --git a/safetensors/src/tensor.rs b/safetensors/src/tensor.rs index e2a1b0ff..d10f8c9b 100644 --- a/safetensors/src/tensor.rs +++ b/safetensors/src/tensor.rs @@ -4,10 +4,12 @@ use crate::slice::{InvalidSlice, SliceIterator, TensorIndexer}; use core::fmt::Display; use core::str::Utf8Error; use serde::{ser::SerializeMap, Deserialize, Deserializer, Serialize, Serializer}; +use core::fmt::Display; #[cfg(feature = "std")] use std::io::Write; const MAX_HEADER_SIZE: usize = 100_000_000; +const SIZEOF_HEADER_SIZE_NUMBER: usize = size_of::(); /// Possible errors that could occur while reading /// A Safetensor file. @@ -217,10 +219,16 @@ pub trait View { fn data_len(&self) -> usize; } -fn prepare + Ord + core::fmt::Display, V: View, I: IntoIterator>( +fn prepare( data: I, data_info: Option>, -) -> Result<(PreparedData, Vec), SafeTensorError> { +) -> Result<(PreparedData, Vec), SafeTensorError> +where + S: AsRef + Ord + Display, + V: View, + I: IntoIterator, + +{ // Make sure we're sorting by descending dtype alignment // Then by name let mut data: Vec<_> = data.into_iter().collect(); @@ -231,7 +239,7 @@ fn prepare + Ord + core::fmt::Display, V: View, I: IntoIterator = Vec::with_capacity(data.len()); let mut hmetadata = Vec::with_capacity(data.len()); let mut offset = 0; - let data: Vec<_> = data.into_iter().collect(); + for (name, tensor) in data { let n = tensor.data_len(); let tensor_info = TensorInfo { @@ -244,17 +252,17 @@ fn prepare + Ord + core::fmt::Display, V: View, I: IntoIterator = Vec::with_capacity(expected_size); - buffer.extend(&n.to_le_bytes().to_vec()); - buffer.extend(&header_bytes); + buffer.extend(n.to_le_bytes()); + buffer.extend(header_bytes); + for tensor in tensors { buffer.extend(tensor.data().as_ref()); } + Ok(buffer) } @@ -293,28 +304,33 @@ pub fn serialize< /// Writing directly to file reduces the need to allocate the whole amount to /// memory. #[cfg(feature = "std")] -pub fn serialize_to_file< - S: AsRef + Ord + core::fmt::Display, - V: View, - I: IntoIterator, ->( +pub fn serialize_to_file( data: I, data_info: Option>, filename: &std::path::Path, -) -> Result<(), SafeTensorError> { +) -> Result<(), SafeTensorError> +where + S: AsRef + Ord + Display, + V: View, + I: IntoIterator, +{ let ( PreparedData { n, header_bytes, .. }, tensors, ) = prepare(data, data_info)?; + let mut f = std::io::BufWriter::new(std::fs::File::create(filename)?); f.write_all(n.to_le_bytes().as_ref())?; f.write_all(&header_bytes)?; + for tensor in tensors { f.write_all(tensor.data().as_ref())?; } + f.flush()?; + Ok(()) } @@ -329,32 +345,33 @@ pub struct SafeTensors<'data> { impl<'data> SafeTensors<'data> { /// Given a byte-buffer representing the whole safetensor file /// parses the header, and returns the size of the header + the parsed data. - pub fn read_metadata<'in_data>( - buffer: &'in_data [u8], - ) -> Result<(usize, Metadata), SafeTensorError> - where - 'in_data: 'data, - { + pub fn read_metadata( + buffer: &'data [u8], + ) -> Result<(usize, Metadata), SafeTensorError>{ let buffer_len = buffer.len(); - if buffer_len < 8 { + let Some(header_size_bytes) = buffer.get(..SIZEOF_HEADER_SIZE_NUMBER) else { return Err(SafeTensorError::HeaderTooSmall); - } - let arr: [u8; 8] = [ - buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7], - ]; + }; + let arr: [u8; SIZEOF_HEADER_SIZE_NUMBER] = header_size_bytes + .try_into() + .expect("this can't fail due to how `header_size_bytes` is defined above"); let n: usize = u64::from_le_bytes(arr) .try_into() .map_err(|_| SafeTensorError::HeaderTooLarge)?; + if n > MAX_HEADER_SIZE { return Err(SafeTensorError::HeaderTooLarge); } let stop = n - .checked_add(8) + .checked_add(SIZEOF_HEADER_SIZE_NUMBER) .ok_or(SafeTensorError::InvalidHeaderLength)?; - if stop > buffer_len { + + // the `.get(start..stop)` returns None if either index is out of bounds, + // so this implicitly also ensures that `stop <= buffer.len()`. + let Some(header_bytes) = buffer.get(SIZEOF_HEADER_SIZE_NUMBER..stop) else { return Err(SafeTensorError::InvalidHeaderLength); - } + }; let string = core::str::from_utf8(&buffer[8..stop]).map_err(SafeTensorError::InvalidHeader)?; // Assert the string starts with { @@ -366,11 +383,13 @@ impl<'data> SafeTensors<'data> { serde_json::from_str(string).map_err(SafeTensorError::InvalidHeaderDeserialization)?; let metadata: Metadata = metadata.try_into()?; let buffer_end = metadata.validate()?; - if buffer_end + 8 + n != buffer_len { + if buffer_end + SIZEOF_HEADER_SIZE_NUMBER + n != buffer_len { return Err(SafeTensorError::MetadataIncompleteBuffer); } + Ok((n, metadata)) } + /// Given a byte-buffer representing the whole safetensor file /// parses it and returns the Deserialized form (No Tensor allocation). /// @@ -390,12 +409,9 @@ impl<'data> SafeTensors<'data> { /// .tensor("test") /// .unwrap(); /// ``` - pub fn deserialize<'in_data>(buffer: &'in_data [u8]) -> Result - where - 'in_data: 'data, - { + pub fn deserialize(buffer: &'data [u8]) -> Result { let (n, metadata) = SafeTensors::read_metadata(buffer)?; - let data = &buffer[n + 8..]; + let data = &buffer[SIZEOF_HEADER_SIZE_NUMBER + n..]; Ok(Self { metadata, data }) } @@ -419,7 +435,7 @@ impl<'data> SafeTensors<'data> { /// Returns an iterator over the tensors contained within the SafeTensors. /// The tensors returned are merely views and the data is not owned by this /// structure. - pub fn iter<'a>(&'a self) -> impl Iterator)> { + pub fn iter(&self) -> impl Iterator)> { self.metadata.index_map.iter().map(|(name, &idx)| { let info = &self.metadata.tensors[idx]; ( @@ -437,26 +453,26 @@ impl<'data> SafeTensors<'data> { /// The tensor returned is merely a view and the data is not owned by this /// structure. pub fn tensor(&self, tensor_name: &str) -> Result, SafeTensorError> { - if let Some(index) = &self.metadata.index_map.get(tensor_name) { - if let Some(info) = &self.metadata.tensors.get(**index) { - Ok(TensorView { - dtype: info.dtype, - shape: info.shape.clone(), - data: &self.data[info.data_offsets.0..info.data_offsets.1], - }) - } else { - Err(SafeTensorError::TensorNotFound(tensor_name.to_string())) - } - } else { - Err(SafeTensorError::TensorNotFound(tensor_name.to_string())) - } + let &index = self.metadata.index_map.get(tensor_name).ok_or_else( + || SafeTensorError::TensorNotFound(tensor_name.to_string()) + )?; + + let info = self.metadata.tensors.get(index).ok_or_else( + || SafeTensorError::TensorNotFound(tensor_name.to_string()) + )?; + + Ok(TensorView { + dtype: info.dtype, + shape: info.shape.clone(), + data: &self.data[info.data_offsets.0..info.data_offsets.1], + }) } /// Return the names of the tensors within the SafeTensors. /// These are used as keys to access to the actual tensors, that can be /// retrieved using the tensor method. - pub fn names(&self) -> Vec<&'_ String> { - self.metadata.index_map.keys().collect() + pub fn names(&self) -> Vec<&'_ str> { + self.metadata.index_map.keys().map(String::as_str).collect() } /// Return how many tensors are currently stored within the SafeTensors. @@ -481,7 +497,7 @@ pub struct Metadata { index_map: HashMap, } -/// Helper struct used only for serialization deserialization +/// Helper struct used only for serialization and deserialization #[derive(Serialize, Deserialize)] struct HashMetadata { #[serde(skip_serializing_if = "Option::is_none")] @@ -523,23 +539,21 @@ impl Serialize for Metadata { S: Serializer, { let mut names = vec![""; self.index_map.len()]; - for (name, index) in &self.index_map { - names[*index] = name; + for (name, &index) in &self.index_map { + names[index] = name; } - let tensors: Vec<_> = names.iter().zip(self.tensors.iter()).collect(); - let length = if let Some(metadata) = &self.metadata { - metadata.len() - } else { - 0 - }; - let mut map = serializer.serialize_map(Some(tensors.len() + length))?; + let length = self.metadata.as_ref().map_or(0, HashMap::len); + let mut map = serializer.serialize_map(Some(self.tensors.len() + length))?; + if let Some(metadata) = &self.metadata { map.serialize_entry("__metadata__", metadata)?; } - for (name, info) in tensors { - map.serialize_entry(&name, &info)?; + + for (name, info) in names.iter().zip(&self.tensors) { + map.serialize_entry(name, info)?; } + map.end() } } @@ -584,11 +598,13 @@ impl Metadata { .unwrap_or("no_tensor"); return Err(SafeTensorError::InvalidOffset(tensor_name.to_string())); } + start = e; + let nelements: usize = info .shape .iter() - .cloned() + .copied() .try_fold(1usize, usize::checked_mul) .ok_or(SafeTensorError::ValidationOverflow)?; let nbits = nelements @@ -601,7 +617,8 @@ impl Metadata { let size = nbits .checked_div(8) .ok_or(SafeTensorError::ValidationOverflow)?; - if (e - s) != size { + + if e - s != nbytes { return Err(SafeTensorError::TensorInvalidInfo); } } @@ -610,15 +627,15 @@ impl Metadata { /// Gives back the tensor metadata pub fn info(&self, name: &str) -> Option<&TensorInfo> { - let index = self.index_map.get(name)?; - self.tensors.get(*index) + let &index = self.index_map.get(name)?; + self.tensors.get(index) } /// Gives back the tensor metadata pub fn tensors(&self) -> HashMap { self.index_map .iter() - .map(|(tensor_name, index)| (tensor_name.clone(), &self.tensors[*index])) + .map(|(tensor_name, &index)| (tensor_name.clone(), &self.tensors[index])) .collect() } @@ -697,8 +714,9 @@ impl<'data> TensorView<'data> { shape: Vec, data: &'data [u8], ) -> Result { - let n = data.len(); + let n_bytes = data.len(); let n_elements: usize = shape.iter().product(); + let size = (n_elements * dtype.bitsize()) .checked_div(8) .ok_or(SafeTensorError::ValidationOverflow)?; @@ -715,7 +733,7 @@ impl<'data> TensorView<'data> { } /// The current tensor shape - pub fn shape(&'data self) -> &'data [usize] { + pub fn shape(&self) -> &[usize] { &self.shape } @@ -1169,9 +1187,10 @@ mod tests { } fn gpt2_like(n_heads: usize, model_id: &str) { - let mut tensors_desc = vec![]; - tensors_desc.push(("wte".to_string(), vec![50257, 768])); - tensors_desc.push(("wpe".to_string(), vec![1024, 768])); + let mut tensors_desc = vec![ + ("wte".to_string(), vec![50257, 768]), + ("wpe".to_string(), vec![1024, 768]), + ]; for i in 0..n_heads { tensors_desc.push((format!("h.{i}.ln_1.weight"), vec![768])); tensors_desc.push((format!("h.{i}.ln_1.bias"), vec![768])); From 3c6bc7fbecb19534d56e1d0ae5b6c777d761910f Mon Sep 17 00:00:00 2001 From: Nicolas Patry Date: Mon, 16 Jun 2025 06:32:30 +0000 Subject: [PATCH 26/37] Rename. (#621) --- safetensors/src/slice.rs | 5 +-- safetensors/src/tensor.rs | 69 ++++++++++++++++++++++----------------- 2 files changed, 40 insertions(+), 34 deletions(-) diff --git a/safetensors/src/slice.rs b/safetensors/src/slice.rs index 2dc1a62a..143e7e5d 100644 --- a/safetensors/src/slice.rs +++ b/safetensors/src/slice.rs @@ -376,10 +376,7 @@ impl<'data> SliceIterator<'data> { /// Gives back the amount of bytes still being in the iterator pub fn remaining_byte_len(&self) -> usize { - self.indices - .iter() - .map(|(start, stop)| stop - start) - .sum() + self.indices.iter().map(|(start, stop)| stop - start).sum() } /// Gives back the amount of bytes still being in the iterator diff --git a/safetensors/src/tensor.rs b/safetensors/src/tensor.rs index d10f8c9b..0a4edf3d 100644 --- a/safetensors/src/tensor.rs +++ b/safetensors/src/tensor.rs @@ -4,12 +4,11 @@ use crate::slice::{InvalidSlice, SliceIterator, TensorIndexer}; use core::fmt::Display; use core::str::Utf8Error; use serde::{ser::SerializeMap, Deserialize, Deserializer, Serialize, Serializer}; -use core::fmt::Display; #[cfg(feature = "std")] use std::io::Write; const MAX_HEADER_SIZE: usize = 100_000_000; -const SIZEOF_HEADER_SIZE_NUMBER: usize = size_of::(); +const N_LEN: usize = size_of::(); /// Possible errors that could occur while reading /// A Safetensor file. @@ -222,12 +221,11 @@ pub trait View { fn prepare( data: I, data_info: Option>, -) -> Result<(PreparedData, Vec), SafeTensorError> +) -> Result<(PreparedData, Vec), SafeTensorError> where S: AsRef + Ord + Display, V: View, I: IntoIterator, - { // Make sure we're sorting by descending dtype alignment // Then by name @@ -252,12 +250,11 @@ where tensors.push(tensor); } - let metadata: Metadata = Metadata::new(data_info, hmetadata)?; let mut metadata_buf = serde_json::to_string(&metadata)?.into_bytes(); // Force alignment to 8 bytes. - let aligned_metadata_len = metadata_buf.len().next_multiple_of(SIZEOF_HEADER_SIZE_NUMBER); + let aligned_metadata_len = metadata_buf.len().next_multiple_of(N_LEN); metadata_buf.resize(aligned_metadata_len, b' '); Ok(( @@ -288,7 +285,7 @@ pub fn serialize< tensors, ) = prepare(data, data_info)?; - let expected_size = SIZEOF_HEADER_SIZE_NUMBER + header_bytes.len() + offset; + let expected_size = N_LEN + header_bytes.len() + offset; let mut buffer: Vec = Vec::with_capacity(expected_size); buffer.extend(n.to_le_bytes()); buffer.extend(header_bytes); @@ -345,14 +342,12 @@ pub struct SafeTensors<'data> { impl<'data> SafeTensors<'data> { /// Given a byte-buffer representing the whole safetensor file /// parses the header, and returns the size of the header + the parsed data. - pub fn read_metadata( - buffer: &'data [u8], - ) -> Result<(usize, Metadata), SafeTensorError>{ + pub fn read_metadata(buffer: &'data [u8]) -> Result<(usize, Metadata), SafeTensorError> { let buffer_len = buffer.len(); - let Some(header_size_bytes) = buffer.get(..SIZEOF_HEADER_SIZE_NUMBER) else { + let Some(header_size_bytes) = buffer.get(..N_LEN) else { return Err(SafeTensorError::HeaderTooSmall); }; - let arr: [u8; SIZEOF_HEADER_SIZE_NUMBER] = header_size_bytes + let arr: [u8; N_LEN] = header_size_bytes .try_into() .expect("this can't fail due to how `header_size_bytes` is defined above"); let n: usize = u64::from_le_bytes(arr) @@ -364,16 +359,15 @@ impl<'data> SafeTensors<'data> { } let stop = n - .checked_add(SIZEOF_HEADER_SIZE_NUMBER) + .checked_add(N_LEN) .ok_or(SafeTensorError::InvalidHeaderLength)?; // the `.get(start..stop)` returns None if either index is out of bounds, // so this implicitly also ensures that `stop <= buffer.len()`. - let Some(header_bytes) = buffer.get(SIZEOF_HEADER_SIZE_NUMBER..stop) else { + let Some(header_bytes) = buffer.get(N_LEN..stop) else { return Err(SafeTensorError::InvalidHeaderLength); }; - let string = - core::str::from_utf8(&buffer[8..stop]).map_err(SafeTensorError::InvalidHeader)?; + let string = core::str::from_utf8(header_bytes).map_err(SafeTensorError::InvalidHeader)?; // Assert the string starts with { // NOTE: Add when we move to 0.4.0 // if !string.starts_with('{') { @@ -383,7 +377,7 @@ impl<'data> SafeTensors<'data> { serde_json::from_str(string).map_err(SafeTensorError::InvalidHeaderDeserialization)?; let metadata: Metadata = metadata.try_into()?; let buffer_end = metadata.validate()?; - if buffer_end + SIZEOF_HEADER_SIZE_NUMBER + n != buffer_len { + if buffer_end + N_LEN + n != buffer_len { return Err(SafeTensorError::MetadataIncompleteBuffer); } @@ -411,7 +405,7 @@ impl<'data> SafeTensors<'data> { /// ``` pub fn deserialize(buffer: &'data [u8]) -> Result { let (n, metadata) = SafeTensors::read_metadata(buffer)?; - let data = &buffer[SIZEOF_HEADER_SIZE_NUMBER + n..]; + let data = &buffer[N_LEN + n..]; Ok(Self { metadata, data }) } @@ -453,13 +447,17 @@ impl<'data> SafeTensors<'data> { /// The tensor returned is merely a view and the data is not owned by this /// structure. pub fn tensor(&self, tensor_name: &str) -> Result, SafeTensorError> { - let &index = self.metadata.index_map.get(tensor_name).ok_or_else( - || SafeTensorError::TensorNotFound(tensor_name.to_string()) - )?; - - let info = self.metadata.tensors.get(index).ok_or_else( - || SafeTensorError::TensorNotFound(tensor_name.to_string()) - )?; + let &index = self + .metadata + .index_map + .get(tensor_name) + .ok_or_else(|| SafeTensorError::TensorNotFound(tensor_name.to_string()))?; + + let info = self + .metadata + .tensors + .get(index) + .ok_or_else(|| SafeTensorError::TensorNotFound(tensor_name.to_string()))?; Ok(TensorView { dtype: info.dtype, @@ -618,7 +616,7 @@ impl Metadata { .checked_div(8) .ok_or(SafeTensorError::ValidationOverflow)?; - if e - s != nbytes { + if e - s != size { return Err(SafeTensorError::TensorInvalidInfo); } } @@ -714,15 +712,18 @@ impl<'data> TensorView<'data> { shape: Vec, data: &'data [u8], ) -> Result { - let n_bytes = data.len(); let n_elements: usize = shape.iter().product(); - let size = (n_elements * dtype.bitsize()) + let nbits = n_elements * dtype.bitsize(); + if nbits % 8 != 0 { + return Err(SafeTensorError::MisalignedSlice); + } + let size = nbits .checked_div(8) .ok_or(SafeTensorError::ValidationOverflow)?; - if n != size { - Err(SafeTensorError::InvalidTensorView(dtype, shape, n)) + if data.len() != size { + Err(SafeTensorError::InvalidTensorView(dtype, shape, data.len())) } else { Ok(Self { dtype, shape, data }) } @@ -1059,6 +1060,14 @@ mod tests { let data: Vec = vec![0u8, 1u8]; let shape = vec![1, 3]; let attn_0 = TensorView::new(Dtype::F4, shape, &data); + assert!(matches!(attn_0, Err(SafeTensorError::MisalignedSlice))); + } + + #[test] + fn test_serialization_fp4_invalid() { + let data: Vec = vec![0u8, 1u8]; + let shape = vec![1, 2]; + let attn_0 = TensorView::new(Dtype::F4, shape, &data); assert!(matches!( attn_0, Err(SafeTensorError::InvalidTensorView(Dtype::F4, _shape, _size)) From cbcbe14219835f0a05bd6377e8af737a4d591698 Mon Sep 17 00:00:00 2001 From: Nicolas Patry Date: Mon, 16 Jun 2025 13:23:05 +0000 Subject: [PATCH 27/37] Fixup into pyobject. (#622) --- bindings/python/src/lib.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/bindings/python/src/lib.rs b/bindings/python/src/lib.rs index b5b0cc68..527767f4 100644 --- a/bindings/python/src/lib.rs +++ b/bindings/python/src/lib.rs @@ -312,8 +312,8 @@ impl fmt::Display for Device { /// Parsing the device index. fn parse_device(name: &str) -> PyResult { let tokens: Vec<_> = name.split(':').collect(); - if let Ok([_, token]) = <[_; 2]>::try_from(tokens) { - Ok(token.parse()?) + if tokens.len() == 2 { + Ok(tokens[1].parse()?) } else { Err(SafetensorError::new_err(format!( "device {name} is invalid" @@ -357,9 +357,17 @@ impl<'py> IntoPyObject<'py> for Device { type Error = std::convert::Infallible; fn into_pyobject(self, py: Python<'py>) -> Result { - self.to_string() - .into_pyobject(py) - .map(pyo3::BoundObject::into_any) + match self { + Device::Cpu => "cpu".into_pyobject(py).map(|x| x.into_any()), + Device::Cuda(n) => format!("cuda:{n}").into_pyobject(py).map(|x| x.into_any()), + Device::Mps => "mps".into_pyobject(py).map(|x| x.into_any()), + Device::Npu(n) => format!("npu:{n}").into_pyobject(py).map(|x| x.into_any()), + Device::Xpu(n) => format!("xpu:{n}").into_pyobject(py).map(|x| x.into_any()), + Device::Xla(n) => format!("xla:{n}").into_pyobject(py).map(|x| x.into_any()), + Device::Mlu(n) => format!("mlu:{n}").into_pyobject(py).map(|x| x.into_any()), + Device::Hpu(n) => format!("hpu:{n}").into_pyobject(py).map(|x| x.into_any()), + Device::Anonymous(n) => n.into_pyobject(py).map(|x| x.into_any()), + } } } From f79f19d13277ec2f53fe107ee335f6492400b0cf Mon Sep 17 00:00:00 2001 From: Nicolas Patry Date: Mon, 16 Jun 2025 13:37:54 +0000 Subject: [PATCH 28/37] Adding a failing test on the device cast. (#623) --- .pre-commit-config.yaml | 2 +- bindings/python/tests/test_pt_comparison.py | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1a28594b..70e9ba35 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -39,7 +39,7 @@ repos: args: ["--line-length", "119", "--target-version", "py35"] types: ["python"] - repo: https://github.com/pycqa/flake8 - rev: 3.8.3 + rev: 7.2.0 hooks: - id: flake8 args: ["--config", "bindings/python/setup.cfg"] diff --git a/bindings/python/tests/test_pt_comparison.py b/bindings/python/tests/test_pt_comparison.py index a87f50aa..441fb351 100644 --- a/bindings/python/tests/test_pt_comparison.py +++ b/bindings/python/tests/test_pt_comparison.py @@ -303,6 +303,11 @@ def test_deserialization_device(self): self.assertEqual(weights["test"].device, torch.device("cpu")) torch.set_default_device(torch.device("cpu")) + torch.set_default_device(torch.device(0)) + weights = load_file(self.sf_filename) + self.assertEqual(weights["test"].device, torch.device("cpu")) + torch.set_default_device(torch.device("cpu")) + @unittest.skipIf(not torch.cuda.is_available(), "Cuda is not available") def test_deserialization_safe_gpu(self): # First time to hit disk From 6544bf21bfa416999ea4c304d11e1d2b9379518d Mon Sep 17 00:00:00 2001 From: Nicolas Patry Date: Tue, 24 Jun 2025 07:33:58 +0000 Subject: [PATCH 29/37] Rust release upgrade (cache v1 is discontinued). (#627) --- .github/workflows/rust-release.yml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/rust-release.yml b/.github/workflows/rust-release.yml index 03341944..0556a906 100644 --- a/.github/workflows/rust-release.yml +++ b/.github/workflows/rust-release.yml @@ -15,13 +15,9 @@ jobs: - name: Checkout repository uses: actions/checkout@v3 - - name: Install Rust - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - + - uses: dtolnay/rust-toolchain@stable - name: Cache Cargo Registry - uses: actions/cache@v1 + uses: actions/cache@v4 with: path: ~/.cargo/registry key: ubuntu-latest-cargo-registry-${{ hashFiles('**/Cargo.toml') }} From 8814598e41e2f840bef3a8f491a952ae999bf7ca Mon Sep 17 00:00:00 2001 From: Nicolas Patry Date: Thu, 3 Jul 2025 20:22:13 +0200 Subject: [PATCH 30/37] Re-adding support for u16, u32, u64. (#629) --- bindings/python/py_src/safetensors/torch.py | 47 +++++++++++++++------ 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/bindings/python/py_src/safetensors/torch.py b/bindings/python/py_src/safetensors/torch.py index 568d4aa7..4f5c801f 100644 --- a/bindings/python/py_src/safetensors/torch.py +++ b/bindings/python/py_src/safetensors/torch.py @@ -41,7 +41,9 @@ def storage_size(tensor: torch.Tensor) -> int: return tensor.nelement() * _SIZE[tensor.dtype] -def _filter_shared_not_shared(tensors: List[Set[str]], state_dict: Dict[str, torch.Tensor]) -> List[Set[str]]: +def _filter_shared_not_shared( + tensors: List[Set[str]], state_dict: Dict[str, torch.Tensor] +) -> List[Set[str]]: filtered_tensors = [] for shared in tensors: if len(shared) < 2: @@ -69,7 +71,11 @@ def _filter_shared_not_shared(tensors: List[Set[str]], state_dict: Dict[str, tor def _find_shared_tensors(state_dict: Dict[str, torch.Tensor]) -> List[Set[str]]: tensors = defaultdict(set) for k, v in state_dict.items(): - if v.device != torch.device("meta") and storage_ptr(v) != 0 and storage_size(v) != 0: + if ( + v.device != torch.device("meta") + and storage_ptr(v) != 0 + and storage_size(v) != 0 + ): # Need to add device as key because of multiple GPU. tensors[(v.device, storage_ptr(v), storage_size(v))].add(k) tensors = list(sorted(tensors.values())) @@ -78,7 +84,9 @@ def _find_shared_tensors(state_dict: Dict[str, torch.Tensor]) -> List[Set[str]]: def _is_complete(tensor: torch.Tensor) -> bool: - return tensor.data_ptr() == storage_ptr(tensor) and tensor.nelement() * _SIZE[tensor.dtype] == storage_size(tensor) + return tensor.data_ptr() == storage_ptr(tensor) and tensor.nelement() * _SIZE[ + tensor.dtype + ] == storage_size(tensor) def _remove_duplicate_names( @@ -97,7 +105,9 @@ def _remove_duplicate_names( shareds = _find_shared_tensors(state_dict) to_remove = defaultdict(list) for shared in shareds: - complete_names = set([name for name in shared if _is_complete(state_dict[name])]) + complete_names = set( + [name for name in shared if _is_complete(state_dict[name])] + ) if not complete_names: raise RuntimeError( "Error while trying to find names to remove to save state dict, but found no suitable name to keep" @@ -207,7 +217,9 @@ def load_model( """ state_dict = load_file(filename, device=device) model_state_dict = model.state_dict() - to_removes = _remove_duplicate_names(model_state_dict, preferred_names=state_dict.keys()) + to_removes = _remove_duplicate_names( + model_state_dict, preferred_names=state_dict.keys() + ) reverse_to_remove = {} for key, to_remove_group in to_removes.items(): @@ -273,7 +285,9 @@ def load_model( return missing, unexpected -def save(tensors: Dict[str, torch.Tensor], metadata: Optional[Dict[str, str]] = None) -> bytes: +def save( + tensors: Dict[str, torch.Tensor], metadata: Optional[Dict[str, str]] = None +) -> bytes: """ Saves a dictionary of tensors into raw bytes in safetensors format. @@ -337,7 +351,9 @@ def save_file( serialize_file(_flatten(tensors), filename, metadata=metadata) -def load_file(filename: Union[str, os.PathLike], device: Union[str, int] = "cpu") -> Dict[str, torch.Tensor]: +def load_file( + filename: Union[str, os.PathLike], device: Union[str, int] = "cpu" +) -> Dict[str, torch.Tensor]: """ Loads a safetensors file into torch format. @@ -402,11 +418,14 @@ def load(data: bytes) -> Dict[str, torch.Tensor]: _SIZE = { torch.int64: 8, + torch.uint64: 8, torch.float32: 4, torch.int32: 4, + torch.uint32: 4, torch.bfloat16: 2, torch.float16: 2, torch.int16: 2, + torch.uint16: 2, torch.uint8: 1, torch.int8: 1, torch.bool: 1, @@ -423,11 +442,11 @@ def load(data: bytes) -> Dict[str, torch.Tensor]: "F16": torch.float16, "BF16": torch.bfloat16, "I64": torch.int64, - # "U64": torch.uint64, + "U64": torch.uint64, "I32": torch.int32, - # "U32": torch.uint32, + "U32": torch.uint32, "I16": torch.int16, - # "U16": torch.uint16, + "U16": torch.uint16, "I8": torch.int8, "U8": torch.uint8, "BOOL": torch.bool, @@ -517,12 +536,16 @@ def _tobytes(tensor: torch.Tensor, name: str) -> bytes: def _flatten(tensors: Dict[str, torch.Tensor]) -> Dict[str, Dict[str, Any]]: if not isinstance(tensors, dict): - raise ValueError(f"Expected a dict of [str, torch.Tensor] but received {type(tensors)}") + raise ValueError( + f"Expected a dict of [str, torch.Tensor] but received {type(tensors)}" + ) invalid_tensors = [] for k, v in tensors.items(): if not isinstance(v, torch.Tensor): - raise ValueError(f"Key `{k}` is invalid, expected torch.Tensor but received {type(v)}") + raise ValueError( + f"Key `{k}` is invalid, expected torch.Tensor but received {type(v)}" + ) if v.layout != torch.strided: invalid_tensors.append(k) From 48933f3822e6980ec01ff866b1b412f7efa84620 Mon Sep 17 00:00:00 2001 From: Nicolas Patry Date: Fri, 1 Aug 2025 17:25:35 +0200 Subject: [PATCH 31/37] Adding _safe_open_handle. (#608) * [WIP]. Adding safe_handle. * Adding S3. * File handle becomes private for merge. --- .pre-commit-config.yaml | 15 ++- .../python/py_src/safetensors/__init__.py | 1 + bindings/python/src/lib.rs | 113 ++++++++++++++++++ bindings/python/tests/test_handle.py | 65 ++++++++++ 4 files changed, 186 insertions(+), 8 deletions(-) create mode 100644 bindings/python/tests/test_handle.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 70e9ba35..27dc28c0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -38,12 +38,11 @@ repos: name: "Python (black)" args: ["--line-length", "119", "--target-version", "py35"] types: ["python"] - - repo: https://github.com/pycqa/flake8 - rev: 7.2.0 + - repo: https://github.com/astral-sh/ruff-pre-commit + # Ruff version. + rev: v0.11.11 hooks: - - id: flake8 - args: ["--config", "bindings/python/setup.cfg"] - - repo: https://github.com/pre-commit/mirrors-isort - rev: v5.7.0 # Use the revision sha / tag you want to point at - hooks: - - id: isort + # Run the linter. + - id: ruff-check + # Run the formatter. + - id: ruff-format diff --git a/bindings/python/py_src/safetensors/__init__.py b/bindings/python/py_src/safetensors/__init__.py index c9a5d2ca..0aea2154 100644 --- a/bindings/python/py_src/safetensors/__init__.py +++ b/bindings/python/py_src/safetensors/__init__.py @@ -4,6 +4,7 @@ __version__, deserialize, safe_open, + _safe_open_handle, serialize, serialize_file, ) diff --git a/bindings/python/src/lib.rs b/bindings/python/src/lib.rs index 527767f4..36f784b4 100644 --- a/bindings/python/src/lib.rs +++ b/bindings/python/src/lib.rs @@ -1258,6 +1258,118 @@ pyo3::create_exception!( "Custom Python Exception for Safetensor errors." ); +#[pyclass] +#[allow(non_camel_case_types)] +struct _safe_open_handle { + inner: Option, +} + +impl _safe_open_handle { + fn inner(&self) -> PyResult<&Open> { + let inner = self + .inner + .as_ref() + .ok_or_else(|| SafetensorError::new_err("File is closed".to_string()))?; + Ok(inner) + } +} + +#[pymethods] +impl _safe_open_handle { + #[new] + #[pyo3(signature = (f, framework, device=Some(Device::Cpu)))] + fn new(f: PyObject, framework: Framework, device: Option) -> PyResult { + let filename = Python::with_gil(|py| -> PyResult { + let _ = f.getattr(py, "fileno")?; + let filename = f.getattr(py, "name")?; + let filename: PathBuf = filename.extract(py)?; + Ok(filename) + })?; + let inner = Some(Open::new(filename, framework, device)?); + Ok(Self { inner }) + } + + /// Return the special non tensor information in the header + /// + /// Returns: + /// (`Dict[str, str]`): + /// The freeform metadata. + pub fn metadata(&self) -> PyResult>> { + Ok(self.inner()?.metadata()) + } + + /// Returns the names of the tensors in the file. + /// + /// Returns: + /// (`List[str]`): + /// The name of the tensors contained in that file + pub fn keys(&self) -> PyResult> { + self.inner()?.keys() + } + + /// Returns the names of the tensors in the file, ordered by offset. + /// + /// Returns: + /// (`List[str]`): + /// The name of the tensors contained in that file + pub fn offset_keys(&self) -> PyResult> { + self.inner()?.offset_keys() + } + + /// Returns a full tensor + /// + /// Args: + /// name (`str`): + /// The name of the tensor you want + /// + /// Returns: + /// (`Tensor`): + /// The tensor in the framework you opened the file for. + /// + /// Example: + /// ```python + /// from safetensors import safe_open + /// + /// with safe_open("model.safetensors", framework="pt", device=0) as f: + /// tensor = f.get_tensor("embedding") + /// + /// ``` + pub fn get_tensor(&self, name: &str) -> PyResult { + self.inner()?.get_tensor(name) + } + + /// Returns a full slice view object + /// + /// Args: + /// name (`str`): + /// The name of the tensor you want + /// + /// Returns: + /// (`PySafeSlice`): + /// A dummy object you can slice into to get a real tensor + /// Example: + /// ```python + /// from safetensors import safe_open + /// + /// with safe_open("model.safetensors", framework="pt", device=0) as f: + /// tensor_part = f.get_slice("embedding")[:, ::8] + /// + /// ``` + pub fn get_slice(&self, name: &str) -> PyResult { + self.inner()?.get_slice(name) + } + + /// Start the context manager + pub fn __enter__(slf: Py) -> Py { + slf + } + + /// Exits the context manager + pub fn __exit__(&mut self, _exc_type: PyObject, _exc_value: PyObject, _traceback: PyObject) { + self.inner = None; + } +} + /// A Python module implemented in Rust. #[pymodule(gil_used = false)] fn _safetensors_rust(m: &PyBound<'_, PyModule>) -> PyResult<()> { @@ -1265,6 +1377,7 @@ fn _safetensors_rust(m: &PyBound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(serialize_file, m)?)?; m.add_function(wrap_pyfunction!(deserialize, m)?)?; m.add_class::()?; + m.add_class::<_safe_open_handle>()?; m.add("SafetensorError", m.py().get_type::())?; m.add("__version__", env!("CARGO_PKG_VERSION"))?; Ok(()) diff --git a/bindings/python/tests/test_handle.py b/bindings/python/tests/test_handle.py new file mode 100644 index 00000000..aaf0717b --- /dev/null +++ b/bindings/python/tests/test_handle.py @@ -0,0 +1,65 @@ +import unittest + +import numpy as np + +from safetensors import _safe_open_handle +from safetensors.numpy import save_file, save + + +class ReadmeTestCase(unittest.TestCase): + def assertTensorEqual(self, tensors1, tensors2, equality_fn): + self.assertEqual(tensors1.keys(), tensors2.keys(), "tensor keys don't match") + + for k, v1 in tensors1.items(): + v2 = tensors2[k] + + self.assertTrue(equality_fn(v1, v2), f"{k} tensors are different") + + def test_numpy_example(self): + tensors = {"a": np.zeros((2, 2)), "b": np.zeros((2, 3), dtype=np.uint8)} + + save_file(tensors, "./out_np.safetensors") + + # Now loading + loaded = {} + with open("./out_np.safetensors", "r") as f: + with safe_open_handle(f, framework="np", device="cpu") as g: + for key in g.keys(): + loaded[key] = g.get_tensor(key) + self.assertTensorEqual(tensors, loaded, np.allclose) + + def test_fsspec(self): + import fsspec + + tensors = {"a": np.zeros((2, 2)), "b": np.zeros((2, 3), dtype=np.uint8)} + + fs = fsspec.filesystem("file") + byts = save(tensors) + with fs.open("fs.safetensors", "wb") as f: + f.write(byts) + # Now loading + loaded = {} + with fs.open("fs.safetensors", "rb") as f: + with safe_open_handle(f, framework="np", device="cpu") as g: + for key in g.keys(): + loaded[key] = g.get_tensor(key) + self.assertTensorEqual(tensors, loaded, np.allclose) + + @unittest.skip("Will not work without s3 access") + def test_fsspec_s3(self): + import s3fs + + tensors = {"a": np.zeros((2, 2)), "b": np.zeros((2, 3), dtype=np.uint8)} + + s3 = s3fs.S3FileSystem(anon=True) + byts = save(tensors) + print(s3.ls("my-bucket")) + with s3.open("out/fs.safetensors", "wb") as f: + f.write(byts) + # Now loading + loaded = {} + with s3.open("out/fs.safetensors", "rb") as f: + with safe_open_handle(f, framework="np", device="cpu") as g: + for key in g.keys(): + loaded[key] = g.get_tensor(key) + self.assertTensorEqual(tensors, loaded, np.allclose) From 7dfa63cf0f62ac74500d92b15844fcd910eadbab Mon Sep 17 00:00:00 2001 From: Alexander Lent Date: Mon, 4 Aug 2025 03:40:07 -0400 Subject: [PATCH 32/37] Fix test_simple.py for 0.6.0 (#634) These tests look for error messages which changed in commit 3012241/PR#616. Fixes: 3012241 ("Better error handling through improved `Display` and `Error` impls (#616)") --- bindings/python/tests/test_simple.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bindings/python/tests/test_simple.py b/bindings/python/tests/test_simple.py index d198391f..1db8c711 100644 --- a/bindings/python/tests/test_simple.py +++ b/bindings/python/tests/test_simple.py @@ -175,7 +175,7 @@ def test_file_not_found(self): with self.assertRaises(FileNotFoundError) as ctx: with safe_open("notafile", framework="pt"): pass - self.assertEqual(str(ctx.exception), 'No such file or directory: "notafile"') + self.assertEqual(str(ctx.exception), 'No such file or directory: notafile') class ReadmeTestCase(unittest.TestCase): @@ -345,19 +345,19 @@ def test_numpy_slice(self): tensor = slice_[2:, 20] self.assertEqual( str(cm.exception), - "Error during slicing [2:, 20] with shape [10, 5]: SliceOutOfRange { dim_index: 1, asked: 20, dim_size: 5 }", + "Error during slicing [2:, 20] with shape [10, 5]: index 20 out of bounds for tensor dimension #1 of size 5", ) with self.assertRaises(SafetensorError) as cm: tensor = slice_[:20] self.assertEqual( str(cm.exception), - "Error during slicing [:20] with shape [10, 5]: SliceOutOfRange { dim_index: 0, asked: 19, dim_size: 10 }", + "Error during slicing [:20] with shape [10, 5]: index 19 out of bounds for tensor dimension #0 of size 10", ) with self.assertRaises(SafetensorError) as cm: tensor = slice_[:, :20] self.assertEqual( str(cm.exception), - "Error during slicing [:, :20] with shape [10, 5]: SliceOutOfRange { dim_index: 1, asked: 19, dim_size: 5 }", + "Error during slicing [:, :20] with shape [10, 5]: index 19 out of bounds for tensor dimension #1 of size 5", ) From b9ccdc69c0ba1f3fad785960981600a6a7553969 Mon Sep 17 00:00:00 2001 From: Nicolas Patry Date: Tue, 5 Aug 2025 18:42:32 +0200 Subject: [PATCH 33/37] GH action... once again. (#635) * GH action... once again. * Using ruff instead of * Moving to ruff instead of black * Fixing the stub to not use black either. * . * Forgot to flush. * Old torch version dont have unsigned variants. * Fixing the handle tests. * Installing missing numpy. * Use numpy > 2 * ... * Yaml. * .. * ... * ..... * So annoying. * Fix uv lock. * Fix the fp4 tests. * Download hdf5 library. * .... * .. * .. * .. * .. * .. * .. * .. * . * .. * Fixing MLX implementation with newer versions. * Split macos into x86 legacy and latest aarch64. * .. * .. * Lock. * .. * . * Numpy version. --- .github/workflows/python.yml | 49 +++- bindings/python/benches/test_pt.py | 10 +- bindings/python/convert.py | 139 ++++++++--- bindings/python/convert_all.py | 9 +- .../python/py_src/safetensors/__init__.pyi | 19 +- bindings/python/py_src/safetensors/mlx.py | 4 +- bindings/python/py_src/safetensors/numpy.py | 18 +- bindings/python/py_src/safetensors/paddle.py | 12 +- .../python/py_src/safetensors/tensorflow.py | 4 +- bindings/python/py_src/safetensors/torch.py | 23 +- bindings/python/pyproject.toml | 14 +- bindings/python/stub.py | 56 +++-- bindings/python/tests/test_handle.py | 6 +- bindings/python/tests/test_mlx_comparison.py | 8 +- bindings/python/tests/test_pt_comparison.py | 2 +- bindings/python/tests/test_pt_model.py | 36 ++- bindings/python/tests/test_simple.py | 10 +- bindings/python/uv.lock | 227 ++++++------------ 18 files changed, 391 insertions(+), 255 deletions(-) diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index fa99ae17..29dbb1d1 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -9,10 +9,10 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-latest, macos-13, windows-latest] + os: [ubuntu-latest, windows-latest] # Lowest and highest, no version specified so that # new releases get automatically tested against - version: [{torch: torch==1.10, python: "3.9", arch: "x64"}, {torch: torch, python: "3.12", arch: "x64"}] + version: [{torch: torch==1.10, python: "3.9", arch: "x64", numpy: numpy==1.26.4}, {torch: torch, python: "3.12", arch: "x64", numpy: numpy}] # TODO this would include macos ARM target. # however jax has an illegal instruction issue # that exists only in CI (probably difference in instruction support). @@ -26,7 +26,20 @@ jobs: version: torch: torch python: "3.13" + numpy: numpy arch: "x64-freethreaded" + - os: macos-13 + version: + torch: torch==1.10 + numpy: "numpy==1.26" + python: "3.9" + arch: "x64" + - os: macos-latest + version: + torch: torch + python: "3.12" + numpy: numpy + arch: "arm64" defaults: run: working-directory: ./bindings/python @@ -63,14 +76,14 @@ jobs: - name: Run Audit run: cargo audit -D warnings - - name: Install - run: | - pip install -U pip - pip install .[numpy] + # - name: Install + # run: | + # pip install -U pip - name: Install (torch) if: matrix.version.arch != 'x64-freethreaded' run: | + pip install ${{ matrix.version.numpy }} pip install ${{ matrix.version.torch }} shell: bash @@ -80,14 +93,22 @@ jobs: pip install ${{ matrix.version.torch }} --index-url https://download.pytorch.org/whl/cu126 shell: bash + - name: Install (hdf5 non windows) + if: matrix.os == 'ubuntu-latest' && matrix.version.arch != 'x64-freethreaded' + run: | + sudo apt-get update + sudo apt-get install libhdf5-dev + - name: Install (tensorflow) if: matrix.version.arch != 'x64-freethreaded' run: | pip install .[tensorflow] + # Force reinstall of numpy, tensorflow uses numpy 2 even on 3.9 + pip install ${{ matrix.version.numpy }} shell: bash - name: Install (jax, flax) - if: matrix.os != 'windows-latest' && matrix.version.arch != "x64-freethreaded" + if: matrix.os != 'windows-latest' && matrix.version.arch != 'x64-freethreaded' run: pip install .[jax] shell: bash @@ -101,14 +122,24 @@ jobs: - name: Check style run: | pip install .[quality] - black --check --line-length 119 --target-version py35 py_src/safetensors tests + ruff format --check . - name: Run tests + if: matrix.version.arch != 'x64-freethreaded' run: | cargo test - pip install .[testing] + pip install ".[testing]" pytest -sv tests/ + - name: Run tests (freethreaded) + if: matrix.version.arch == 'x64-freethreaded' + run: | + cargo test + pip install ".[testingfree]" + pip install pytest numpy + pytest -sv tests/test_pt* + pytest -sv tests/test_simple.py + test_s390x_big_endian: runs-on: ubuntu-latest permissions: diff --git a/bindings/python/benches/test_pt.py b/bindings/python/benches/test_pt.py index e9c06fcf..b19db48a 100644 --- a/bindings/python/benches/test_pt.py +++ b/bindings/python/benches/test_pt.py @@ -118,7 +118,10 @@ def test_pt_sf_load_gpu(benchmark): assert torch.allclose(v, tv) -@pytest.mark.skipif(not hasattr(torch.backends, "mps") or not torch.backends.mps.is_available(), reason="requires mps") +@pytest.mark.skipif( + not hasattr(torch.backends, "mps") or not torch.backends.mps.is_available(), + reason="requires mps", +) def test_pt_pt_load_mps(benchmark): # benchmark something weights = create_gpt2(12) @@ -133,7 +136,10 @@ def test_pt_pt_load_mps(benchmark): assert torch.allclose(v, tv) -@pytest.mark.skipif(not hasattr(torch.backends, "mps") or not torch.backends.mps.is_available(), reason="requires mps") +@pytest.mark.skipif( + not hasattr(torch.backends, "mps") or not torch.backends.mps.is_available(), + reason="requires mps", +) def test_pt_sf_load_mps(benchmark): # benchmark something weights = create_gpt2(12) diff --git a/bindings/python/convert.py b/bindings/python/convert.py index 3a2e4d1f..8088fa90 100644 --- a/bindings/python/convert.py +++ b/bindings/python/convert.py @@ -8,7 +8,13 @@ import torch -from huggingface_hub import CommitInfo, CommitOperationAdd, Discussion, HfApi, hf_hub_download +from huggingface_hub import ( + CommitInfo, + CommitOperationAdd, + Discussion, + HfApi, + hf_hub_download, +) from huggingface_hub.file_download import repo_folder_name from safetensors.torch import _find_shared_tensors, _is_complete, load_file, save_file @@ -49,7 +55,9 @@ def _remove_duplicate_names( shareds = _find_shared_tensors(state_dict) to_remove = defaultdict(list) for shared in shareds: - complete_names = set([name for name in shared if _is_complete(state_dict[name])]) + complete_names = set( + [name for name in shared if _is_complete(state_dict[name])] + ) if not complete_names: if len(shared) == 1: # Force contiguous @@ -81,14 +89,20 @@ def _remove_duplicate_names( return to_remove -def get_discard_names(model_id: str, revision: Optional[str], folder: str, token: Optional[str]) -> List[str]: +def get_discard_names( + model_id: str, revision: Optional[str], folder: str, token: Optional[str] +) -> List[str]: try: import json import transformers config_filename = hf_hub_download( - model_id, revision=revision, filename="config.json", token=token, cache_dir=folder + model_id, + revision=revision, + filename="config.json", + token=token, + cache_dir=folder, ) with open(config_filename, "r") as f: config = json.load(f) @@ -129,10 +143,19 @@ def rename(pt_filename: str) -> str: def convert_multi( - model_id: str, *, revision=Optional[str], folder: str, token: Optional[str], discard_names: List[str] + model_id: str, + *, + revision=Optional[str], + folder: str, + token: Optional[str], + discard_names: List[str], ) -> ConversionResult: filename = hf_hub_download( - repo_id=model_id, revision=revision, filename="pytorch_model.bin.index.json", token=token, cache_dir=folder + repo_id=model_id, + revision=revision, + filename="pytorch_model.bin.index.json", + token=token, + cache_dir=folder, ) with open(filename, "r") as f: data = json.load(f) @@ -140,7 +163,9 @@ def convert_multi( filenames = set(data["weight_map"].values()) local_filenames = [] for filename in filenames: - pt_filename = hf_hub_download(repo_id=model_id, filename=filename, token=token, cache_dir=folder) + pt_filename = hf_hub_download( + repo_id=model_id, filename=filename, token=token, cache_dir=folder + ) sf_filename = rename(pt_filename) sf_filename = os.path.join(folder, sf_filename) @@ -156,7 +181,8 @@ def convert_multi( local_filenames.append(index) operations = [ - CommitOperationAdd(path_in_repo=os.path.basename(local), path_or_fileobj=local) for local in local_filenames + CommitOperationAdd(path_in_repo=os.path.basename(local), path_or_fileobj=local) + for local in local_filenames ] errors: List[Tuple[str, "Exception"]] = [] @@ -164,10 +190,19 @@ def convert_multi( def convert_single( - model_id: str, *, revision: Optional[str], folder: str, token: Optional[str], discard_names: List[str] + model_id: str, + *, + revision: Optional[str], + folder: str, + token: Optional[str], + discard_names: List[str], ) -> ConversionResult: pt_filename = hf_hub_download( - repo_id=model_id, revision=revision, filename="pytorch_model.bin", token=token, cache_dir=folder + repo_id=model_id, + revision=revision, + filename="pytorch_model.bin", + token=token, + cache_dir=folder, ) sf_name = "model.safetensors" @@ -219,20 +254,30 @@ def create_diff(pt_infos: Dict[str, List[str]], sf_infos: Dict[str, List[str]]) sf_only = sf_set - pt_set if pt_only: - errors.append(f"{key} : PT warnings contain {pt_only} which are not present in SF warnings") + errors.append( + f"{key} : PT warnings contain {pt_only} which are not present in SF warnings" + ) if sf_only: - errors.append(f"{key} : SF warnings contain {sf_only} which are not present in PT warnings") + errors.append( + f"{key} : SF warnings contain {sf_only} which are not present in PT warnings" + ) return "\n".join(errors) -def previous_pr(api: "HfApi", model_id: str, pr_title: str, revision=Optional[str]) -> Optional["Discussion"]: +def previous_pr( + api: "HfApi", model_id: str, pr_title: str, revision=Optional[str] +) -> Optional["Discussion"]: try: revision_commit = api.model_info(model_id, revision=revision).sha discussions = api.get_repo_discussions(repo_id=model_id) except Exception: return None for discussion in discussions: - if discussion.status in {"open", "closed"} and discussion.is_pull_request and discussion.title == pr_title: + if ( + discussion.status in {"open", "closed"} + and discussion.is_pull_request + and discussion.title == pr_title + ): commits = api.list_repo_commits(model_id, revision=discussion.git_reference) if revision_commit == commits[1].commit_id: @@ -241,7 +286,12 @@ def previous_pr(api: "HfApi", model_id: str, pr_title: str, revision=Optional[st def convert_generic( - model_id: str, *, revision=Optional[str], folder: str, filenames: Set[str], token: Optional[str] + model_id: str, + *, + revision=Optional[str], + folder: str, + filenames: Set[str], + token: Optional[str], ) -> ConversionResult: operations = [] errors = [] @@ -251,7 +301,11 @@ def convert_generic( prefix, ext = os.path.splitext(filename) if ext in extensions: pt_filename = hf_hub_download( - model_id, revision=revision, filename=filename, token=token, cache_dir=folder + model_id, + revision=revision, + filename=filename, + token=token, + cache_dir=folder, ) dirname, raw_filename = os.path.split(filename) if raw_filename == "pytorch_model.bin": @@ -263,7 +317,11 @@ def convert_generic( sf_filename = os.path.join(folder, sf_in_repo) try: convert_file(pt_filename, sf_filename, discard_names=[]) - operations.append(CommitOperationAdd(path_in_repo=sf_in_repo, path_or_fileobj=sf_filename)) + operations.append( + CommitOperationAdd( + path_in_repo=sf_in_repo, path_or_fileobj=sf_filename + ) + ) except Exception as e: errors.append((pt_filename, e)) return operations, errors @@ -285,28 +343,50 @@ def convert( pr = previous_pr(api, model_id, pr_title, revision=revision) library_name = getattr(info, "library_name", None) - if any(filename.endswith(".safetensors") for filename in filenames) and not force: - raise AlreadyExists(f"Model {model_id} is already converted, skipping..") + if ( + any(filename.endswith(".safetensors") for filename in filenames) + and not force + ): + raise AlreadyExists( + f"Model {model_id} is already converted, skipping.." + ) elif pr is not None and not force: url = f"https://huggingface.co/{model_id}/discussions/{pr.num}" new_pr = pr - raise AlreadyExists(f"Model {model_id} already has an open PR check out {url}") + raise AlreadyExists( + f"Model {model_id} already has an open PR check out {url}" + ) elif library_name == "transformers": - - discard_names = get_discard_names(model_id, revision=revision, folder=folder, token=api.token) + discard_names = get_discard_names( + model_id, revision=revision, folder=folder, token=api.token + ) if "pytorch_model.bin" in filenames: operations, errors = convert_single( - model_id, revision=revision, folder=folder, token=api.token, discard_names=discard_names + model_id, + revision=revision, + folder=folder, + token=api.token, + discard_names=discard_names, ) elif "pytorch_model.bin.index.json" in filenames: operations, errors = convert_multi( - model_id, revision=revision, folder=folder, token=api.token, discard_names=discard_names + model_id, + revision=revision, + folder=folder, + token=api.token, + discard_names=discard_names, ) else: - raise RuntimeError(f"Model {model_id} doesn't seem to be a valid pytorch model. Cannot convert") + raise RuntimeError( + f"Model {model_id} doesn't seem to be a valid pytorch model. Cannot convert" + ) else: operations, errors = convert_generic( - model_id, revision=revision, folder=folder, filenames=filenames, token=api.token + model_id, + revision=revision, + folder=folder, + filenames=filenames, + token=api.token, ) if operations: @@ -366,7 +446,9 @@ def convert( " Continue [Y/n] ?" ) if txt.lower() in {"", "y"}: - commit_info, errors = convert(api, model_id, revision=args.revision, force=args.force) + commit_info, errors = convert( + api, model_id, revision=args.revision, force=args.force + ) string = f""" ### Success 🔥 Yay! This model was successfully converted and a PR was open using your token, here: @@ -375,7 +457,8 @@ def convert( if errors: string += "\nErrors during conversion:\n" string += "\n".join( - f"Error while converting {filename}: {e}, skipped conversion" for filename, e in errors + f"Error while converting {filename}: {e}, skipped conversion" + for filename, e in errors ) print(string) else: diff --git a/bindings/python/convert_all.py b/bindings/python/convert_all.py index 39fe9b4e..a2f97715 100644 --- a/bindings/python/convert_all.py +++ b/bindings/python/convert_all.py @@ -1,4 +1,5 @@ """Simple utility tool to convert automatically most downloaded models""" + from convert import AlreadyExists, convert from huggingface_hub import HfApi, ModelFilter, ModelSearchArguments from transformers import AutoConfig @@ -10,7 +11,11 @@ total = 50 models = list( - api.list_models(filter=ModelFilter(library=args.library.Transformers), sort="downloads", direction=-1) + api.list_models( + filter=ModelFilter(library=args.library.Transformers), + sort="downloads", + direction=-1, + ) )[:total] correct = 0 @@ -40,4 +45,4 @@ print(f"Errors: {errors}") print(f"File size is difference {len(errors)}") - print(f"Correct rate {correct}/{total} ({correct/total * 100:.2f}%)") + print(f"Correct rate {correct}/{total} ({correct / total * 100:.2f}%)") diff --git a/bindings/python/py_src/safetensors/__init__.pyi b/bindings/python/py_src/safetensors/__init__.pyi index fa74b755..a89e0655 100644 --- a/bindings/python/py_src/safetensors/__init__.pyi +++ b/bindings/python/py_src/safetensors/__init__.pyi @@ -49,7 +49,7 @@ def serialize_file(tensor_dict, filename, metadata=None): Returns: (`NoneType`): - On success return None. + On success return None """ pass @@ -68,19 +68,21 @@ class safe_open: device (`str`, defaults to `"cpu"`): The device on which you want the tensors. """ - def __init__(self, filename, framework, device=...): pass + def __enter__(self): """ Start the context manager """ pass + def __exit__(self, _exc_type, _exc_value, _traceback): """ Exits the context manager """ pass + def get_slice(self, name): """ Returns a full slice view object @@ -102,6 +104,7 @@ class safe_open: ``` """ pass + def get_tensor(self, name): """ Returns a full tensor @@ -124,6 +127,7 @@ class safe_open: ``` """ pass + def keys(self): """ Returns the names of the tensors in the file. @@ -133,6 +137,7 @@ class safe_open: The name of the tensors contained in that file """ pass + def metadata(self): """ Return the special non tensor information in the header @@ -143,6 +148,16 @@ class safe_open: """ pass + def offset_keys(self): + """ + Returns the names of the tensors in the file, ordered by offset. + + Returns: + (`List[str]`): + The name of the tensors contained in that file + """ + pass + class SafetensorError(Exception): """ Custom Python Exception for Safetensor errors. diff --git a/bindings/python/py_src/safetensors/mlx.py b/bindings/python/py_src/safetensors/mlx.py index df04e710..985b73b9 100644 --- a/bindings/python/py_src/safetensors/mlx.py +++ b/bindings/python/py_src/safetensors/mlx.py @@ -7,7 +7,9 @@ from safetensors import numpy, safe_open -def save(tensors: Dict[str, mx.array], metadata: Optional[Dict[str, str]] = None) -> bytes: +def save( + tensors: Dict[str, mx.array], metadata: Optional[Dict[str, str]] = None +) -> bytes: """ Saves a dictionary of tensors into raw bytes in safetensors format. diff --git a/bindings/python/py_src/safetensors/numpy.py b/bindings/python/py_src/safetensors/numpy.py index 89e00e11..282f2871 100644 --- a/bindings/python/py_src/safetensors/numpy.py +++ b/bindings/python/py_src/safetensors/numpy.py @@ -13,7 +13,9 @@ def _tobytes(tensor: np.ndarray) -> bytes: return tensor.tobytes() -def save(tensor_dict: Dict[str, np.ndarray], metadata: Optional[Dict[str, str]] = None) -> bytes: +def save( + tensor_dict: Dict[str, np.ndarray], metadata: Optional[Dict[str, str]] = None +) -> bytes: """ Saves a dictionary of tensors into raw bytes in safetensors format. @@ -38,14 +40,19 @@ def save(tensor_dict: Dict[str, np.ndarray], metadata: Optional[Dict[str, str]] byte_data = save(tensors) ``` """ - flattened = {k: {"dtype": v.dtype.name, "shape": v.shape, "data": _tobytes(v)} for k, v in tensor_dict.items()} + flattened = { + k: {"dtype": v.dtype.name, "shape": v.shape, "data": _tobytes(v)} + for k, v in tensor_dict.items() + } serialized = serialize(flattened, metadata=metadata) result = bytes(serialized) return result def save_file( - tensor_dict: Dict[str, np.ndarray], filename: Union[str, os.PathLike], metadata: Optional[Dict[str, str]] = None + tensor_dict: Dict[str, np.ndarray], + filename: Union[str, os.PathLike], + metadata: Optional[Dict[str, str]] = None, ) -> None: """ Saves a dictionary of tensors into raw bytes in safetensors format. @@ -73,7 +80,10 @@ def save_file( save_file(tensors, "model.safetensors") ``` """ - flattened = {k: {"dtype": v.dtype.name, "shape": v.shape, "data": _tobytes(v)} for k, v in tensor_dict.items()} + flattened = { + k: {"dtype": v.dtype.name, "shape": v.shape, "data": _tobytes(v)} + for k, v in tensor_dict.items() + } serialize_file(flattened, filename, metadata=metadata) diff --git a/bindings/python/py_src/safetensors/paddle.py b/bindings/python/py_src/safetensors/paddle.py index cec36866..5ec459e3 100644 --- a/bindings/python/py_src/safetensors/paddle.py +++ b/bindings/python/py_src/safetensors/paddle.py @@ -7,7 +7,9 @@ from safetensors import numpy -def save(tensors: Dict[str, paddle.Tensor], metadata: Optional[Dict[str, str]] = None) -> bytes: +def save( + tensors: Dict[str, paddle.Tensor], metadata: Optional[Dict[str, str]] = None +) -> bytes: """ Saves a dictionary of tensors into raw bytes in safetensors format. @@ -98,7 +100,9 @@ def load(data: bytes, device: str = "cpu") -> Dict[str, paddle.Tensor]: return _np2paddle(flat, device) -def load_file(filename: Union[str, os.PathLike], device="cpu") -> Dict[str, paddle.Tensor]: +def load_file( + filename: Union[str, os.PathLike], device="cpu" +) -> Dict[str, paddle.Tensor]: """ Loads a safetensors file into paddle format. @@ -126,7 +130,9 @@ def load_file(filename: Union[str, os.PathLike], device="cpu") -> Dict[str, padd return output -def _np2paddle(numpy_dict: Dict[str, np.ndarray], device: str = "cpu") -> Dict[str, paddle.Tensor]: +def _np2paddle( + numpy_dict: Dict[str, np.ndarray], device: str = "cpu" +) -> Dict[str, paddle.Tensor]: for k, v in numpy_dict.items(): numpy_dict[k] = paddle.to_tensor(v, place=device) return numpy_dict diff --git a/bindings/python/py_src/safetensors/tensorflow.py b/bindings/python/py_src/safetensors/tensorflow.py index 8513f803..c2bfc936 100644 --- a/bindings/python/py_src/safetensors/tensorflow.py +++ b/bindings/python/py_src/safetensors/tensorflow.py @@ -7,7 +7,9 @@ from safetensors import numpy, safe_open -def save(tensors: Dict[str, tf.Tensor], metadata: Optional[Dict[str, str]] = None) -> bytes: +def save( + tensors: Dict[str, tf.Tensor], metadata: Optional[Dict[str, str]] = None +) -> bytes: """ Saves a dictionary of tensors into raw bytes in safetensors format. diff --git a/bindings/python/py_src/safetensors/torch.py b/bindings/python/py_src/safetensors/torch.py index 4f5c801f..49405bf3 100644 --- a/bindings/python/py_src/safetensors/torch.py +++ b/bindings/python/py_src/safetensors/torch.py @@ -2,6 +2,7 @@ import sys from collections import defaultdict from typing import Any, Dict, List, Optional, Set, Tuple, Union +from packaging.version import Version import torch @@ -418,14 +419,11 @@ def load(data: bytes) -> Dict[str, torch.Tensor]: _SIZE = { torch.int64: 8, - torch.uint64: 8, torch.float32: 4, torch.int32: 4, - torch.uint32: 4, torch.bfloat16: 2, torch.float16: 2, torch.int16: 2, - torch.uint16: 2, torch.uint8: 1, torch.int8: 1, torch.bool: 1, @@ -435,6 +433,14 @@ def load(data: bytes) -> Dict[str, torch.Tensor]: _float8_e8m0: 1, _float4_e2m1_x2: 1, } +if Version(torch.__version__) > Version("2.0.0"): + _SIZE.update( + { + torch.uint64: 8, + torch.uint32: 4, + torch.uint16: 2, + } + ) _TYPES = { "F64": torch.float64, @@ -442,17 +448,22 @@ def load(data: bytes) -> Dict[str, torch.Tensor]: "F16": torch.float16, "BF16": torch.bfloat16, "I64": torch.int64, - "U64": torch.uint64, "I32": torch.int32, - "U32": torch.uint32, "I16": torch.int16, - "U16": torch.uint16, "I8": torch.int8, "U8": torch.uint8, "BOOL": torch.bool, "F8_E4M3": _float8_e4m3fn, "F8_E5M2": _float8_e5m2, } +if Version(torch.__version__) > Version("2.0.0"): + _TYPES.update( + { + "U64": torch.uint64, + "U32": torch.uint32, + "U16": torch.uint16, + } + ) def _getdtype(dtype_str: str) -> torch.dtype: diff --git a/bindings/python/pyproject.toml b/bindings/python/pyproject.toml index 1409126a..47dbb19d 100644 --- a/bindings/python/pyproject.toml +++ b/bindings/python/pyproject.toml @@ -59,10 +59,7 @@ paddlepaddle = [ "paddlepaddle>=2.4.1", ] quality = [ - "black==22.3", # after updating to black 2023, also update Python version in pyproject.toml to 3.7 - "click==8.0.4", - "isort>=5.5.4", - "flake8>=3.8.3", + "ruff", # after updating to black 2023, also update Python version in pyproject.toml to 3.7 ] testing = [ "safetensors[numpy]", @@ -74,6 +71,15 @@ testing = [ # "python-afl>=0.7.3", "hypothesis>=6.70.2", ] +testingfree = [ + "safetensors[numpy]", + "huggingface_hub>=0.12.1", + "setuptools_rust>=1.5.2", + "pytest>=7.2.0", + "pytest-benchmark>=4.0.0", + # "python-afl>=0.7.3", + "hypothesis>=6.70.2", +] all = [ "safetensors[torch]", "safetensors[numpy]", diff --git a/bindings/python/stub.py b/bindings/python/stub.py index 71fef2cc..a87f6bca 100644 --- a/bindings/python/stub.py +++ b/bindings/python/stub.py @@ -1,9 +1,8 @@ import argparse import inspect import os - -import black - +import subprocess +import tempfile INDENT = " " * 4 GENERATED_COMMENT = "# Generated content DO NOT EDIT\n" @@ -42,7 +41,10 @@ def fn_predicate(obj): return ( obj.__doc__ and obj.__text_signature__ - and (not obj.__name__.startswith("_") or obj.__name__ in {"__enter__", "__exit__"}) + and ( + not obj.__name__.startswith("_") + or obj.__name__ in {"__enter__", "__exit__"} + ) ) if inspect.isgetsetdescriptor(obj): return obj.__doc__ and not obj.__name__.startswith("_") @@ -78,7 +80,9 @@ def pyi_file(obj, indent=""): body = "" if obj.__doc__: - body += f'{indent}"""\n{indent}{do_indent(obj.__doc__, indent)}\n{indent}"""\n' + body += ( + f'{indent}"""\n{indent}{do_indent(obj.__doc__, indent)}\n{indent}"""\n' + ) fns = inspect.getmembers(obj, fn_predicate) @@ -86,7 +90,7 @@ def pyi_file(obj, indent=""): if obj.__text_signature__: signature = obj.__text_signature__.replace("(", "(self, ") body += f"{indent}def __init__{signature}:\n" - body += f"{indent+INDENT}pass\n" + body += f"{indent + INDENT}pass\n" body += "\n" for name, fn in fns: @@ -126,39 +130,41 @@ def py_file(module, origin): return string -def do_black(content, is_pyi): - mode = black.Mode( - target_versions={black.TargetVersion.PY35}, - line_length=119, - is_pyi=is_pyi, - string_normalization=True, - experimental_string_processing=False, - ) - try: - content = content.replace("$self", "self") - return black.format_file_contents(content, fast=True, mode=mode) - except black.NothingChanged: - return content +def do_black(content): + content = content.replace("$self", "self") + with tempfile.NamedTemporaryFile(mode="w+", suffix=".pyi") as f: + f.write(content) + f.flush() + _ = subprocess.check_output(["ruff", "format", f.name]) + f.seek(0) + new_content = f.read() + return new_content def write(module, directory, origin, check=False): - submodules = [(name, member) for name, member in inspect.getmembers(module) if inspect.ismodule(member)] + submodules = [ + (name, member) + for name, member in inspect.getmembers(module) + if inspect.ismodule(member) + ] filename = os.path.join(directory, "__init__.pyi") pyi_content = pyi_file(module) - pyi_content = do_black(pyi_content, is_pyi=True) + pyi_content = do_black(pyi_content) os.makedirs(directory, exist_ok=True) if check: with open(filename, "r") as f: data = f.read() - assert data == pyi_content, f"The content of {filename} seems outdated, please run `python stub.py`" + assert data == pyi_content, ( + f"The content of {filename} seems outdated, please run `python stub.py`" + ) else: with open(filename, "w") as f: f.write(pyi_content) filename = os.path.join(directory, "__init__.py") py_content = py_file(module, origin) - py_content = do_black(py_content, is_pyi=False) + py_content = do_black(py_content) os.makedirs(directory, exist_ok=True) is_auto = False @@ -174,7 +180,9 @@ def write(module, directory, origin, check=False): if check: with open(filename, "r") as f: data = f.read() - assert data == py_content, f"The content of {filename} seems outdated, please run `python stub.py`" + assert data == py_content, ( + f"The content of {filename} seems outdated, please run `python stub.py`" + ) else: with open(filename, "w") as f: f.write(py_content) diff --git a/bindings/python/tests/test_handle.py b/bindings/python/tests/test_handle.py index aaf0717b..2528ce55 100644 --- a/bindings/python/tests/test_handle.py +++ b/bindings/python/tests/test_handle.py @@ -23,7 +23,7 @@ def test_numpy_example(self): # Now loading loaded = {} with open("./out_np.safetensors", "r") as f: - with safe_open_handle(f, framework="np", device="cpu") as g: + with _safe_open_handle(f, framework="np", device="cpu") as g: for key in g.keys(): loaded[key] = g.get_tensor(key) self.assertTensorEqual(tensors, loaded, np.allclose) @@ -40,7 +40,7 @@ def test_fsspec(self): # Now loading loaded = {} with fs.open("fs.safetensors", "rb") as f: - with safe_open_handle(f, framework="np", device="cpu") as g: + with _safe_open_handle(f, framework="np", device="cpu") as g: for key in g.keys(): loaded[key] = g.get_tensor(key) self.assertTensorEqual(tensors, loaded, np.allclose) @@ -59,7 +59,7 @@ def test_fsspec_s3(self): # Now loading loaded = {} with s3.open("out/fs.safetensors", "rb") as f: - with safe_open_handle(f, framework="np", device="cpu") as g: + with _safe_open_handle(f, framework="np", device="cpu") as g: for key in g.keys(): loaded[key] = g.get_tensor(key) self.assertTensorEqual(tensors, loaded, np.allclose) diff --git a/bindings/python/tests/test_mlx_comparison.py b/bindings/python/tests/test_mlx_comparison.py index 1f21469a..6557cc9a 100644 --- a/bindings/python/tests/test_mlx_comparison.py +++ b/bindings/python/tests/test_mlx_comparison.py @@ -23,13 +23,13 @@ class LoadTestCase(unittest.TestCase): def setUp(self): data = { - "test": mx.randn((1024, 1024), dtype=mx.float32), - "test2": mx.randn((1024, 1024), dtype=mx.float32), - "test3": mx.randn((1024, 1024), dtype=mx.float32), + "test": mx.random.uniform(shape=(1024, 1024), dtype=mx.float32), + "test2": mx.random.uniform(shape=(1024, 1024), dtype=mx.float32), + "test3": mx.random.uniform(shape=(1024, 1024), dtype=mx.float32), # This doesn't work because bfloat16 is not implemented # with similar workarounds as jax/tensorflow. # https://github.com/ml-explore/mlx/issues/1296 - # "test4": mx.randn((1024, 1024), dtype=mx.bfloat16), + # "test4": mx.random.uniform(shape=(1024, 1024), dtype=mx.bfloat16), } self.mlx_filename = "./tests/data/mlx_load.npz" self.sf_filename = "./tests/data/mlx_load.safetensors" diff --git a/bindings/python/tests/test_pt_comparison.py b/bindings/python/tests/test_pt_comparison.py index 441fb351..64782204 100644 --- a/bindings/python/tests/test_pt_comparison.py +++ b/bindings/python/tests/test_pt_comparison.py @@ -95,7 +95,7 @@ def test_odd_dtype_fp8(self): self.assertEqual(reloaded["test2"].item(), -0.5) def test_odd_dtype_fp4(self): - if Version(torch.__version__) <= Version("2.7"): + if Version(torch.__version__) < Version("2.8"): return # torch.float4 requires 2.8 test1 = torch.tensor([0.0], dtype=torch.float8_e8m0fnu) diff --git a/bindings/python/tests/test_pt_model.py b/bindings/python/tests/test_pt_model.py index 7614c33b..4ad82ee7 100644 --- a/bindings/python/tests/test_pt_model.py +++ b/bindings/python/tests/test_pt_model.py @@ -100,7 +100,9 @@ def test_find_shared_non_shared_tensors(self): C = A[2:] D = A[:1] # Shared storage but *do* overlap - self.assertEqual(_find_shared_tensors({"B": B, "C": C, "D": D}), [{"B", "D"}, {"C"}]) + self.assertEqual( + _find_shared_tensors({"B": B, "C": C, "D": D}), [{"B", "D"}, {"C"}] + ) def test_end_ptr(self): A = torch.zeros((4,)) @@ -133,7 +135,9 @@ def test_remove_duplicate_names(self): B = A[:1, :] self.assertEqual(_remove_duplicate_names({"A": A, "B": B}), {"A": ["B"]}) - self.assertEqual(_remove_duplicate_names({"A": A, "B": B, "C": A}), {"A": ["B", "C"]}) + self.assertEqual( + _remove_duplicate_names({"A": A, "B": B, "C": A}), {"A": ["B", "C"]} + ) with self.assertRaises(RuntimeError): self.assertEqual(_remove_duplicate_names({"B": B}), []) @@ -216,7 +220,8 @@ def test_workaround_non_contiguous(self): def test_workaround_copy(self): model = CopyModel() self.assertEqual( - _find_shared_tensors(model.state_dict()), [{"a.weight"}, {"a.bias"}, {"b.weight"}, {"b.bias"}] + _find_shared_tensors(model.state_dict()), + [{"a.weight"}, {"a.bias"}, {"b.weight"}, {"b.bias"}], ) save_model(model, "tmp.safetensors") @@ -237,11 +242,13 @@ def test_difference_with_torch(self): # The model happily loads the tensors, and ends up *not* sharing the tensors by. # doing copies self.assertEqual( - _find_shared_tensors(model2.state_dict()), [{"a.weight"}, {"a.bias"}, {"b.weight"}, {"b.bias"}] + _find_shared_tensors(model2.state_dict()), + [{"a.weight"}, {"a.bias"}, {"b.weight"}, {"b.bias"}], ) model2.load_state_dict(torch.load("tmp2.bin")) self.assertEqual( - _find_shared_tensors(model2.state_dict()), [{"a.weight"}, {"a.bias"}, {"b.weight"}, {"b.bias"}] + _find_shared_tensors(model2.state_dict()), + [{"a.weight"}, {"a.bias"}, {"b.weight"}, {"b.bias"}], ) # However safetensors cannot save those, so we cannot @@ -249,7 +256,9 @@ def test_difference_with_torch(self): save_model(model, "tmp2.safetensors") with self.assertRaises(RuntimeError) as ctx: load_model(model2, "tmp2.safetensors") - self.assertIn("""Missing key(s) in state_dict: "b.bias", "b.weight""", str(ctx.exception)) + self.assertIn( + """Missing key(s) in state_dict: "b.bias", "b.weight""", str(ctx.exception) + ) def test_difference_torch_odd(self): model = NoSharedModel() @@ -259,14 +268,20 @@ def test_difference_torch_odd(self): torch.save(model.state_dict(), "tmp3.bin") model2 = Model() - self.assertEqual(_find_shared_tensors(model2.state_dict()), [{"a.weight", "b.weight"}, {"b.bias", "a.bias"}]) + self.assertEqual( + _find_shared_tensors(model2.state_dict()), + [{"a.weight", "b.weight"}, {"b.bias", "a.bias"}], + ) # Torch will affect either `b` or `a` to the shared tensor in the `model2` model2.load_state_dict(torch.load("tmp3.bin")) # XXX: model2 uses only the B weight not the A weight anymore. self.assertFalse(torch.allclose(model2.a.weight, model.a.weight)) torch.testing.assert_close(model2.a.weight, model.b.weight) - self.assertEqual(_find_shared_tensors(model2.state_dict()), [{"a.weight", "b.weight"}, {"b.bias", "a.bias"}]) + self.assertEqual( + _find_shared_tensors(model2.state_dict()), + [{"a.weight", "b.weight"}, {"b.bias", "a.bias"}], + ) # Everything is saved as-is save_model(model, "tmp3.safetensors") @@ -275,4 +290,7 @@ def test_difference_torch_odd(self): with self.assertRaises(RuntimeError) as ctx: load_model(model2, "tmp3.safetensors") # Safetensors properly warns the user that some ke - self.assertIn("""Unexpected key(s) in state_dict: "b.bias", "b.weight""", str(ctx.exception)) + self.assertIn( + """Unexpected key(s) in state_dict: "b.bias", "b.weight""", + str(ctx.exception), + ) diff --git a/bindings/python/tests/test_simple.py b/bindings/python/tests/test_simple.py index 1db8c711..f3e77d90 100644 --- a/bindings/python/tests/test_simple.py +++ b/bindings/python/tests/test_simple.py @@ -175,7 +175,7 @@ def test_file_not_found(self): with self.assertRaises(FileNotFoundError) as ctx: with safe_open("notafile", framework="pt"): pass - self.assertEqual(str(ctx.exception), 'No such file or directory: notafile') + self.assertEqual(str(ctx.exception), "No such file or directory: notafile") class ReadmeTestCase(unittest.TestCase): @@ -244,7 +244,9 @@ def test_torch_slice(self): save_file_pt(tensors, f"./slice_{ident}.safetensors") # Now loading - with safe_open(f"./slice_{ident}.safetensors", framework="pt", device="cpu") as f: + with safe_open( + f"./slice_{ident}.safetensors", framework="pt", device="cpu" + ) as f: slice_ = f.get_slice("a") tensor = slice_[:] self.assertEqual(list(tensor.shape), [10, 5]) @@ -335,7 +337,9 @@ def test_numpy_slice(self): with self.assertRaises(SafetensorError) as cm: tensor = slice_[2:, -6] - self.assertEqual(str(cm.exception), "Invalid index -6 for dimension 1 of size 5") + self.assertEqual( + str(cm.exception), "Invalid index -6 for dimension 1 of size 5" + ) with self.assertRaises(SafetensorError) as cm: tensor = slice_[[0, 1]] diff --git a/bindings/python/uv.lock b/bindings/python/uv.lock index ed80f7ea..7e375fcd 100644 --- a/bindings/python/uv.lock +++ b/bindings/python/uv.lock @@ -63,33 +63,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3", size = 63815 }, ] -[[package]] -name = "black" -version = "22.3.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "click" }, - { name = "mypy-extensions" }, - { name = "pathspec" }, - { name = "platformdirs" }, - { name = "tomli", marker = "python_full_version < '3.11'" }, - { name = "typing-extensions", marker = "python_full_version < '3.10'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/ee/1f/b29c7371958ab41a800f8718f5d285bf4333b8d0b5a5a8650234463ee644/black-22.3.0.tar.gz", hash = "sha256:35020b8886c022ced9282b51b5a875b6d1ab0c387b31a065b84db7c33085ca79", size = 554277 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e1/1b/3ba8128f0b6e86d87343a1275e17baeeeee1a89e02d2a0d275f472be3310/black-22.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:2497f9c2386572e28921fa8bec7be3e51de6801f7459dffd6e62492531c47e09", size = 2392131 }, - { url = "https://files.pythonhosted.org/packages/31/1a/0233cdbfbcfbc0864d815cf28ca40cdb65acf3601f3bf943d6d04e867858/black-22.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5795a0375eb87bfe902e80e0c8cfaedf8af4d49694d69161e5bd3206c18618bb", size = 1339315 }, - { url = "https://files.pythonhosted.org/packages/4f/98/8f775455f99a8e4b16d8d26efdc8292f99b1c0ebfe04357d800ff379c0ae/black-22.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e3556168e2e5c49629f7b0f377070240bd5511e45e25a4497bb0073d9dda776a", size = 1212888 }, - { url = "https://files.pythonhosted.org/packages/93/98/6f7c2f7f81d87b5771febcee933ba58640fca29a767262763bc353074f63/black-22.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67c8301ec94e3bcc8906740fe071391bce40a862b7be0b86fb5382beefecd968", size = 1474258 }, - { url = "https://files.pythonhosted.org/packages/5f/10/613ddfc646a1f51f24ad9173e4969025210fe9034a69718f08297ecb9b76/black-22.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:fd57160949179ec517d32ac2ac898b5f20d68ed1a9c977346efbac9c2f1e779d", size = 1137867 }, - { url = "https://files.pythonhosted.org/packages/a4/43/940f848d7d1ecf0be18453a293e5736e9ce60fd6197386a791bcc491f232/black-22.3.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5891ef8abc06576985de8fa88e95ab70641de6c1fca97e2a15820a9b69e51b20", size = 2390442 }, - { url = "https://files.pythonhosted.org/packages/e5/b7/e4e8907dffdac70f018ddb89681dbc77cbc7ac78d1f8a39259110a7e7943/black-22.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:30d78ba6bf080eeaf0b7b875d924b15cd46fec5fd044ddfbad38c8ea9171043a", size = 1338106 }, - { url = "https://files.pythonhosted.org/packages/56/74/c27c496223168af625d6bba8a14bc581e7742bf7248504a4b5743c374767/black-22.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ee8f1f7228cce7dffc2b464f07ce769f478968bfb3dd1254a4c2eeed84928aad", size = 1212264 }, - { url = "https://files.pythonhosted.org/packages/51/ec/c87695b087b7525fd9c7732c630455f231d3df9a300b730bd0e04ea00f84/black-22.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ee227b696ca60dd1c507be80a6bc849a5a6ab57ac7352aad1ffec9e8b805f21", size = 1473733 }, - { url = "https://files.pythonhosted.org/packages/5b/f9/e7aca76001a702dc258fb0443ca2553d5db13a3515c09062fbf344184363/black-22.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:9b542ced1ec0ceeff5b37d69838106a6348e60db7b8fdd245294dc1d26136265", size = 1137278 }, - { url = "https://files.pythonhosted.org/packages/2e/ef/a38a2189959246543e60859fb65bd3143129f6d18dfc7bcdd79217f81ca2/black-22.3.0-py3-none-any.whl", hash = "sha256:bc58025940a896d7e5356952228b68f793cf5fcb342be703c3a2669a1488cb72", size = 153859 }, -] - [[package]] name = "certifi" version = "2025.4.26" @@ -193,18 +166,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5e/6c/309972937d931069816dc8b28193a650485bc35cca92c04c8c15c4bd181e/chex-0.1.89-py3-none-any.whl", hash = "sha256:145241c27d8944adb634fb7d472a460e1c1b643f561507d4031ad5156ef82dfa", size = 99908 }, ] -[[package]] -name = "click" -version = "8.0.4" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/dd/cf/706c1ad49ab26abed0b77a2f867984c1341ed7387b8030a6aa914e2942a0/click-8.0.4.tar.gz", hash = "sha256:8458d7b1287c5fb128c90e23381cf99dcde74beaf6c7ff6384ce84d6fe090adb", size = 329520 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/4a/a8/0b2ced25639fb20cc1c9784de90a8c25f9504a7f18cd8b5397bd61696d7d/click-8.0.4-py3-none-any.whl", hash = "sha256:6a7a62563bbfabfda3a38f3023a1db4a35978c0abd76f6c9605ecd6554d6d9b1", size = 97486 }, -] - [[package]] name = "colorama" version = "0.4.6" @@ -289,20 +250,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4d/36/2a115987e2d8c300a974597416d9de88f2444426de9571f4b59b2cca3acc/filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de", size = 16215 }, ] -[[package]] -name = "flake8" -version = "7.2.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "mccabe" }, - { name = "pycodestyle" }, - { name = "pyflakes" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/e7/c4/5842fc9fc94584c455543540af62fd9900faade32511fab650e9891ec225/flake8-7.2.0.tar.gz", hash = "sha256:fa558ae3f6f7dbf2b4f22663e5343b6b6023620461f8d4ff2019ef4b5ee70426", size = 48177 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/83/5c/0627be4c9976d56b1217cb5187b7504e7fd7d3503f8bfd312a04077bd4f7/flake8-7.2.0-py2.py3-none-any.whl", hash = "sha256:93b92ba5bdb60754a6da14fa3b93a9361fd00a59632ada61fd7b130436c40343", size = 57786 }, -] - [[package]] name = "flatbuffers" version = "25.2.10" @@ -605,15 +552,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050 }, ] -[[package]] -name = "isort" -version = "6.0.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b8/21/1e2a441f74a653a144224d7d21afe8f4169e6c7c20bb13aec3a2dc3815e0/isort-6.0.1.tar.gz", hash = "sha256:1cb5df28dfbc742e490c5e41bad6da41b805b0a8be7bc93cd0fb2a8a890ac450", size = 821955 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c1/11/114d0a5f4dabbdcedc1125dee0888514c3c3b16d3e9facad87ed96fad97c/isort-6.0.1-py3-none-any.whl", hash = "sha256:2dc5d7f65c9678d94c88dfc29161a320eec67328bc97aad576874cb4be1e9615", size = 94186 }, -] - [[package]] name = "jax" version = "0.4.30" @@ -864,15 +802,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b3/73/085399401383ce949f727afec55ec3abd76648d04b9f22e1c0e99cb4bec3/MarkupSafe-3.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a", size = 15506 }, ] -[[package]] -name = "mccabe" -version = "0.7.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e7/ff/0ffefdcac38932a54d2b5eed4e0ba8a408f215002cd178ad1df0f2806ff8/mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325", size = 9658 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/27/1a/1f68f9ba0c207934b35b86a8ca3aad8395a3d6dd7921c0686e23853ff5a9/mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e", size = 7350 }, -] - [[package]] name = "mdurl" version = "0.1.2" @@ -911,24 +840,42 @@ wheels = [ [[package]] name = "mlx" -version = "0.25.1" +version = "0.27.1" source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mlx-metal", marker = "sys_platform == 'darwin'" }, +] wheels = [ - { url = "https://files.pythonhosted.org/packages/8b/42/6ce1ce83a8d7b600a69bde314b4c1b3e6aaeb6acd83d762124162dd8a751/mlx-0.25.1-cp310-cp310-macosx_13_0_arm64.whl", hash = "sha256:d13aa885d38a04d32f9818fffbceaa17555eb67fea02d16e53d2217ab4d8eb5d", size = 30723244 }, - { url = "https://files.pythonhosted.org/packages/fc/cd/bdbc33a51fa5ada9d593e8c4c491331ce57e5ab49e0d107f214e340c4417/mlx-0.25.1-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:d07082c35e4196fdc17813f344a529dbc6c7210edb35aaa5833cf3509fecf183", size = 30134290 }, - { url = "https://files.pythonhosted.org/packages/df/88/60f88cf4717ee497f0ba1f3ae77ace23cef486eaed1c85bbc65d81e2b687/mlx-0.25.1-cp310-cp310-macosx_15_0_arm64.whl", hash = "sha256:1fdafc0b247e22d324699245e2a339225265d3b6d12e669fe02402eb73f46216", size = 30134777 }, - { url = "https://files.pythonhosted.org/packages/0d/99/24b7c3622aab9eef8875fd96ae9183923ef8da00ecfe0997c9979c9a4f84/mlx-0.25.1-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:c647a242a7880ad89215a118df2f7d97b554fa54e55cc1b90ef7506e593a83eb", size = 30723278 }, - { url = "https://files.pythonhosted.org/packages/33/a0/9694271393ec8f135f4a3b1f16a9b475f3ea42e8fe4a18397b5680e6f162/mlx-0.25.1-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:d6da7ab9e51fd780083a3003c96cdd538b465d2b1a16e2fd77217348c70dfb44", size = 30134574 }, - { url = "https://files.pythonhosted.org/packages/60/7e/16c84be009c0c37862aa328915c2d188abd05756819668e87d138dabe353/mlx-0.25.1-cp311-cp311-macosx_15_0_arm64.whl", hash = "sha256:db0caac2c9dd6fe0ae15448b4dcb40cd3bd28d6ad9f935e2c383eb1844af77a2", size = 30135217 }, - { url = "https://files.pythonhosted.org/packages/8c/44/868009d072fca94fabf1cdb55a6c61d49ce72bc829a560d05ec94714cd0c/mlx-0.25.1-cp312-cp312-macosx_13_0_arm64.whl", hash = "sha256:8f6c0754570a94be4a1b25ce10986665ed0b57ee8ad8f50bc713b4801264eb98", size = 30717669 }, - { url = "https://files.pythonhosted.org/packages/64/8e/f84e1fada4f64d9a88974e3b208eedd5dfa94f06d542c86ff1a7a9d1197c/mlx-0.25.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:bc9a387819fc214dc915b2fff9164346bf9c3aa90aabcc38dbf1c232329861f7", size = 30135893 }, - { url = "https://files.pythonhosted.org/packages/b1/19/7174aeea051995d10d0b09383c6b2b88a1222e17d7a41151becf87dc3c46/mlx-0.25.1-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:cb6e5fb85535c3438bcb16e616e3aa2ec47844fcadf67d85ee862b256369f185", size = 30136426 }, - { url = "https://files.pythonhosted.org/packages/02/1b/7da8f1d224a4287cdd5eda77d878a73ff13c22e2c89097bc6effcc5c318a/mlx-0.25.1-cp313-cp313-macosx_13_0_arm64.whl", hash = "sha256:f2ca5c2f60804bbb3968ee3e087ce4cf5789065f4c927f76b025b3f5f122a63a", size = 30717676 }, - { url = "https://files.pythonhosted.org/packages/50/0f/1b4752c9325716ae7d1b8050442fe28372390cf2a4d993456535c4f50e16/mlx-0.25.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:59d233b12dc0c003d63883c73abbf40e29fe0a3176dd9d2095399c5f3688eb58", size = 30135902 }, - { url = "https://files.pythonhosted.org/packages/53/06/10f2465ea3b1fa2d7ca31e79b19869f8df0de4b8b57a932eab607aa36e3f/mlx-0.25.1-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:67d192dbd0677ea365f3305592ddb449488f3486f4791a7ac2e76494bea668a5", size = 30136384 }, - { url = "https://files.pythonhosted.org/packages/41/c8/3b872d4a32042973d1d24900215e1b299a8e648fd95de8b1c0144e423819/mlx-0.25.1-cp39-cp39-macosx_13_0_arm64.whl", hash = "sha256:324de0673922309fe0ab3a230fa66a7d0ce4f4b9b2e9d273f2816adddc99e285", size = 30723570 }, - { url = "https://files.pythonhosted.org/packages/b0/4e/da5e5cd2afe1e429c2893c7ed9bfb7ea9181f17e711b5515bca3e28a691b/mlx-0.25.1-cp39-cp39-macosx_14_0_arm64.whl", hash = "sha256:b7bb2e7e996c27a5e6ad19bbfc336bde71e0d4df23b5673a35087b321dd05b3b", size = 30134765 }, - { url = "https://files.pythonhosted.org/packages/b1/71/fc94cbe575b52ff1f0f95074b970271e93ff9a5d9e42864ea8f664c93e77/mlx-0.25.1-cp39-cp39-macosx_15_0_arm64.whl", hash = "sha256:138b0e7daf1f4014a184d8fc05df1f0a92a50fd99c9aeac8fef0b9bc31358cc1", size = 30135576 }, + { url = "https://files.pythonhosted.org/packages/c9/ed/07a7145c500914ed8ab704a7a3828a5134e85f8b4458e1fee887306867d6/mlx-0.27.1-cp310-cp310-macosx_13_0_arm64.whl", hash = "sha256:a033b65fe46425ad5032867d5a71a556a5168108d89aa7092b457556c70d84fc", size = 557679 }, + { url = "https://files.pythonhosted.org/packages/aa/ae/b3e46904ea04b5badb77195169880733f09976a3dfc81c954b99f9adbbc4/mlx-0.27.1-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:2836c6fd9803dc0c6cd06f204e31b3e0191e6c5b6bc8570b28661d926908cba3", size = 530556 }, + { url = "https://files.pythonhosted.org/packages/6e/24/85f5a7dfcf0b4974aa43a2f6dc0d59dfc04e4a1051aacebd7e7810b823ff/mlx-0.27.1-cp310-cp310-macosx_15_0_arm64.whl", hash = "sha256:8b0566054c46d84c470cc99cda2afc3914ad6c7808fbb724dc1ec235e5b2a98c", size = 530559 }, + { url = "https://files.pythonhosted.org/packages/14/bd/91ad900837a3760ba056863c1350f0deabc3e462c3999b4d5ea875368177/mlx-0.27.1-cp310-cp310-manylinux_2_35_x86_64.whl", hash = "sha256:91ef93ce09900c9a8ca662cf34e3c39ab5af2762822ecd6b12fecae518be167f", size = 628183 }, + { url = "https://files.pythonhosted.org/packages/ac/63/88cb9a5019bea21244385eacc4c64deb4d074a8bc3b4b6d2d97cdacf97a2/mlx-0.27.1-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:d2e5dedbfbcbe558e51a5c476ca6a18e307676f9e49854eb27e53778bc474699", size = 557582 }, + { url = "https://files.pythonhosted.org/packages/fa/87/c2d7343e7b054481c52e23a190911c40aed4f8c77a8dfeda1f48d5cb520a/mlx-0.27.1-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:9f04b9778897a879c9ca22e5413dfa1efc192d86d7211b184e079efec49dfb8b", size = 530820 }, + { url = "https://files.pythonhosted.org/packages/06/bf/20497ca7411028baa56372c20e94a3eaddac973155b415f08fc12592c2cf/mlx-0.27.1-cp311-cp311-macosx_15_0_arm64.whl", hash = "sha256:01d794f9e390438ab4f942a18d9a8ca65bef10c2c2007ef38ca988d039d6d9d3", size = 530821 }, + { url = "https://files.pythonhosted.org/packages/48/68/234a0d846576502ea1bf8ea478c764d87eec9042349e298d2aea58c4e8e9/mlx-0.27.1-cp311-cp311-manylinux_2_35_x86_64.whl", hash = "sha256:fae11432d0639789f1e172b19b35ac8987c8ab9716e55a23fc7a170d6545fc33", size = 628500 }, + { url = "https://files.pythonhosted.org/packages/65/43/125102bbb2be6825880ae2dc8d8702f99cfa7753407f574457b36e422218/mlx-0.27.1-cp312-cp312-macosx_13_0_arm64.whl", hash = "sha256:0c570c9afb57c697bd864504115be8a7c4de97f0b80557a597d496ee426a6812", size = 549869 }, + { url = "https://files.pythonhosted.org/packages/f3/79/0bf681700fc8b165517e907f9ec777b5a5d628004a65a777148f68c6baa0/mlx-0.27.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:ccff7bbbd9df302b26e79013ef6d0c3531c9ba5963ead521e2d85856811b86a0", size = 531671 }, + { url = "https://files.pythonhosted.org/packages/ec/97/f1367b4892bef7f78e38737d3a28094e93124f11684a28a9e92ed5a13b2b/mlx-0.27.1-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:9ccadaed449c07dfeae484620992b904c17dfea7564f8df63095c60eed3af02b", size = 531672 }, + { url = "https://files.pythonhosted.org/packages/9c/0f/3ebec0806ed2c5ba8ba151394cd62a46b4d83ea347da33af91b86d8969d4/mlx-0.27.1-cp312-cp312-manylinux_2_35_x86_64.whl", hash = "sha256:742c413e75605b71db69379a176da63e32ba19b9e9ad03b8763adbd1fcfcd394", size = 621661 }, + { url = "https://files.pythonhosted.org/packages/86/f6/4324386b0764deb692e14a97282a348a9a938aa8b441bf8b6c7599f418d4/mlx-0.27.1-cp313-cp313-macosx_13_0_arm64.whl", hash = "sha256:803669a28031766c2b0fe94c0a3bfd030184e706092f0a831b33620c1e2ef865", size = 549847 }, + { url = "https://files.pythonhosted.org/packages/cf/4b/3194ccb03527a050c04d837d731a11599f8620e6ce16d3971798caae1d44/mlx-0.27.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:e9649b3d86ce564000797384510c9d07af38a9ce2a07df8e2f7c6a3e0f0f059e", size = 531664 }, + { url = "https://files.pythonhosted.org/packages/cc/57/a6e0d8dc6e7ba08a64d71fb89d743e77446040113ea1dbb7950be8f60f39/mlx-0.27.1-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:5c501ceec7c6aa2ea1c850dd4e14e679f5416a142264b9d5d405a4e0aeb991b2", size = 531663 }, + { url = "https://files.pythonhosted.org/packages/48/96/6932e0fa866d08cdf77a3fc37cf624e4cac8960d2e297c3fd80afb49417d/mlx-0.27.1-cp313-cp313-manylinux_2_35_x86_64.whl", hash = "sha256:42bfbabdcd0b7aa1c94748c8963e66680a3cf3f599b01036db14e496bf276eb8", size = 621609 }, + { url = "https://files.pythonhosted.org/packages/b0/34/bb2d1a7bdd27384f282d97e5add37a1f7d22c8e355b4011682d22f5ecdc5/mlx-0.27.1-cp39-cp39-macosx_13_0_arm64.whl", hash = "sha256:18e9a12ce91c034d11a348f479e9cf6d13b7af64541fdcc4ef32a67903b19d3c", size = 557489 }, + { url = "https://files.pythonhosted.org/packages/3c/da/944d821aae2e5aa5440be824ab110db39b290c164bbbca2c8148f350b106/mlx-0.27.1-cp39-cp39-macosx_14_0_arm64.whl", hash = "sha256:fe94c860df8fb803e6330b46901c94cbe0f63b7e9e9ed94ca8920925ac671177", size = 530801 }, + { url = "https://files.pythonhosted.org/packages/6e/26/0e2e62c9798eb47fa981af469813c06259c73696813220b417b4039fbe95/mlx-0.27.1-cp39-cp39-macosx_15_0_arm64.whl", hash = "sha256:4384c06ce8d8eed23018e99331a612ff9837c7ae1ca953aef9dee056174465db", size = 530798 }, + { url = "https://files.pythonhosted.org/packages/86/13/a4864945059b8277f370661d2bab86146fc7e97ee29f0f17a1fdf9f5d239/mlx-0.27.1-cp39-cp39-manylinux_2_35_x86_64.whl", hash = "sha256:3ab919caa2b1f605d4dcea543dcbe7be43f3a4a5102232959d5659c9108b6fb4", size = 628882 }, +] + +[[package]] +name = "mlx-metal" +version = "0.27.1" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8b/77/89fa3327011f018638c9e943e1edc081ce9ca0ed296fe64d6daf93c6ff51/mlx_metal-0.27.1-py3-none-macosx_13_0_arm64.whl", hash = "sha256:c66d9b1adb3c0ea19492fba6493f672bc7542e65dd65f7e2995918815fbeb907", size = 33523035 }, + { url = "https://files.pythonhosted.org/packages/d7/a8/ac706ad6ce834834762d5146d791f77710efc896c13ef47fd7d672099056/mlx_metal-0.27.1-py3-none-macosx_14_0_arm64.whl", hash = "sha256:fe4415ddd242974d91c7ca0699cd01507d17da8a5ba304122ef137cdb5e7fff4", size = 32926383 }, + { url = "https://files.pythonhosted.org/packages/78/77/6963681fb54ecaa0ae5de4209c15504a803a0edd1a33fd074e6c558fd5e0/mlx_metal-0.27.1-py3-none-macosx_15_0_arm64.whl", hash = "sha256:d025dea30bda8baa32c928cfa333eac64a5adc8d07656f8fc55072d99403ebc9", size = 32897065 }, ] [[package]] @@ -1003,15 +950,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5f/e8/2162621e18dbc36e2bc8492fd0e97b3975f5d89fe0472ae6d5f7fbdd8cf7/msgpack-1.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:4d1b7ff2d6146e16e8bd665ac726a89c74163ef8cd39fa8c1087d4e52d3a2325", size = 74787 }, ] -[[package]] -name = "mypy-extensions" -version = "1.1.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963 }, -] - [[package]] name = "namex" version = "0.0.9" @@ -1463,15 +1401,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ad/ee/eef6cfb98a44e11891bda8e898a9620df1303664f45e64285edc6ac93536/paddlepaddle-3.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:4b078cee4f6da995e4d2b1c46d1d94545f31a487b02ec1c61cfbb9e7d6d082f2", size = 96937322 }, ] -[[package]] -name = "pathspec" -version = "0.12.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191 }, -] - [[package]] name = "pillow" version = "11.2.1" @@ -1560,15 +1489,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/21/2c/5e05f58658cf49b6667762cca03d6e7d85cededde2caf2ab37b81f80e574/pillow-11.2.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:208653868d5c9ecc2b327f9b9ef34e0e42a4cdd172c2988fd81d62d2bc9bc044", size = 2674751 }, ] -[[package]] -name = "platformdirs" -version = "4.3.7" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b6/2d/7d512a3913d60623e7eb945c6d1b4f0bddf1d0b7ada5225274c87e5b53d1/platformdirs-4.3.7.tar.gz", hash = "sha256:eb437d586b6a0986388f0d6f74aa0cde27b48d0e3d66843640bfb6bdcdb6e351", size = 21291 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/6d/45/59578566b3275b8fd9157885918fcd0c4d74162928a5310926887b856a51/platformdirs-4.3.7-py3-none-any.whl", hash = "sha256:a03875334331946f13c549dbd8f4bac7a13a50a895a0eb1e8c6a8ace80d40a94", size = 18499 }, -] - [[package]] name = "pluggy" version = "1.5.0" @@ -1603,24 +1523,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl", hash = "sha256:859625bc251f64e21f077d099d4162689c762b5d6a4c3c97553d56241c9674d5", size = 22335 }, ] -[[package]] -name = "pycodestyle" -version = "2.13.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/04/6e/1f4a62078e4d95d82367f24e685aef3a672abfd27d1a868068fed4ed2254/pycodestyle-2.13.0.tar.gz", hash = "sha256:c8415bf09abe81d9c7f872502a6eee881fbe85d8763dd5b9924bb0a01d67efae", size = 39312 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/07/be/b00116df1bfb3e0bb5b45e29d604799f7b91dd861637e4d448b4e09e6a3e/pycodestyle-2.13.0-py2.py3-none-any.whl", hash = "sha256:35863c5974a271c7a726ed228a14a4f6daf49df369d8c50cd9a6f58a5e143ba9", size = 31424 }, -] - -[[package]] -name = "pyflakes" -version = "3.3.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/af/cc/1df338bd7ed1fa7c317081dcf29bf2f01266603b301e6858856d346a12b3/pyflakes-3.3.2.tar.gz", hash = "sha256:6dfd61d87b97fba5dcfaaf781171ac16be16453be6d816147989e7f6e6a9576b", size = 64175 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/15/40/b293a4fa769f3b02ab9e387c707c4cbdc34f073f945de0386107d4e669e6/pyflakes-3.3.2-py2.py3-none-any.whl", hash = "sha256:5039c8339cbb1944045f4ee5466908906180f13cc99cc9949348d10f82a5c32a", size = 63164 }, -] - [[package]] name = "pygments" version = "2.19.1" @@ -1742,21 +1644,42 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0d/9b/63f4c7ebc259242c89b3acafdb37b41d1185c07ff0011164674e9076b491/rich-14.0.0-py3-none-any.whl", hash = "sha256:1c9491e1951aac09caffd42f448ee3d04e58923ffe14993f6e83068dc395d7e0", size = 243229 }, ] +[[package]] +name = "ruff" +version = "0.12.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a1/81/0bd3594fa0f690466e41bd033bdcdf86cba8288345ac77ad4afbe5ec743a/ruff-0.12.7.tar.gz", hash = "sha256:1fc3193f238bc2d7968772c82831a4ff69252f673be371fb49663f0068b7ec71", size = 5197814 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e1/d2/6cb35e9c85e7a91e8d22ab32ae07ac39cc34a71f1009a6f9e4a2a019e602/ruff-0.12.7-py3-none-linux_armv6l.whl", hash = "sha256:76e4f31529899b8c434c3c1dede98c4483b89590e15fb49f2d46183801565303", size = 11852189 }, + { url = "https://files.pythonhosted.org/packages/63/5b/a4136b9921aa84638f1a6be7fb086f8cad0fde538ba76bda3682f2599a2f/ruff-0.12.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:789b7a03e72507c54fb3ba6209e4bb36517b90f1a3569ea17084e3fd295500fb", size = 12519389 }, + { url = "https://files.pythonhosted.org/packages/a8/c9/3e24a8472484269b6b1821794141f879c54645a111ded4b6f58f9ab0705f/ruff-0.12.7-py3-none-macosx_11_0_arm64.whl", hash = "sha256:2e1c2a3b8626339bb6369116e7030a4cf194ea48f49b64bb505732a7fce4f4e3", size = 11743384 }, + { url = "https://files.pythonhosted.org/packages/26/7c/458dd25deeb3452c43eaee853c0b17a1e84169f8021a26d500ead77964fd/ruff-0.12.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32dec41817623d388e645612ec70d5757a6d9c035f3744a52c7b195a57e03860", size = 11943759 }, + { url = "https://files.pythonhosted.org/packages/7f/8b/658798472ef260ca050e400ab96ef7e85c366c39cf3dfbef4d0a46a528b6/ruff-0.12.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:47ef751f722053a5df5fa48d412dbb54d41ab9b17875c6840a58ec63ff0c247c", size = 11654028 }, + { url = "https://files.pythonhosted.org/packages/a8/86/9c2336f13b2a3326d06d39178fd3448dcc7025f82514d1b15816fe42bfe8/ruff-0.12.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a828a5fc25a3efd3e1ff7b241fd392686c9386f20e5ac90aa9234a5faa12c423", size = 13225209 }, + { url = "https://files.pythonhosted.org/packages/76/69/df73f65f53d6c463b19b6b312fd2391dc36425d926ec237a7ed028a90fc1/ruff-0.12.7-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:5726f59b171111fa6a69d82aef48f00b56598b03a22f0f4170664ff4d8298efb", size = 14182353 }, + { url = "https://files.pythonhosted.org/packages/58/1e/de6cda406d99fea84b66811c189b5ea139814b98125b052424b55d28a41c/ruff-0.12.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:74e6f5c04c4dd4aba223f4fe6e7104f79e0eebf7d307e4f9b18c18362124bccd", size = 13631555 }, + { url = "https://files.pythonhosted.org/packages/6f/ae/625d46d5164a6cc9261945a5e89df24457dc8262539ace3ac36c40f0b51e/ruff-0.12.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d0bfe4e77fba61bf2ccadf8cf005d6133e3ce08793bbe870dd1c734f2699a3e", size = 12667556 }, + { url = "https://files.pythonhosted.org/packages/55/bf/9cb1ea5e3066779e42ade8d0cd3d3b0582a5720a814ae1586f85014656b6/ruff-0.12.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06bfb01e1623bf7f59ea749a841da56f8f653d641bfd046edee32ede7ff6c606", size = 12939784 }, + { url = "https://files.pythonhosted.org/packages/55/7f/7ead2663be5627c04be83754c4f3096603bf5e99ed856c7cd29618c691bd/ruff-0.12.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e41df94a957d50083fd09b916d6e89e497246698c3f3d5c681c8b3e7b9bb4ac8", size = 11771356 }, + { url = "https://files.pythonhosted.org/packages/17/40/a95352ea16edf78cd3a938085dccc55df692a4d8ba1b3af7accbe2c806b0/ruff-0.12.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:4000623300563c709458d0ce170c3d0d788c23a058912f28bbadc6f905d67afa", size = 11612124 }, + { url = "https://files.pythonhosted.org/packages/4d/74/633b04871c669e23b8917877e812376827c06df866e1677f15abfadc95cb/ruff-0.12.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:69ffe0e5f9b2cf2b8e289a3f8945b402a1b19eff24ec389f45f23c42a3dd6fb5", size = 12479945 }, + { url = "https://files.pythonhosted.org/packages/be/34/c3ef2d7799c9778b835a76189c6f53c179d3bdebc8c65288c29032e03613/ruff-0.12.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:a07a5c8ffa2611a52732bdc67bf88e243abd84fe2d7f6daef3826b59abbfeda4", size = 12998677 }, + { url = "https://files.pythonhosted.org/packages/77/ab/aca2e756ad7b09b3d662a41773f3edcbd262872a4fc81f920dc1ffa44541/ruff-0.12.7-py3-none-win32.whl", hash = "sha256:c928f1b2ec59fb77dfdf70e0419408898b63998789cc98197e15f560b9e77f77", size = 11756687 }, + { url = "https://files.pythonhosted.org/packages/b4/71/26d45a5042bc71db22ddd8252ca9d01e9ca454f230e2996bb04f16d72799/ruff-0.12.7-py3-none-win_amd64.whl", hash = "sha256:9c18f3d707ee9edf89da76131956aba1270c6348bfee8f6c647de841eac7194f", size = 12912365 }, + { url = "https://files.pythonhosted.org/packages/4c/9b/0b8aa09817b63e78d94b4977f18b1fcaead3165a5ee49251c5d5c245bb2d/ruff-0.12.7-py3-none-win_arm64.whl", hash = "sha256:dfce05101dbd11833a0776716d5d1578641b7fddb537fe7fa956ab85d1769b69", size = 11982083 }, +] + [[package]] name = "safetensors" source = { editable = "." } [package.optional-dependencies] all = [ - { name = "black" }, - { name = "click" }, - { name = "flake8" }, { name = "flax", version = "0.8.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "flax", version = "0.10.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "h5py" }, { name = "huggingface-hub" }, { name = "hypothesis" }, - { name = "isort" }, { name = "jax", version = "0.4.30", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "jax", version = "0.5.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "jaxlib", version = "0.4.30", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, @@ -1765,20 +1688,17 @@ all = [ { name = "paddlepaddle" }, { name = "pytest" }, { name = "pytest-benchmark" }, + { name = "ruff" }, { name = "setuptools-rust" }, { name = "tensorflow" }, { name = "torch" }, ] dev = [ - { name = "black" }, - { name = "click" }, - { name = "flake8" }, { name = "flax", version = "0.8.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "flax", version = "0.10.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "h5py" }, { name = "huggingface-hub" }, { name = "hypothesis" }, - { name = "isort" }, { name = "jax", version = "0.4.30", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "jax", version = "0.5.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "jaxlib", version = "0.4.30", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, @@ -1787,6 +1707,7 @@ dev = [ { name = "paddlepaddle" }, { name = "pytest" }, { name = "pytest-benchmark" }, + { name = "ruff" }, { name = "setuptools-rust" }, { name = "tensorflow" }, { name = "torch" }, @@ -1815,10 +1736,7 @@ pinned-tf = [ { name = "tensorflow" }, ] quality = [ - { name = "black" }, - { name = "click" }, - { name = "flake8" }, - { name = "isort" }, + { name = "ruff" }, ] tensorflow = [ { name = "numpy" }, @@ -1833,6 +1751,14 @@ testing = [ { name = "pytest-benchmark" }, { name = "setuptools-rust" }, ] +testingfree = [ + { name = "huggingface-hub" }, + { name = "hypothesis" }, + { name = "numpy" }, + { name = "pytest" }, + { name = "pytest-benchmark" }, + { name = "setuptools-rust" }, +] torch = [ { name = "numpy" }, { name = "torch" }, @@ -1840,21 +1766,22 @@ torch = [ [package.metadata] requires-dist = [ - { name = "black", marker = "extra == 'quality'", specifier = "==22.3" }, - { name = "click", marker = "extra == 'quality'", specifier = "==8.0.4" }, - { name = "flake8", marker = "extra == 'quality'", specifier = ">=3.8.3" }, { name = "flax", marker = "extra == 'jax'", specifier = ">=0.6.3" }, { name = "h5py", marker = "extra == 'testing'", specifier = ">=3.7.0" }, { name = "huggingface-hub", marker = "extra == 'testing'", specifier = ">=0.12.1" }, + { name = "huggingface-hub", marker = "extra == 'testingfree'", specifier = ">=0.12.1" }, { name = "hypothesis", marker = "extra == 'testing'", specifier = ">=6.70.2" }, - { name = "isort", marker = "extra == 'quality'", specifier = ">=5.5.4" }, + { name = "hypothesis", marker = "extra == 'testingfree'", specifier = ">=6.70.2" }, { name = "jax", marker = "extra == 'jax'", specifier = ">=0.3.25" }, { name = "jaxlib", marker = "extra == 'jax'", specifier = ">=0.3.25" }, { name = "mlx", marker = "extra == 'mlx'", specifier = ">=0.0.9" }, { name = "numpy", marker = "extra == 'numpy'", specifier = ">=1.21.6" }, { name = "paddlepaddle", marker = "extra == 'paddlepaddle'", specifier = ">=2.4.1" }, { name = "pytest", marker = "extra == 'testing'", specifier = ">=7.2.0" }, + { name = "pytest", marker = "extra == 'testingfree'", specifier = ">=7.2.0" }, { name = "pytest-benchmark", marker = "extra == 'testing'", specifier = ">=4.0.0" }, + { name = "pytest-benchmark", marker = "extra == 'testingfree'", specifier = ">=4.0.0" }, + { name = "ruff", marker = "extra == 'quality'" }, { name = "safetensors", extras = ["all"], marker = "extra == 'dev'" }, { name = "safetensors", extras = ["jax"], marker = "extra == 'all'" }, { name = "safetensors", extras = ["numpy"], marker = "extra == 'all'" }, @@ -1863,6 +1790,7 @@ requires-dist = [ { name = "safetensors", extras = ["numpy"], marker = "extra == 'pinned-tf'" }, { name = "safetensors", extras = ["numpy"], marker = "extra == 'tensorflow'" }, { name = "safetensors", extras = ["numpy"], marker = "extra == 'testing'" }, + { name = "safetensors", extras = ["numpy"], marker = "extra == 'testingfree'" }, { name = "safetensors", extras = ["numpy"], marker = "extra == 'torch'" }, { name = "safetensors", extras = ["paddlepaddle"], marker = "extra == 'all'" }, { name = "safetensors", extras = ["pinned-tf"], marker = "extra == 'all'" }, @@ -1870,11 +1798,12 @@ requires-dist = [ { name = "safetensors", extras = ["testing"], marker = "extra == 'all'" }, { name = "safetensors", extras = ["torch"], marker = "extra == 'all'" }, { name = "setuptools-rust", marker = "extra == 'testing'", specifier = ">=1.5.2" }, + { name = "setuptools-rust", marker = "extra == 'testingfree'", specifier = ">=1.5.2" }, { name = "tensorflow", marker = "extra == 'pinned-tf'", specifier = "==2.18.0" }, { name = "tensorflow", marker = "extra == 'tensorflow'", specifier = ">=2.11.0" }, { name = "torch", marker = "extra == 'torch'", specifier = ">=1.10" }, ] -provides-extras = ["numpy", "torch", "tensorflow", "pinned-tf", "jax", "mlx", "paddlepaddle", "quality", "testing", "all", "dev"] +provides-extras = ["numpy", "torch", "tensorflow", "pinned-tf", "jax", "mlx", "paddlepaddle", "quality", "testing", "testingfree", "all", "dev"] [[package]] name = "scipy" From 94f5d38794fdedde2cf0e756914b8250533a6c1a Mon Sep 17 00:00:00 2001 From: Nicolas Patry Date: Wed, 6 Aug 2025 11:11:45 +0200 Subject: [PATCH 34/37] Preparing for patch 6.0.1. (#638) * Preparing for patch 6.0.1. * Tune down false positives. --- .github/workflows/trufflehog.yml | 4 ++++ bindings/python/Cargo.toml | 2 +- safetensors/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/trufflehog.yml b/.github/workflows/trufflehog.yml index 9cbbf680..8a15d8c9 100644 --- a/.github/workflows/trufflehog.yml +++ b/.github/workflows/trufflehog.yml @@ -13,3 +13,7 @@ jobs: fetch-depth: 0 - name: Secret Scanning uses: trufflesecurity/trufflehog@main + with: + extra_args: --results=verified,unknown + + diff --git a/bindings/python/Cargo.toml b/bindings/python/Cargo.toml index 646312bf..1eb786b3 100644 --- a/bindings/python/Cargo.toml +++ b/bindings/python/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "safetensors-python" -version = "0.6.0-dev.0" +version = "0.6.2-dev.0" edition = "2021" rust-version = "1.74" diff --git a/safetensors/Cargo.toml b/safetensors/Cargo.toml index 68ebac64..839d06e2 100644 --- a/safetensors/Cargo.toml +++ b/safetensors/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "safetensors" -version = "0.6.0-dev.0" +version = "0.6.2-dev.0" edition = "2021" rust-version = "1.80" homepage = "https://github.com/huggingface/safetensors" From 5eecd2917c5efe77c2c3b065ad07afcbcd057cba Mon Sep 17 00:00:00 2001 From: Nicolas Patry Date: Fri, 8 Aug 2025 14:23:12 +0200 Subject: [PATCH 35/37] Fixing clippy in 1.89 (#644) --- bindings/python/src/lib.rs | 2 +- safetensors/src/tensor.rs | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/bindings/python/src/lib.rs b/bindings/python/src/lib.rs index 36f784b4..c039d6e4 100644 --- a/bindings/python/src/lib.rs +++ b/bindings/python/src/lib.rs @@ -33,7 +33,7 @@ struct PyView<'a> { } impl View for &PyView<'_> { - fn data(&self) -> std::borrow::Cow<[u8]> { + fn data(&self) -> std::borrow::Cow<'_, [u8]> { Cow::Borrowed(self.data.as_bytes()) } fn shape(&self) -> &[usize] { diff --git a/safetensors/src/tensor.rs b/safetensors/src/tensor.rs index 0a4edf3d..c9ee2143 100644 --- a/safetensors/src/tensor.rs +++ b/safetensors/src/tensor.rs @@ -142,7 +142,7 @@ struct PreparedData { /// fn shape(&self) -> &[usize]{ /// &self.shape /// } -/// fn data(&self) -> Cow<[u8]>{ +/// fn data(&self) -> Cow<'_, [u8]>{ /// (&self.data).into() /// } /// fn data_len(&self) -> usize{ @@ -166,7 +166,7 @@ struct PreparedData { /// fn shape(&self) -> &[usize]{ /// &self.shape /// } -/// fn data(&self) -> Cow<[u8]>{ +/// fn data(&self) -> Cow<'_, [u8]>{ /// self.data.into() /// } /// fn data_len(&self) -> usize{ @@ -193,7 +193,7 @@ struct PreparedData { /// fn shape(&self) -> &[usize]{ /// &self.shape /// } -/// fn data(&self) -> Cow<[u8]>{ +/// fn data(&self) -> Cow<'_, [u8]>{ /// // This copies data from GPU to CPU. /// let data: Vec = self.data.to_vec(); /// data.into() @@ -211,7 +211,7 @@ pub trait View { /// The shape of the tensor fn shape(&self) -> &[usize]; /// The data of the tensor - fn data(&self) -> Cow<[u8]>; + fn data(&self) -> Cow<'_, [u8]>; /// The length of the data, in bytes. /// This is necessary as this might be faster to get than `data().len()` /// for instance for tensors residing in GPU. @@ -678,7 +678,7 @@ impl View for &TensorView<'_> { &self.shape } - fn data(&self) -> Cow<[u8]> { + fn data(&self) -> Cow<'_, [u8]> { self.data.into() } @@ -696,7 +696,7 @@ impl View for TensorView<'_> { &self.shape } - fn data(&self) -> Cow<[u8]> { + fn data(&self) -> Cow<'_, [u8]> { self.data.into() } From 2b253406f8896a5589083f68d05e5fbda30778a6 Mon Sep 17 00:00:00 2001 From: Nicolas Patry Date: Fri, 8 Aug 2025 14:33:40 +0200 Subject: [PATCH 36/37] Fixing the version check for uint support in torch. (#643) --- .pre-commit-config.yaml | 13 +++++++------ bindings/python/py_src/safetensors/torch.py | 4 ++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 27dc28c0..dd716eed 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -31,13 +31,14 @@ repos: "--", "-Dwarnings", ] - - repo: https://github.com/psf/black - rev: 22.3.0 + - repo: https://github.com/astral-sh/ruff-pre-commit + # Ruff version. + rev: v0.12.8 hooks: - - id: black - name: "Python (black)" - args: ["--line-length", "119", "--target-version", "py35"] - types: ["python"] + # Run the linter. + - id: ruff-check + # Run the formatter. + - id: ruff-format - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. rev: v0.11.11 diff --git a/bindings/python/py_src/safetensors/torch.py b/bindings/python/py_src/safetensors/torch.py index 49405bf3..f2285e0f 100644 --- a/bindings/python/py_src/safetensors/torch.py +++ b/bindings/python/py_src/safetensors/torch.py @@ -433,7 +433,7 @@ def load(data: bytes) -> Dict[str, torch.Tensor]: _float8_e8m0: 1, _float4_e2m1_x2: 1, } -if Version(torch.__version__) > Version("2.0.0"): +if Version(torch.__version__) >= Version("2.3.0"): _SIZE.update( { torch.uint64: 8, @@ -456,7 +456,7 @@ def load(data: bytes) -> Dict[str, torch.Tensor]: "F8_E4M3": _float8_e4m3fn, "F8_E5M2": _float8_e5m2, } -if Version(torch.__version__) > Version("2.0.0"): +if Version(torch.__version__) >= Version("2.3.0"): _TYPES.update( { "U64": torch.uint64, From aa6c43d729868fc43918e862d42bfeaf60485d1d Mon Sep 17 00:00:00 2001 From: Nicolas Patry Date: Fri, 8 Aug 2025 15:09:52 +0200 Subject: [PATCH 37/37] Patch release 0.6.2 --- bindings/python/Cargo.lock | 234 +++++++++++++++++++++++++++++++++++++ bindings/python/Cargo.toml | 2 +- safetensors/Cargo.toml | 2 +- 3 files changed, 236 insertions(+), 2 deletions(-) create mode 100644 bindings/python/Cargo.lock diff --git a/bindings/python/Cargo.lock b/bindings/python/Cargo.lock new file mode 100644 index 00000000..c2d1b3aa --- /dev/null +++ b/bindings/python/Cargo.lock @@ -0,0 +1,234 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "indoc" +version = "2.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd" + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "libc" +version = "0.2.174" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" + +[[package]] +name = "memchr" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" + +[[package]] +name = "memmap2" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "portable-atomic" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" + +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "pyo3" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8970a78afe0628a3e3430376fc5fd76b6b45c4d43360ffd6cdd40bdde72b682a" +dependencies = [ + "indoc", + "libc", + "memoffset", + "once_cell", + "portable-atomic", + "pyo3-build-config", + "pyo3-ffi", + "pyo3-macros", + "unindent", +] + +[[package]] +name = "pyo3-build-config" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "458eb0c55e7ece017adeba38f2248ff3ac615e53660d7c71a238d7d2a01c7598" +dependencies = [ + "once_cell", + "target-lexicon", +] + +[[package]] +name = "pyo3-ffi" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7114fe5457c61b276ab77c5055f206295b812608083644a5c5b2640c3102565c" +dependencies = [ + "libc", + "pyo3-build-config", +] + +[[package]] +name = "pyo3-macros" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8725c0a622b374d6cb051d11a0983786448f7785336139c3c94f5aa6bef7e50" +dependencies = [ + "proc-macro2", + "pyo3-macros-backend", + "quote", + "syn", +] + +[[package]] +name = "pyo3-macros-backend" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4109984c22491085343c05b0dbc54ddc405c3cf7b4374fc533f5c3313a572ccc" +dependencies = [ + "heck", + "proc-macro2", + "pyo3-build-config", + "quote", + "syn", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "safetensors" +version = "0.6.2" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "safetensors-python" +version = "0.6.2" +dependencies = [ + "memmap2", + "pyo3", + "safetensors", + "serde_json", +] + +[[package]] +name = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.140" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "syn" +version = "2.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "target-lexicon" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e502f78cdbb8ba4718f566c418c52bc729126ffd16baee5baa718cf25dd5a69a" + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "unindent" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3" diff --git a/bindings/python/Cargo.toml b/bindings/python/Cargo.toml index 1eb786b3..e1e21564 100644 --- a/bindings/python/Cargo.toml +++ b/bindings/python/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "safetensors-python" -version = "0.6.2-dev.0" +version = "0.6.2" edition = "2021" rust-version = "1.74" diff --git a/safetensors/Cargo.toml b/safetensors/Cargo.toml index 839d06e2..de83c0ef 100644 --- a/safetensors/Cargo.toml +++ b/safetensors/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "safetensors" -version = "0.6.2-dev.0" +version = "0.6.2" edition = "2021" rust-version = "1.80" homepage = "https://github.com/huggingface/safetensors"