diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml index 8ff4b058..80ab2a27 100644 --- a/.github/workflows/python-ci.yml +++ b/.github/workflows/python-ci.yml @@ -65,15 +65,16 @@ jobs: - name: Install dependencies and run tests run: pixi run -e dev test - - name: Upload coverage - uses: codecov/codecov-action@v4.0.1 + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v5 with: - token: ${{ secrets.CODECOV_TOKEN_NEW }} - name: Pytest coverage - env_vars: OS,PYTHON,GITHUB_ACTIONS,GITHUB_ACTION,GITHUB_REF,GITHUB_REPOSITORY,GITHUB_HEAD_REF,GITHUB_RUN_ID,GITHUB_SHA,COVERAGE_FILE - env: - OS: ${{ matrix.os }} - PYTHON: ${{ matrix.python-version }} + name: unit-tests-job + flags: unittests + files: ./coverage-unit.xml + fail_ci_if_error: true + verbose: true + token: ${{ secrets.CODECOV_TOKEN }} + slug: EasyScience/corelib Package_Testing: diff --git a/pixi.lock b/pixi.lock index 60fe0002..a1627563 100644 --- a/pixi.lock +++ b/pixi.lock @@ -11,25 +11,27 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.10.5-hbd8a1cb_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.44-ha97dd6f_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.44-h1aa0949_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.1-hecca717_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.6-h2dba641_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h9ec8514_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-h767d61c_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-h767d61c_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.1-hb9d3cd8_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.50.4-h0c1763c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h8f9b012_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.2-he9a06e4_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.5.4-h26f9b46_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.13.9-h2b335a9_100_cp313.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.13.9-hc97d973_101_cp313.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8c095d6_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_hd72426e_102.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb8e6e7a_2.conda - pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/cc/e6/33d305e6cce0a8daeb79c7d8d6547d6e5f27f4e35fa4883fc9c9eb638596/aiohttp-3.13.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/f7/0d/4764669bdf47bd472899b3d3db91fffbe925c8e3038ec591a2fd2ad6a14d/aiohttp-3.13.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/ac/19dbba27e891f39feb4170b884da449ee2699ef4ebb88eefeda364bbbbcf/asteval-1.0.6-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl @@ -37,7 +39,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/cb/8c/2b30c12155ad8de0cf641d76a8b396a16d2c36bc6d50b621a62b7c4567c1/build-1.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/43/8e/278ea79cf8ee0c395a5ad74625b3465c2fc234bb277f171dd59dd203820d/bumps-1.0.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/7e/e8/64c37fadfc2816a7701fa8a6ed8d87327c7d54eacfbfb6edab14a2f2be75/cloudpickle-3.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/4b/32/e0f13a1c5b0f8572d0ec6ae2f6c677b7991fafd95da523159c19eff0696a/contourpy-1.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/68/49/869b49db0bad6fba7c7471d612c356e745929d14e0de63acbc53e88f2a50/dfo_ls-1.6-py3-none-any.whl @@ -57,7 +59,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/f5/b7/339b9ed180c28418f3c5c425f341759ce3722b61cc54f8c20918a034a1d5/mpld3-0.5.11-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5d/ba/459f18c16f2b3fc1a1ca871f72f07d70c07bf768ad0a507a698b8052ac58/msgpack-1.1.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/c6/2d/f0b184fa88d6630aa267680bdb8623fb69cb0d024b8c6f0d23f9a0f406d3/multidict-6.7.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/13/34/00c7ae8194074ed82b64e0bb7c24220eac5f77ac90c16e23cf0d2cfd2a03/narwhals-2.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/62/cd/9481a199a086ac9f91eaa232b56cff90ca7fdc2cb6658de93825b1007094/narwhals-2.10.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9e/7e/7d306ff7cb143e6d975cfa7eb98a93e73495c4deabb7d1b5ecf09ea0fd69/numpy-2.3.4-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/15/07/284f757f63f8a8d69ed4472bfd85122bd086e637bf4ed09de572d575a693/pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl @@ -70,10 +72,10 @@ environments: - pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d8/f0/c5aa0a69fd9326f013110653543f36ece4913c17921f3e1dbd78e1b423ee/python_engineio-4.12.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/d7/5b/821733876bad200638237d1cab671b46cfdafb73c0b4094f59c5947155ae/python_socketio-5.14.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c0/1a/b393a06aa6f2f6ab4a9c5c160a62d488b17d6da5cf93a67bc13a6e3239cd/python_socketio-5.14.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c3/cf/4c3853de982ba47f94493c90fb4bf0a2164ca5b48a769b4facd6c28c9f6b/scipp-25.8.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/da/6a/1a927b14ddc7714111ea51f4e568203b2bb6ed59bdd036d62127c1a360c8/scipy-1.16.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/77/34/1956aed61c4abb91926f9513330afac4654cc2a711ecb73085dc4e2e5c1d/scipp-25.11.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/21/f6/4bfb5695d8941e5c570a04d9fcd0d36bce7511b7d78e6e75c8f9791f82d0/scipy-1.16.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - pypi: https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c0/ba/daf16c2d1965bf6237fb696639e3e93645ac6801f7dcaf9ec694a74e9326/setuptools_git_versioning-2.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/52/59/0782e51887ac6b07ffd1570e0364cf901ebc36345fea669969d2084baebb/simple_websocket-1.1.0-py3-none-any.whl @@ -88,20 +90,20 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h500dc9f_8.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.10.5-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.7.1-h21dd04a_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.4.6-h281671d_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.5.2-h750e83c_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.1-hd471939_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libmpdec-4.0.0-h6e16a3a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.50.4-h39a8b3b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.1-hd23fc13_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.5-h0622a9a_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.5.4-h230baf5_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.13.9-h2bd861f_100_cp313.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.13.9-h17c18a5_101_cp313.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.2-h7cca4af_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-hf689a15_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda - pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/92/c8/1cf495bac85cf71b80fad5f6d7693e84894f11b9fe876b64b0a1e7cbf32f/aiohttp-3.13.1-cp313-cp313-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/db/ed/1f59215ab6853fbaa5c8495fa6cbc39edfc93553426152b75d82a5f32b76/aiohttp-3.13.2-cp313-cp313-macosx_10_13_x86_64.whl - pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/ac/19dbba27e891f39feb4170b884da449ee2699ef4ebb88eefeda364bbbbcf/asteval-1.0.6-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl @@ -109,7 +111,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/cb/8c/2b30c12155ad8de0cf641d76a8b396a16d2c36bc6d50b621a62b7c4567c1/build-1.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/43/8e/278ea79cf8ee0c395a5ad74625b3465c2fc234bb277f171dd59dd203820d/bumps-1.0.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/7e/e8/64c37fadfc2816a7701fa8a6ed8d87327c7d54eacfbfb6edab14a2f2be75/cloudpickle-3.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/68/35/0167aad910bbdb9599272bd96d01a9ec6852f36b9455cf2ca67bd4cc2d23/contourpy-1.3.3-cp313-cp313-macosx_10_13_x86_64.whl - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/68/49/869b49db0bad6fba7c7471d612c356e745929d14e0de63acbc53e88f2a50/dfo_ls-1.6-py3-none-any.whl @@ -129,7 +131,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/f5/b7/339b9ed180c28418f3c5c425f341759ce3722b61cc54f8c20918a034a1d5/mpld3-0.5.11-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6b/31/b46518ecc604d7edf3a4f94cb3bf021fc62aa301f0cb849936968164ef23/msgpack-1.1.2-cp313-cp313-macosx_10_13_x86_64.whl - pypi: https://files.pythonhosted.org/packages/91/1c/eb97db117a1ebe46d457a3d235a7b9d2e6dcab174f42d1b67663dd9e5371/multidict-6.7.0-cp313-cp313-macosx_10_13_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/13/34/00c7ae8194074ed82b64e0bb7c24220eac5f77ac90c16e23cf0d2cfd2a03/narwhals-2.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/62/cd/9481a199a086ac9f91eaa232b56cff90ca7fdc2cb6658de93825b1007094/narwhals-2.10.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/57/7e/b72610cc91edf138bc588df5150957a4937221ca6058b825b4725c27be62/numpy-2.3.4-cp313-cp313-macosx_10_13_x86_64.whl - pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/cd/4b/18b035ee18f97c1040d94debd8f2e737000ad70ccc8f5513f4eefad75f4b/pandas-2.3.3-cp313-cp313-macosx_10_13_x86_64.whl @@ -142,10 +144,10 @@ environments: - pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d8/f0/c5aa0a69fd9326f013110653543f36ece4913c17921f3e1dbd78e1b423ee/python_engineio-4.12.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/d7/5b/821733876bad200638237d1cab671b46cfdafb73c0b4094f59c5947155ae/python_socketio-5.14.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c0/1a/b393a06aa6f2f6ab4a9c5c160a62d488b17d6da5cf93a67bc13a6e3239cd/python_socketio-5.14.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/88/3b/1815d8914c70257173ec307d3b7f8016c878a1542a195a18de25c63e2ec7/scipp-25.8.0-cp313-cp313-macosx_11_0_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/c1/27/c5b52f1ee81727a9fc457f5ac1e9bf3d6eab311805ea615c83c27ba06400/scipy-1.16.2-cp313-cp313-macosx_10_14_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/71/f2/18d5be10ac890ce7490451eb55d41bf9d96e481751362a30ed1a8bc176fa/scipp-25.11.0-cp313-cp313-macosx_11_0_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/72/f1/57e8327ab1508272029e27eeef34f2302ffc156b69e7e233e906c2a5c379/scipy-1.16.3-cp313-cp313-macosx_10_14_x86_64.whl - pypi: https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c0/ba/daf16c2d1965bf6237fb696639e3e93645ac6801f7dcaf9ec694a74e9326/setuptools_git_versioning-2.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/52/59/0782e51887ac6b07ffd1570e0364cf901ebc36345fea669969d2084baebb/simple_websocket-1.1.0-py3-none-any.whl @@ -161,20 +163,20 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.10.5-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-75.1-hfee45f7_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.1-hec049ff_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.4.6-h1da3d7d_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-he5f378a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.1-h39f12f2_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h5505292_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.50.4-h4237e3c_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.5.4-h5503f6c_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.13.9-h09175d0_100_cp313.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.13.9-hfc2f54d_101_cp313.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h1d1bf99_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h892fb3f_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda - pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a8/19/23c6b81cca587ec96943d977a58d11d05a82837022e65cd5502d665a7d11/aiohttp-3.13.1-cp313-cp313-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/68/7b/fe0fe0f5e05e13629d893c760465173a15ad0039c0a5b0d0040995c8075e/aiohttp-3.13.2-cp313-cp313-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/ac/19dbba27e891f39feb4170b884da449ee2699ef4ebb88eefeda364bbbbcf/asteval-1.0.6-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl @@ -182,7 +184,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/cb/8c/2b30c12155ad8de0cf641d76a8b396a16d2c36bc6d50b621a62b7c4567c1/build-1.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/43/8e/278ea79cf8ee0c395a5ad74625b3465c2fc234bb277f171dd59dd203820d/bumps-1.0.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/7e/e8/64c37fadfc2816a7701fa8a6ed8d87327c7d54eacfbfb6edab14a2f2be75/cloudpickle-3.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/96/e4/7adcd9c8362745b2210728f209bfbcf7d91ba868a2c5f40d8b58f54c509b/contourpy-1.3.3-cp313-cp313-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/68/49/869b49db0bad6fba7c7471d612c356e745929d14e0de63acbc53e88f2a50/dfo_ls-1.6-py3-none-any.whl @@ -202,7 +204,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/f5/b7/339b9ed180c28418f3c5c425f341759ce3722b61cc54f8c20918a034a1d5/mpld3-0.5.11-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/92/dc/c385f38f2c2433333345a82926c6bfa5ecfff3ef787201614317b58dd8be/msgpack-1.1.2-cp313-cp313-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/f1/d8/6c3442322e41fb1dd4de8bd67bfd11cd72352ac131f6368315617de752f1/multidict-6.7.0-cp313-cp313-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/13/34/00c7ae8194074ed82b64e0bb7c24220eac5f77ac90c16e23cf0d2cfd2a03/narwhals-2.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/62/cd/9481a199a086ac9f91eaa232b56cff90ca7fdc2cb6658de93825b1007094/narwhals-2.10.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/3e/46/bdd3370dcea2f95ef14af79dbf81e6927102ddf1cc54adc0024d61252fd9/numpy-2.3.4-cp313-cp313-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/31/94/72fac03573102779920099bcac1c3b05975c2cb5f01eac609faf34bed1ca/pandas-2.3.3-cp313-cp313-macosx_11_0_arm64.whl @@ -215,10 +217,10 @@ environments: - pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d8/f0/c5aa0a69fd9326f013110653543f36ece4913c17921f3e1dbd78e1b423ee/python_engineio-4.12.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/d7/5b/821733876bad200638237d1cab671b46cfdafb73c0b4094f59c5947155ae/python_socketio-5.14.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c0/1a/b393a06aa6f2f6ab4a9c5c160a62d488b17d6da5cf93a67bc13a6e3239cd/python_socketio-5.14.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/9b/70/10c2358156874a645f5556c4bdcddd01cf10c9b73b15434e04512be5101b/scipp-25.8.0-cp313-cp313-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/32/a9/15c20d08e950b540184caa8ced675ba1128accb0e09c653780ba023a4110/scipy-1.16.2-cp313-cp313-macosx_12_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/64/7c/d8a343b0a622987335a1ac848084079c47c21e44fcc450f9c145b11a56f6/scipp-25.11.0-cp313-cp313-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/44/13/7e63cfba8a7452eb756306aa2fd9b37a29a323b672b964b4fdeded9a3f21/scipy-1.16.3-cp313-cp313-macosx_12_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c0/ba/daf16c2d1965bf6237fb696639e3e93645ac6801f7dcaf9ec694a74e9326/setuptools_git_versioning-2.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/52/59/0782e51887ac6b07ffd1570e0364cf901ebc36345fea669969d2084baebb/simple_websocket-1.1.0-py3-none-any.whl @@ -233,13 +235,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_8.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.10.5-h4c7d964_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.7.1-hac47afa_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.4.6-h537db12_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.5.2-h52bdfb6_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.1-h2466b09_2.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-h2466b09_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.50.4-hf5d6505_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.1-h2466b09_2.conda - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.5.4-h725018a_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.13.9-hdf00ec1_100_cp313.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.13.9-h09917c8_101_cp313.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h2c6b04d_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda @@ -248,7 +250,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_32.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.44.35208-h818238b_32.conda - pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/cc/00/f3a92c592a845ebb2f47d102a67f35f0925cb854c5e7386f1a3a1fdff2ab/aiohttp-3.13.1-cp313-cp313-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/5d/28/a8a9fc6957b2cee8902414e41816b5ab5536ecf43c3b1843c10e82c559b2/aiohttp-3.13.2-cp313-cp313-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/ac/19dbba27e891f39feb4170b884da449ee2699ef4ebb88eefeda364bbbbcf/asteval-1.0.6-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl @@ -256,7 +258,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/cb/8c/2b30c12155ad8de0cf641d76a8b396a16d2c36bc6d50b621a62b7c4567c1/build-1.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/43/8e/278ea79cf8ee0c395a5ad74625b3465c2fc234bb277f171dd59dd203820d/bumps-1.0.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/7e/e8/64c37fadfc2816a7701fa8a6ed8d87327c7d54eacfbfb6edab14a2f2be75/cloudpickle-3.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/18/0b/0098c214843213759692cc638fce7de5c289200a830e5035d1791d7a2338/contourpy-1.3.3-cp313-cp313-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl @@ -277,7 +279,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/f5/b7/339b9ed180c28418f3c5c425f341759ce3722b61cc54f8c20918a034a1d5/mpld3-0.5.11-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/74/07/1ed8277f8653c40ebc65985180b007879f6a836c525b3885dcc6448ae6cb/msgpack-1.1.2-cp313-cp313-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/32/31/75c59e7d3b4205075b4c183fa4ca398a2daf2303ddf616b04ae6ef55cffe/multidict-6.7.0-cp313-cp313-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/13/34/00c7ae8194074ed82b64e0bb7c24220eac5f77ac90c16e23cf0d2cfd2a03/narwhals-2.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/62/cd/9481a199a086ac9f91eaa232b56cff90ca7fdc2cb6658de93825b1007094/narwhals-2.10.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/09/97/fd421e8bc50766665ad35536c2bb4ef916533ba1fdd053a62d96cc7c8b95/numpy-2.3.4-cp313-cp313-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/4f/c7/e54682c96a895d0c808453269e0b5928a07a127a15704fedb643e9b0a4c8/pandas-2.3.3-cp313-cp313-win_amd64.whl @@ -290,10 +292,10 @@ environments: - pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d8/f0/c5aa0a69fd9326f013110653543f36ece4913c17921f3e1dbd78e1b423ee/python_engineio-4.12.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/d7/5b/821733876bad200638237d1cab671b46cfdafb73c0b4094f59c5947155ae/python_socketio-5.14.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c0/1a/b393a06aa6f2f6ab4a9c5c160a62d488b17d6da5cf93a67bc13a6e3239cd/python_socketio-5.14.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ca/3b/8d206694f1dfe8c6305d8c13d9d71fcb3962543b99d6ca8df76fcee5964d/scipp-25.8.0-cp313-cp313-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/a1/57/0f38e396ad19e41b4c5db66130167eef8ee620a49bc7d0512e3bb67e0cab/scipy-1.16.2-cp313-cp313-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/f6/f3/9d1bb423a2dc0bbebfc98191095dd410a1268397b9c692d76a3ea971c790/scipp-25.11.0-cp313-cp313-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/cd/01/1204382461fcbfeb05b6161b594f4007e78b6eba9b375382f79153172b4d/scipy-1.16.3-cp313-cp313-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c0/ba/daf16c2d1965bf6237fb696639e3e93645ac6801f7dcaf9ec694a74e9326/setuptools_git_versioning-2.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/52/59/0782e51887ac6b07ffd1570e0364cf901ebc36345fea669969d2084baebb/simple_websocket-1.1.0-py3-none-any.whl @@ -315,26 +317,28 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.10.5-hbd8a1cb_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.44-ha97dd6f_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.44-h1aa0949_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.1-hecca717_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.6-h2dba641_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h9ec8514_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-h767d61c_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-h767d61c_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.1-hb9d3cd8_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.50.4-h0c1763c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h8f9b012_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.2-he9a06e4_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.5.4-h26f9b46_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.13.9-h2b335a9_100_cp313.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.13.9-hc97d973_101_cp313.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8c095d6_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_hd72426e_102.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb8e6e7a_2.conda - pypi: https://files.pythonhosted.org/packages/8d/3f/95338030883d8c8b91223b4e21744b04d11b161a3ef117295d8241f50ab4/accessible_pygments-0.0.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/cc/e6/33d305e6cce0a8daeb79c7d8d6547d6e5f27f4e35fa4883fc9c9eb638596/aiohttp-3.13.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/f7/0d/4764669bdf47bd472899b3d3db91fffbe925c8e3038ec591a2fd2ad6a14d/aiohttp-3.13.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/7e/b3/6b4067be973ae96ba0d615946e314c5ae35f9f993eca561b356540bb0c2b/alabaster-1.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/ac/19dbba27e891f39feb4170b884da449ee2699ef4ebb88eefeda364bbbbcf/asteval-1.0.6-py3-none-any.whl @@ -349,7 +353,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/e4/37/af0d2ef3967ac0d6113837b44a4f0bfe1328c2b9763bd5b1744520e5cfed/certifi-2025.10.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/6f/f5fbc992a329ee4e0f288c1fe0e2ad9485ed064cac731ed2fe47dcc38cbf/chardet-5.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/7e/e8/64c37fadfc2816a7701fa8a6ed8d87327c7d54eacfbfb6edab14a2f2be75/cloudpickle-3.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/af/02/18785edcdf6266cdd6c6dc7635f1cbeefd9a5b4c3bb8aff8bd681e9dd095/codecov-2.1.13-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/4b/32/e0f13a1c5b0f8572d0ec6ae2f6c677b7991fafd95da523159c19eff0696a/contourpy-1.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl @@ -380,8 +384,8 @@ environments: - pypi: https://files.pythonhosted.org/packages/f5/b7/339b9ed180c28418f3c5c425f341759ce3722b61cc54f8c20918a034a1d5/mpld3-0.5.11-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5d/ba/459f18c16f2b3fc1a1ca871f72f07d70c07bf768ad0a507a698b8052ac58/msgpack-1.1.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/c6/2d/f0b184fa88d6630aa267680bdb8623fb69cb0d024b8c6f0d23f9a0f406d3/multidict-6.7.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/13/34/00c7ae8194074ed82b64e0bb7c24220eac5f77ac90c16e23cf0d2cfd2a03/narwhals-2.9.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/11/0e/16b3886858b3953ef836dea25b951f3ab0c5b5a431da03f675c0e999afb8/nh3-0.3.1-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/62/cd/9481a199a086ac9f91eaa232b56cff90ca7fdc2cb6658de93825b1007094/narwhals-2.10.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/42/0f/c76bf3dba22c73c38e9b1113b017cf163f7696f50e003404ec5ecdb1e8a6/nh3-0.3.2-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/9e/7e/7d306ff7cb143e6d975cfa7eb98a93e73495c4deabb7d1b5ecf09ea0fd69/numpy-2.3.4-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/15/07/284f757f63f8a8d69ed4472bfd85122bd086e637bf4ed09de572d575a693/pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl @@ -402,15 +406,15 @@ environments: - pypi: https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d8/f0/c5aa0a69fd9326f013110653543f36ece4913c17921f3e1dbd78e1b423ee/python_engineio-4.12.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/d7/5b/821733876bad200638237d1cab671b46cfdafb73c0b4094f59c5947155ae/python_socketio-5.14.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c0/1a/b393a06aa6f2f6ab4a9c5c160a62d488b17d6da5cf93a67bc13a6e3239cd/python_socketio-5.14.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e1/67/921ec3024056483db83953ae8e48079ad62b92db7880013ca77632921dd0/readme_renderer-44.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/48/9c/6d8035cafa2d2d314f34e6cd9313a299de095b26e96f1c7312878f988eec/restructuredtext_lint-1.4.0.tar.gz - pypi: https://files.pythonhosted.org/packages/53/97/d2cbbaa10c9b826af0e10fdf836e1bf344d9f0abb873ebc34d1f49642d3f/roman_numerals_py-3.1.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e0/35/266a80d0eb97bd224b3265b9437bd89dde0dcf4faf299db1212e81824e7e/ruff-0.14.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/c3/cf/4c3853de982ba47f94493c90fb4bf0a2164ca5b48a769b4facd6c28c9f6b/scipp-25.8.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/da/6a/1a927b14ddc7714111ea51f4e568203b2bb6ed59bdd036d62127c1a360c8/scipy-1.16.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/a7/e7/138b883f0dfe4ad5b76b58bf4ae675f4d2176ac2b24bdd81b4d966b28c61/ruff-0.14.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/77/34/1956aed61c4abb91926f9513330afac4654cc2a711ecb73085dc4e2e5c1d/scipp-25.11.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/21/f6/4bfb5695d8941e5c570a04d9fcd0d36bce7511b7d78e6e75c8f9791f82d0/scipy-1.16.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - pypi: https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c0/ba/daf16c2d1965bf6237fb696639e3e93645ac6801f7dcaf9ec694a74e9326/setuptools_git_versioning-2.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/52/59/0782e51887ac6b07ffd1570e0364cf901ebc36345fea669969d2084baebb/simple_websocket-1.1.0-py3-none-any.whl @@ -429,14 +433,14 @@ environments: - pypi: https://files.pythonhosted.org/packages/52/a7/d2782e4e3f77c8450f727ba74a8f12756d5ba823d81b941f1b04da9d033a/sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/80/c5/0c06759b95747882bb50abda18f5fb48c3e9b0fbfc6ebc0e23550b52415d/stevedore-5.5.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/44/6f/7120676b6d73228c96e17f1f794d8ab046fc910d781c8d151120c3f1569e/toml-0.10.2-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/3e/84/1691aae773dccff72c866ad19af7adb12d4fb8b439c8bfb36ffc429c8c27/tox-4.31.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/40/17/3dd6f646da0c2b5f47950f6a8259082f0e5de1a6a2f2d8e91dae6ff8efb0/tox_gh_actions-3.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fc/cc/e09c0d663a004945f82beecd4f147053567910479314e8d01ba71e5d5dea/tox-4.32.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/9e/8d50f3b3fc4af8c73154f64d4a2293bfa2d517a19000e70ef2d614254084/tox_gh_actions-3.5.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e1/85/a4ff8758c66f1fc32aa5e9a145908394bf9cf1c79ffd1113cfdeb77e74e4/trove_classifiers-2025.9.11.17-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5c/23/c7abc0ca0a1526a0774eca151daeb8de62ec457e77262b66b359c3c7679e/tzdata-2025.2-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8f/5e/f1e1dd319e35e962a4e00b33150a8868b6329cc1d19fd533436ba5488f09/uncertainties-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/27/73/d9a94da0e9d470a543c1b9d3ccbceb0f59455983088e727b8a1824ed90fb/virtualenv-20.35.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/79/0c/c05523fa3181fdf0c9c52a6ba91a23fbf3246cc095f26f6516f9c60e6771/virtualenv-20.35.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/78/58/e860788190eba3bcce367f74d29c4675466ce8dddfba85f7827588416f01/wsproto-1.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/11/c9/cd8538dc2e7727095e0c1d867bad1e40c98f37763e6d995c1939f5fdc7b1/yarl-1.22.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - pypi: ./ @@ -444,21 +448,21 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h500dc9f_8.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.10.5-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.7.1-h21dd04a_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.4.6-h281671d_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.5.2-h750e83c_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.1-hd471939_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libmpdec-4.0.0-h6e16a3a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.50.4-h39a8b3b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.1-hd23fc13_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.5-h0622a9a_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.5.4-h230baf5_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.13.9-h2bd861f_100_cp313.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.13.9-h17c18a5_101_cp313.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.2-h7cca4af_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-hf689a15_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda - pypi: https://files.pythonhosted.org/packages/8d/3f/95338030883d8c8b91223b4e21744b04d11b161a3ef117295d8241f50ab4/accessible_pygments-0.0.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/92/c8/1cf495bac85cf71b80fad5f6d7693e84894f11b9fe876b64b0a1e7cbf32f/aiohttp-3.13.1-cp313-cp313-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/db/ed/1f59215ab6853fbaa5c8495fa6cbc39edfc93553426152b75d82a5f32b76/aiohttp-3.13.2-cp313-cp313-macosx_10_13_x86_64.whl - pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/7e/b3/6b4067be973ae96ba0d615946e314c5ae35f9f993eca561b356540bb0c2b/alabaster-1.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/ac/19dbba27e891f39feb4170b884da449ee2699ef4ebb88eefeda364bbbbcf/asteval-1.0.6-py3-none-any.whl @@ -473,7 +477,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/e4/37/af0d2ef3967ac0d6113837b44a4f0bfe1328c2b9763bd5b1744520e5cfed/certifi-2025.10.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/6f/f5fbc992a329ee4e0f288c1fe0e2ad9485ed064cac731ed2fe47dcc38cbf/chardet-5.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl - - pypi: https://files.pythonhosted.org/packages/7e/e8/64c37fadfc2816a7701fa8a6ed8d87327c7d54eacfbfb6edab14a2f2be75/cloudpickle-3.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/af/02/18785edcdf6266cdd6c6dc7635f1cbeefd9a5b4c3bb8aff8bd681e9dd095/codecov-2.1.13-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/68/35/0167aad910bbdb9599272bd96d01a9ec6852f36b9455cf2ca67bd4cc2d23/contourpy-1.3.3-cp313-cp313-macosx_10_13_x86_64.whl @@ -504,8 +508,8 @@ environments: - pypi: https://files.pythonhosted.org/packages/f5/b7/339b9ed180c28418f3c5c425f341759ce3722b61cc54f8c20918a034a1d5/mpld3-0.5.11-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6b/31/b46518ecc604d7edf3a4f94cb3bf021fc62aa301f0cb849936968164ef23/msgpack-1.1.2-cp313-cp313-macosx_10_13_x86_64.whl - pypi: https://files.pythonhosted.org/packages/91/1c/eb97db117a1ebe46d457a3d235a7b9d2e6dcab174f42d1b67663dd9e5371/multidict-6.7.0-cp313-cp313-macosx_10_13_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/13/34/00c7ae8194074ed82b64e0bb7c24220eac5f77ac90c16e23cf0d2cfd2a03/narwhals-2.9.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e1/28/a387fed70438d2810c8ac866e7b24bf1a5b6f30ae65316dfe4de191afa52/nh3-0.3.1-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl + - pypi: https://files.pythonhosted.org/packages/62/cd/9481a199a086ac9f91eaa232b56cff90ca7fdc2cb6658de93825b1007094/narwhals-2.10.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b6/3e/f5a5cc2885c24be13e9b937441bd16a012ac34a657fe05e58927e8af8b7a/nh3-0.3.2-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl - pypi: https://files.pythonhosted.org/packages/57/7e/b72610cc91edf138bc588df5150957a4937221ca6058b825b4725c27be62/numpy-2.3.4-cp313-cp313-macosx_10_13_x86_64.whl - pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/cd/4b/18b035ee18f97c1040d94debd8f2e737000ad70ccc8f5513f4eefad75f4b/pandas-2.3.3-cp313-cp313-macosx_10_13_x86_64.whl @@ -526,15 +530,15 @@ environments: - pypi: https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d8/f0/c5aa0a69fd9326f013110653543f36ece4913c17921f3e1dbd78e1b423ee/python_engineio-4.12.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/d7/5b/821733876bad200638237d1cab671b46cfdafb73c0b4094f59c5947155ae/python_socketio-5.14.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c0/1a/b393a06aa6f2f6ab4a9c5c160a62d488b17d6da5cf93a67bc13a6e3239cd/python_socketio-5.14.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e1/67/921ec3024056483db83953ae8e48079ad62b92db7880013ca77632921dd0/readme_renderer-44.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/48/9c/6d8035cafa2d2d314f34e6cd9313a299de095b26e96f1c7312878f988eec/restructuredtext_lint-1.4.0.tar.gz - pypi: https://files.pythonhosted.org/packages/53/97/d2cbbaa10c9b826af0e10fdf836e1bf344d9f0abb873ebc34d1f49642d3f/roman_numerals_py-3.1.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ef/2e/1226961855ccd697255988f5a2474890ac7c5863b080b15bd038df820818/ruff-0.14.1-py3-none-macosx_10_12_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/88/3b/1815d8914c70257173ec307d3b7f8016c878a1542a195a18de25c63e2ec7/scipp-25.8.0-cp313-cp313-macosx_11_0_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/c1/27/c5b52f1ee81727a9fc457f5ac1e9bf3d6eab311805ea615c83c27ba06400/scipy-1.16.2-cp313-cp313-macosx_10_14_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/d3/c8/6724f4634c1daf52409fbf13fefda64aa9c8f81e44727a378b7b73dc590b/ruff-0.14.3-py3-none-macosx_10_12_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/71/f2/18d5be10ac890ce7490451eb55d41bf9d96e481751362a30ed1a8bc176fa/scipp-25.11.0-cp313-cp313-macosx_11_0_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/72/f1/57e8327ab1508272029e27eeef34f2302ffc156b69e7e233e906c2a5c379/scipy-1.16.3-cp313-cp313-macosx_10_14_x86_64.whl - pypi: https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c0/ba/daf16c2d1965bf6237fb696639e3e93645ac6801f7dcaf9ec694a74e9326/setuptools_git_versioning-2.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/52/59/0782e51887ac6b07ffd1570e0364cf901ebc36345fea669969d2084baebb/simple_websocket-1.1.0-py3-none-any.whl @@ -553,14 +557,14 @@ environments: - pypi: https://files.pythonhosted.org/packages/52/a7/d2782e4e3f77c8450f727ba74a8f12756d5ba823d81b941f1b04da9d033a/sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/80/c5/0c06759b95747882bb50abda18f5fb48c3e9b0fbfc6ebc0e23550b52415d/stevedore-5.5.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/44/6f/7120676b6d73228c96e17f1f794d8ab046fc910d781c8d151120c3f1569e/toml-0.10.2-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/3e/84/1691aae773dccff72c866ad19af7adb12d4fb8b439c8bfb36ffc429c8c27/tox-4.31.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/40/17/3dd6f646da0c2b5f47950f6a8259082f0e5de1a6a2f2d8e91dae6ff8efb0/tox_gh_actions-3.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fc/cc/e09c0d663a004945f82beecd4f147053567910479314e8d01ba71e5d5dea/tox-4.32.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/9e/8d50f3b3fc4af8c73154f64d4a2293bfa2d517a19000e70ef2d614254084/tox_gh_actions-3.5.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e1/85/a4ff8758c66f1fc32aa5e9a145908394bf9cf1c79ffd1113cfdeb77e74e4/trove_classifiers-2025.9.11.17-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5c/23/c7abc0ca0a1526a0774eca151daeb8de62ec457e77262b66b359c3c7679e/tzdata-2025.2-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8f/5e/f1e1dd319e35e962a4e00b33150a8868b6329cc1d19fd533436ba5488f09/uncertainties-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/27/73/d9a94da0e9d470a543c1b9d3ccbceb0f59455983088e727b8a1824ed90fb/virtualenv-20.35.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/79/0c/c05523fa3181fdf0c9c52a6ba91a23fbf3246cc095f26f6516f9c60e6771/virtualenv-20.35.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/78/58/e860788190eba3bcce367f74d29c4675466ce8dddfba85f7827588416f01/wsproto-1.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/01/88/04d98af0b47e0ef42597b9b28863b9060bb515524da0a65d5f4db160b2d5/yarl-1.22.0-cp313-cp313-macosx_10_13_x86_64.whl - pypi: ./ @@ -569,21 +573,21 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.10.5-hbd8a1cb_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-75.1-hfee45f7_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.1-hec049ff_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.4.6-h1da3d7d_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-he5f378a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.1-h39f12f2_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h5505292_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.50.4-h4237e3c_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.5.4-h5503f6c_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.13.9-h09175d0_100_cp313.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.13.9-hfc2f54d_101_cp313.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h1d1bf99_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h892fb3f_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda - pypi: https://files.pythonhosted.org/packages/8d/3f/95338030883d8c8b91223b4e21744b04d11b161a3ef117295d8241f50ab4/accessible_pygments-0.0.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a8/19/23c6b81cca587ec96943d977a58d11d05a82837022e65cd5502d665a7d11/aiohttp-3.13.1-cp313-cp313-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/68/7b/fe0fe0f5e05e13629d893c760465173a15ad0039c0a5b0d0040995c8075e/aiohttp-3.13.2-cp313-cp313-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/7e/b3/6b4067be973ae96ba0d615946e314c5ae35f9f993eca561b356540bb0c2b/alabaster-1.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/ac/19dbba27e891f39feb4170b884da449ee2699ef4ebb88eefeda364bbbbcf/asteval-1.0.6-py3-none-any.whl @@ -598,7 +602,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/e4/37/af0d2ef3967ac0d6113837b44a4f0bfe1328c2b9763bd5b1744520e5cfed/certifi-2025.10.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/6f/f5fbc992a329ee4e0f288c1fe0e2ad9485ed064cac731ed2fe47dcc38cbf/chardet-5.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl - - pypi: https://files.pythonhosted.org/packages/7e/e8/64c37fadfc2816a7701fa8a6ed8d87327c7d54eacfbfb6edab14a2f2be75/cloudpickle-3.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/af/02/18785edcdf6266cdd6c6dc7635f1cbeefd9a5b4c3bb8aff8bd681e9dd095/codecov-2.1.13-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/96/e4/7adcd9c8362745b2210728f209bfbcf7d91ba868a2c5f40d8b58f54c509b/contourpy-1.3.3-cp313-cp313-macosx_11_0_arm64.whl @@ -629,8 +633,8 @@ environments: - pypi: https://files.pythonhosted.org/packages/f5/b7/339b9ed180c28418f3c5c425f341759ce3722b61cc54f8c20918a034a1d5/mpld3-0.5.11-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/92/dc/c385f38f2c2433333345a82926c6bfa5ecfff3ef787201614317b58dd8be/msgpack-1.1.2-cp313-cp313-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/f1/d8/6c3442322e41fb1dd4de8bd67bfd11cd72352ac131f6368315617de752f1/multidict-6.7.0-cp313-cp313-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/13/34/00c7ae8194074ed82b64e0bb7c24220eac5f77ac90c16e23cf0d2cfd2a03/narwhals-2.9.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e1/28/a387fed70438d2810c8ac866e7b24bf1a5b6f30ae65316dfe4de191afa52/nh3-0.3.1-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl + - pypi: https://files.pythonhosted.org/packages/62/cd/9481a199a086ac9f91eaa232b56cff90ca7fdc2cb6658de93825b1007094/narwhals-2.10.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b6/3e/f5a5cc2885c24be13e9b937441bd16a012ac34a657fe05e58927e8af8b7a/nh3-0.3.2-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl - pypi: https://files.pythonhosted.org/packages/3e/46/bdd3370dcea2f95ef14af79dbf81e6927102ddf1cc54adc0024d61252fd9/numpy-2.3.4-cp313-cp313-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/31/94/72fac03573102779920099bcac1c3b05975c2cb5f01eac609faf34bed1ca/pandas-2.3.3-cp313-cp313-macosx_11_0_arm64.whl @@ -651,15 +655,15 @@ environments: - pypi: https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d8/f0/c5aa0a69fd9326f013110653543f36ece4913c17921f3e1dbd78e1b423ee/python_engineio-4.12.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/d7/5b/821733876bad200638237d1cab671b46cfdafb73c0b4094f59c5947155ae/python_socketio-5.14.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c0/1a/b393a06aa6f2f6ab4a9c5c160a62d488b17d6da5cf93a67bc13a6e3239cd/python_socketio-5.14.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e1/67/921ec3024056483db83953ae8e48079ad62b92db7880013ca77632921dd0/readme_renderer-44.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/48/9c/6d8035cafa2d2d314f34e6cd9313a299de095b26e96f1c7312878f988eec/restructuredtext_lint-1.4.0.tar.gz - pypi: https://files.pythonhosted.org/packages/53/97/d2cbbaa10c9b826af0e10fdf836e1bf344d9f0abb873ebc34d1f49642d3f/roman_numerals_py-3.1.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c1/ea/fd9e95863124ed159cd0667ec98449ae461de94acda7101f1acb6066da00/ruff-0.14.1-py3-none-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/9b/70/10c2358156874a645f5556c4bdcddd01cf10c9b73b15434e04512be5101b/scipp-25.8.0-cp313-cp313-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/32/a9/15c20d08e950b540184caa8ced675ba1128accb0e09c653780ba023a4110/scipy-1.16.2-cp313-cp313-macosx_12_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/de/03/db1bce591d55fd5f8a08bb02517fa0b5097b2ccabd4ea1ee29aa72b67d96/ruff-0.14.3-py3-none-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/64/7c/d8a343b0a622987335a1ac848084079c47c21e44fcc450f9c145b11a56f6/scipp-25.11.0-cp313-cp313-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/44/13/7e63cfba8a7452eb756306aa2fd9b37a29a323b672b964b4fdeded9a3f21/scipy-1.16.3-cp313-cp313-macosx_12_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c0/ba/daf16c2d1965bf6237fb696639e3e93645ac6801f7dcaf9ec694a74e9326/setuptools_git_versioning-2.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/52/59/0782e51887ac6b07ffd1570e0364cf901ebc36345fea669969d2084baebb/simple_websocket-1.1.0-py3-none-any.whl @@ -678,14 +682,14 @@ environments: - pypi: https://files.pythonhosted.org/packages/52/a7/d2782e4e3f77c8450f727ba74a8f12756d5ba823d81b941f1b04da9d033a/sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/80/c5/0c06759b95747882bb50abda18f5fb48c3e9b0fbfc6ebc0e23550b52415d/stevedore-5.5.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/44/6f/7120676b6d73228c96e17f1f794d8ab046fc910d781c8d151120c3f1569e/toml-0.10.2-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/3e/84/1691aae773dccff72c866ad19af7adb12d4fb8b439c8bfb36ffc429c8c27/tox-4.31.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/40/17/3dd6f646da0c2b5f47950f6a8259082f0e5de1a6a2f2d8e91dae6ff8efb0/tox_gh_actions-3.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fc/cc/e09c0d663a004945f82beecd4f147053567910479314e8d01ba71e5d5dea/tox-4.32.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/9e/8d50f3b3fc4af8c73154f64d4a2293bfa2d517a19000e70ef2d614254084/tox_gh_actions-3.5.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e1/85/a4ff8758c66f1fc32aa5e9a145908394bf9cf1c79ffd1113cfdeb77e74e4/trove_classifiers-2025.9.11.17-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5c/23/c7abc0ca0a1526a0774eca151daeb8de62ec457e77262b66b359c3c7679e/tzdata-2025.2-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8f/5e/f1e1dd319e35e962a4e00b33150a8868b6329cc1d19fd533436ba5488f09/uncertainties-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/27/73/d9a94da0e9d470a543c1b9d3ccbceb0f59455983088e727b8a1824ed90fb/virtualenv-20.35.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/79/0c/c05523fa3181fdf0c9c52a6ba91a23fbf3246cc095f26f6516f9c60e6771/virtualenv-20.35.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/78/58/e860788190eba3bcce367f74d29c4675466ce8dddfba85f7827588416f01/wsproto-1.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/18/91/3274b215fd8442a03975ce6bee5fe6aa57a8326b29b9d3d56234a1dca244/yarl-1.22.0-cp313-cp313-macosx_11_0_arm64.whl - pypi: ./ @@ -693,13 +697,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_8.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.10.5-h4c7d964_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.7.1-hac47afa_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.4.6-h537db12_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.5.2-h52bdfb6_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.1-h2466b09_2.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-h2466b09_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.50.4-hf5d6505_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.1-h2466b09_2.conda - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.5.4-h725018a_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.13.9-hdf00ec1_100_cp313.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.13.9-h09917c8_101_cp313.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h2c6b04d_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda @@ -709,7 +713,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.44.35208-h818238b_32.conda - pypi: https://files.pythonhosted.org/packages/8d/3f/95338030883d8c8b91223b4e21744b04d11b161a3ef117295d8241f50ab4/accessible_pygments-0.0.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/cc/00/f3a92c592a845ebb2f47d102a67f35f0925cb854c5e7386f1a3a1fdff2ab/aiohttp-3.13.1-cp313-cp313-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/5d/28/a8a9fc6957b2cee8902414e41816b5ab5536ecf43c3b1843c10e82c559b2/aiohttp-3.13.2-cp313-cp313-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/7e/b3/6b4067be973ae96ba0d615946e314c5ae35f9f993eca561b356540bb0c2b/alabaster-1.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/ac/19dbba27e891f39feb4170b884da449ee2699ef4ebb88eefeda364bbbbcf/asteval-1.0.6-py3-none-any.whl @@ -724,7 +728,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/e4/37/af0d2ef3967ac0d6113837b44a4f0bfe1328c2b9763bd5b1744520e5cfed/certifi-2025.10.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/6f/f5fbc992a329ee4e0f288c1fe0e2ad9485ed064cac731ed2fe47dcc38cbf/chardet-5.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c4/26/b9924fa27db384bdcd97ab83b4f0a8058d96ad9626ead570674d5e737d90/charset_normalizer-3.4.4-cp313-cp313-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/7e/e8/64c37fadfc2816a7701fa8a6ed8d87327c7d54eacfbfb6edab14a2f2be75/cloudpickle-3.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/af/02/18785edcdf6266cdd6c6dc7635f1cbeefd9a5b4c3bb8aff8bd681e9dd095/codecov-2.1.13-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/18/0b/0098c214843213759692cc638fce7de5c289200a830e5035d1791d7a2338/contourpy-1.3.3-cp313-cp313-win_amd64.whl @@ -755,8 +759,8 @@ environments: - pypi: https://files.pythonhosted.org/packages/f5/b7/339b9ed180c28418f3c5c425f341759ce3722b61cc54f8c20918a034a1d5/mpld3-0.5.11-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/74/07/1ed8277f8653c40ebc65985180b007879f6a836c525b3885dcc6448ae6cb/msgpack-1.1.2-cp313-cp313-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/32/31/75c59e7d3b4205075b4c183fa4ca398a2daf2303ddf616b04ae6ef55cffe/multidict-6.7.0-cp313-cp313-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/13/34/00c7ae8194074ed82b64e0bb7c24220eac5f77ac90c16e23cf0d2cfd2a03/narwhals-2.9.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a5/ca/263eb96b6d32c61a92c1e5480b7f599b60db7d7fbbc0d944be7532d0ac42/nh3-0.3.1-cp38-abi3-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/62/cd/9481a199a086ac9f91eaa232b56cff90ca7fdc2cb6658de93825b1007094/narwhals-2.10.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/64/9a/1a1c154f10a575d20dd634e5697805e589bbdb7673a0ad00e8da90044ba7/nh3-0.3.2-cp38-abi3-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/09/97/fd421e8bc50766665ad35536c2bb4ef916533ba1fdd053a62d96cc7c8b95/numpy-2.3.4-cp313-cp313-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/4f/c7/e54682c96a895d0c808453269e0b5928a07a127a15704fedb643e9b0a4c8/pandas-2.3.3-cp313-cp313-win_amd64.whl @@ -777,15 +781,15 @@ environments: - pypi: https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d8/f0/c5aa0a69fd9326f013110653543f36ece4913c17921f3e1dbd78e1b423ee/python_engineio-4.12.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/d7/5b/821733876bad200638237d1cab671b46cfdafb73c0b4094f59c5947155ae/python_socketio-5.14.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c0/1a/b393a06aa6f2f6ab4a9c5c160a62d488b17d6da5cf93a67bc13a6e3239cd/python_socketio-5.14.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e1/67/921ec3024056483db83953ae8e48079ad62b92db7880013ca77632921dd0/readme_renderer-44.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/48/9c/6d8035cafa2d2d314f34e6cd9313a299de095b26e96f1c7312878f988eec/restructuredtext_lint-1.4.0.tar.gz - pypi: https://files.pythonhosted.org/packages/53/97/d2cbbaa10c9b826af0e10fdf836e1bf344d9f0abb873ebc34d1f49642d3f/roman_numerals_py-3.1.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/02/88/0ee4ca507d4aa05f67e292d2e5eb0b3e358fbcfe527554a2eda9ac422d6b/ruff-0.14.1-py3-none-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/ca/3b/8d206694f1dfe8c6305d8c13d9d71fcb3962543b99d6ca8df76fcee5964d/scipp-25.8.0-cp313-cp313-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/a1/57/0f38e396ad19e41b4c5db66130167eef8ee620a49bc7d0512e3bb67e0cab/scipy-1.16.2-cp313-cp313-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/03/15/51960ae340823c9859fb60c63301d977308735403e2134e17d1d2858c7fb/ruff-0.14.3-py3-none-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/f6/f3/9d1bb423a2dc0bbebfc98191095dd410a1268397b9c692d76a3ea971c790/scipp-25.11.0-cp313-cp313-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/cd/01/1204382461fcbfeb05b6161b594f4007e78b6eba9b375382f79153172b4d/scipy-1.16.3-cp313-cp313-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c0/ba/daf16c2d1965bf6237fb696639e3e93645ac6801f7dcaf9ec694a74e9326/setuptools_git_versioning-2.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/52/59/0782e51887ac6b07ffd1570e0364cf901ebc36345fea669969d2084baebb/simple_websocket-1.1.0-py3-none-any.whl @@ -804,14 +808,14 @@ environments: - pypi: https://files.pythonhosted.org/packages/52/a7/d2782e4e3f77c8450f727ba74a8f12756d5ba823d81b941f1b04da9d033a/sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/80/c5/0c06759b95747882bb50abda18f5fb48c3e9b0fbfc6ebc0e23550b52415d/stevedore-5.5.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/44/6f/7120676b6d73228c96e17f1f794d8ab046fc910d781c8d151120c3f1569e/toml-0.10.2-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/3e/84/1691aae773dccff72c866ad19af7adb12d4fb8b439c8bfb36ffc429c8c27/tox-4.31.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/40/17/3dd6f646da0c2b5f47950f6a8259082f0e5de1a6a2f2d8e91dae6ff8efb0/tox_gh_actions-3.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fc/cc/e09c0d663a004945f82beecd4f147053567910479314e8d01ba71e5d5dea/tox-4.32.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/9e/8d50f3b3fc4af8c73154f64d4a2293bfa2d517a19000e70ef2d614254084/tox_gh_actions-3.5.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e1/85/a4ff8758c66f1fc32aa5e9a145908394bf9cf1c79ffd1113cfdeb77e74e4/trove_classifiers-2025.9.11.17-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5c/23/c7abc0ca0a1526a0774eca151daeb8de62ec457e77262b66b359c3c7679e/tzdata-2025.2-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8f/5e/f1e1dd319e35e962a4e00b33150a8868b6329cc1d19fd533436ba5488f09/uncertainties-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/27/73/d9a94da0e9d470a543c1b9d3ccbceb0f59455983088e727b8a1824ed90fb/virtualenv-20.35.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/79/0c/c05523fa3181fdf0c9c52a6ba91a23fbf3246cc095f26f6516f9c60e6771/virtualenv-20.35.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/78/58/e860788190eba3bcce367f74d29c4675466ce8dddfba85f7827588416f01/wsproto-1.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9a/ee/450914ae11b419eadd067c6183ae08381cfdfcb9798b90b2b713bbebddda/yarl-1.22.0-cp313-cp313-win_amd64.whl - pypi: ./ @@ -857,10 +861,10 @@ packages: version: 2.6.1 sha256: f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8 requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/92/c8/1cf495bac85cf71b80fad5f6d7693e84894f11b9fe876b64b0a1e7cbf32f/aiohttp-3.13.1-cp313-cp313-macosx_10_13_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/5d/28/a8a9fc6957b2cee8902414e41816b5ab5536ecf43c3b1843c10e82c559b2/aiohttp-3.13.2-cp313-cp313-win_amd64.whl name: aiohttp - version: 3.13.1 - sha256: 4bef5b83296cebb8167707b4f8d06c1805db0af632f7a72d7c5288a84667e7c3 + version: 3.13.2 + sha256: a88d13e7ca367394908f8a276b89d04a3652044612b9a408a0bb22a5ed976a1a requires_dist: - aiohappyeyeballs>=2.5.0 - aiosignal>=1.4.0 @@ -875,10 +879,10 @@ packages: - brotlicffi ; platform_python_implementation != 'CPython' and extra == 'speedups' - backports-zstd ; python_full_version < '3.14' and platform_python_implementation == 'CPython' and extra == 'speedups' requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/a8/19/23c6b81cca587ec96943d977a58d11d05a82837022e65cd5502d665a7d11/aiohttp-3.13.1-cp313-cp313-macosx_11_0_arm64.whl +- pypi: https://files.pythonhosted.org/packages/68/7b/fe0fe0f5e05e13629d893c760465173a15ad0039c0a5b0d0040995c8075e/aiohttp-3.13.2-cp313-cp313-macosx_11_0_arm64.whl name: aiohttp - version: 3.13.1 - sha256: 27af0619c33f9ca52f06069ec05de1a357033449ab101836f431768ecfa63ff5 + version: 3.13.2 + sha256: 5276807b9de9092af38ed23ce120539ab0ac955547b38563a9ba4f5b07b95293 requires_dist: - aiohappyeyeballs>=2.5.0 - aiosignal>=1.4.0 @@ -893,10 +897,10 @@ packages: - brotlicffi ; platform_python_implementation != 'CPython' and extra == 'speedups' - backports-zstd ; python_full_version < '3.14' and platform_python_implementation == 'CPython' and extra == 'speedups' requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/cc/00/f3a92c592a845ebb2f47d102a67f35f0925cb854c5e7386f1a3a1fdff2ab/aiohttp-3.13.1-cp313-cp313-win_amd64.whl +- pypi: https://files.pythonhosted.org/packages/db/ed/1f59215ab6853fbaa5c8495fa6cbc39edfc93553426152b75d82a5f32b76/aiohttp-3.13.2-cp313-cp313-macosx_10_13_x86_64.whl name: aiohttp - version: 3.13.1 - sha256: ef56ffe60e8d97baac123272bde1ab889ee07d3419606fae823c80c2b86c403e + version: 3.13.2 + sha256: 088912a78b4d4f547a1f19c099d5a506df17eacec3c6f4375e2831ec1d995742 requires_dist: - aiohappyeyeballs>=2.5.0 - aiosignal>=1.4.0 @@ -911,10 +915,10 @@ packages: - brotlicffi ; platform_python_implementation != 'CPython' and extra == 'speedups' - backports-zstd ; python_full_version < '3.14' and platform_python_implementation == 'CPython' and extra == 'speedups' requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/cc/e6/33d305e6cce0a8daeb79c7d8d6547d6e5f27f4e35fa4883fc9c9eb638596/aiohttp-3.13.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/f7/0d/4764669bdf47bd472899b3d3db91fffbe925c8e3038ec591a2fd2ad6a14d/aiohttp-3.13.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl name: aiohttp - version: 3.13.1 - sha256: 010dc9b7110f055006acd3648d5d5955bb6473b37c3663ec42a1b4cba7413e6b + version: 3.13.2 + sha256: ac6cde5fba8d7d8c6ac963dbb0256a9854e9fafff52fbcc58fdf819357892c3e requires_dist: - aiohappyeyeballs>=2.5.0 - aiosignal>=1.4.0 @@ -1132,10 +1136,10 @@ packages: version: 3.4.4 sha256: a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894 requires_python: '>=3.7' -- pypi: https://files.pythonhosted.org/packages/7e/e8/64c37fadfc2816a7701fa8a6ed8d87327c7d54eacfbfb6edab14a2f2be75/cloudpickle-3.1.1-py3-none-any.whl +- pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl name: cloudpickle - version: 3.1.1 - sha256: c8c5a44295039331ee9dad40ba100a9c7297b6f988e50e87ccdf3765a668350e + version: 3.1.2 + sha256: 9acb47f6afd73f60dc1df93bb801b472f05ff42fa6c84167d25cb206be1fbf4a requires_python: '>=3.8' - pypi: https://files.pythonhosted.org/packages/af/02/18785edcdf6266cdd6c6dc7635f1cbeefd9a5b4c3bb8aff8bd681e9dd095/codecov-2.1.13-py2.py3-none-any.whl name: codecov @@ -1642,18 +1646,19 @@ packages: version: 1.4.9 sha256: b67e6efbf68e077dd71d1a6b37e43e1a99d0bff1a3d51867d45ee8908b931098 requires_python: '>=3.10' -- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.44-ha97dd6f_2.conda - sha256: 707dfb8d55d7a5c6f95c772d778ef07a7ca85417d9971796f7d3daad0b615de8 - md5: 14bae321b8127b63cba276bd53fac237 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.44-h1aa0949_4.conda + sha256: 96b6900ca0489d9e5d0318a6b49f8eff43fd85fef6e07cb0c25344ee94cd7a3a + md5: c94ab6ff54ba5172cf1c58267005670f depends: - __glibc >=2.17,<3.0.a0 + - zstd >=1.5.7,<1.6.0a0 constrains: - binutils_impl_linux-64 2.44 license: GPL-3.0-only license_family: GPL purls: [] - size: 747158 - timestamp: 1758810907507 + size: 742501 + timestamp: 1761335175964 - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.1-hecca717_0.conda sha256: da2080da8f0288b95dd86765c801c6e166c4619b910b11f9a8446fb852438dc2 md5: 4211416ecba1866fab0c6470986c22d6 @@ -1705,49 +1710,49 @@ packages: purls: [] size: 141322 timestamp: 1752719767870 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.6-h2dba641_1.conda - sha256: 764432d32db45466e87f10621db5b74363a9f847d2b8b1f9743746cd160f06ab - md5: ede4673863426c0883c0063d853bbd85 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h9ec8514_0.conda + sha256: 25cbdfa65580cfab1b8d15ee90b4c9f1e0d72128f1661449c9a999d341377d54 + md5: 35f29eec58405aaf55e01cb470d8c26a depends: - __glibc >=2.17,<3.0.a0 - - libgcc >=13 + - libgcc >=14 license: MIT license_family: MIT purls: [] - size: 57433 - timestamp: 1743434498161 -- conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.4.6-h281671d_1.conda - sha256: 6394b1bc67c64a21a5cc73d1736d1d4193a64515152e861785c44d2cfc49edf3 - md5: 4ca9ea59839a9ca8df84170fab4ceb41 + size: 57821 + timestamp: 1760295480630 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.5.2-h750e83c_0.conda + sha256: 277dc89950f5d97f1683f26e362d6dca3c2efa16cb2f6fdb73d109effa1cd3d0 + md5: d214916b24c625bcc459b245d509f22e depends: - __osx >=10.13 license: MIT license_family: MIT purls: [] - size: 51216 - timestamp: 1743434595269 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.4.6-h1da3d7d_1.conda - sha256: c6a530924a9b14e193ea9adfe92843de2a806d1b7dbfd341546ece9653129e60 - md5: c215a60c2935b517dcda8cad4705734d + size: 52573 + timestamp: 1760295626449 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-he5f378a_0.conda + sha256: 9b8acdf42df61b7bfe8bdc545c016c29e61985e79748c64ad66df47dbc2e295f + md5: 411ff7cd5d1472bba0f55c0faf04453b depends: - __osx >=11.0 license: MIT license_family: MIT purls: [] - size: 39839 - timestamp: 1743434670405 -- conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.4.6-h537db12_1.conda - sha256: d3b0b8812eab553d3464bbd68204f007f1ebadf96ce30eb0cbc5159f72e353f5 - md5: 85d8fa5e55ed8f93f874b3b23ed54ec6 + size: 40251 + timestamp: 1760295839166 +- conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.5.2-h52bdfb6_0.conda + sha256: ddff25aaa4f0aa535413f5d831b04073789522890a4d8626366e43ecde1534a3 + md5: ba4ad812d2afc22b9a34ce8327a0930f depends: - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 license: MIT license_family: MIT purls: [] - size: 44978 - timestamp: 1743435053850 + size: 44866 + timestamp: 1760295760649 - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-h767d61c_7.conda sha256: 08f9b87578ab981c7713e4e6a7d935e40766e10691732bba376d4964562bcb45 md5: c0374badb3a5d4b1372db28d19462c53 @@ -1905,6 +1910,19 @@ packages: purls: [] size: 1288499 timestamp: 1753948889360 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h8f9b012_7.conda + sha256: 1b981647d9775e1cdeb2fab0a4dd9cd75a6b0de2963f6c3953dbd712f78334b3 + md5: 5b767048b1b3ee9a954b06f4084f93dc + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc 15.2.0 h767d61c_7 + constrains: + - libstdcxx-ng ==15.2.0=*_7 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 3898269 + timestamp: 1759968103436 - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.2-he9a06e4_0.conda sha256: e5ec6d2ad7eef538ddcb9ea62ad4346fde70a4736342c4ad87bd713641eb9808 md5: 80c07c68d2f6870250959dcc95b209d1 @@ -2158,10 +2176,10 @@ packages: requires_dist: - typing-extensions>=4.1.0 ; python_full_version < '3.11' requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/13/34/00c7ae8194074ed82b64e0bb7c24220eac5f77ac90c16e23cf0d2cfd2a03/narwhals-2.9.0-py3-none-any.whl +- pypi: https://files.pythonhosted.org/packages/62/cd/9481a199a086ac9f91eaa232b56cff90ca7fdc2cb6658de93825b1007094/narwhals-2.10.1-py3-none-any.whl name: narwhals - version: 2.9.0 - sha256: c59f7de4763004ae81691ce16df71b4e55aead0ead7ccde8c8f2ef8c9559c765 + version: 2.10.1 + sha256: eed3d9ec8f821963456fef306c1ad11017995982169fca1f38f71c97d6a97b9b requires_dist: - cudf>=24.10.0 ; extra == 'cudf' - dask[dataframe]>=2024.8 ; extra == 'dask' @@ -2206,20 +2224,20 @@ packages: purls: [] size: 797030 timestamp: 1738196177597 -- pypi: https://files.pythonhosted.org/packages/11/0e/16b3886858b3953ef836dea25b951f3ab0c5b5a431da03f675c0e999afb8/nh3-0.3.1-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/42/0f/c76bf3dba22c73c38e9b1113b017cf163f7696f50e003404ec5ecdb1e8a6/nh3-0.3.2-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl name: nh3 - version: 0.3.1 - sha256: 94292dd1bd2a2e142fa5bb94c0ee1d84433a5d9034640710132da7e0376fca3a + version: 0.3.2 + sha256: 7bb18403f02b655a1bbe4e3a4696c2ae1d6ae8f5991f7cacb684b1ae27e6c9f7 requires_python: '>=3.8' -- pypi: https://files.pythonhosted.org/packages/a5/ca/263eb96b6d32c61a92c1e5480b7f599b60db7d7fbbc0d944be7532d0ac42/nh3-0.3.1-cp38-abi3-win_amd64.whl +- pypi: https://files.pythonhosted.org/packages/64/9a/1a1c154f10a575d20dd634e5697805e589bbdb7673a0ad00e8da90044ba7/nh3-0.3.2-cp38-abi3-win_amd64.whl name: nh3 - version: 0.3.1 - sha256: c0acef923a1c3a2df3ee5825ea79c149b6748c6449781c53ab6923dc75e87d26 + version: 0.3.2 + sha256: 562da3dca7a17f9077593214a9781a94b8d76de4f158f8c895e62f09573945fe requires_python: '>=3.8' -- pypi: https://files.pythonhosted.org/packages/e1/28/a387fed70438d2810c8ac866e7b24bf1a5b6f30ae65316dfe4de191afa52/nh3-0.3.1-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl +- pypi: https://files.pythonhosted.org/packages/b6/3e/f5a5cc2885c24be13e9b937441bd16a012ac34a657fe05e58927e8af8b7a/nh3-0.3.2-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl name: nh3 - version: 0.3.1 - sha256: 1de5c1a35bed19a1b1286bab3c3abfe42e990a8a6c4ce9bb9ab4bde49107ea3b + version: 0.3.2 + sha256: 7064ccf5ace75825bd7bf57859daaaf16ed28660c1c6b306b649a9eda4b54b1e requires_python: '>=3.8' - pypi: https://files.pythonhosted.org/packages/09/97/fd421e8bc50766665ad35536c2bb4ef916533ba1fdd053a62d96cc7c8b95/numpy-2.3.4-cp313-cp313-win_amd64.whl name: numpy @@ -3007,16 +3025,16 @@ packages: - pytest-xdist ; extra == 'testing' - virtualenv ; extra == 'testing' requires_python: '>=3.9' -- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.13.9-h2b335a9_100_cp313.conda - build_number: 100 - sha256: 317ee7a38f4cc97336a2aedf9c79e445adf11daa0d082422afa63babcd5117e4 - md5: 78ba5c3a7aecc68ab3a9f396d3b69d06 +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.13.9-hc97d973_101_cp313.conda + build_number: 101 + sha256: e89da062abd0d3e76c8d3b35d3cafc5f0d05914339dcb238f9e3675f2a58d883 + md5: 4780fe896e961722d0623fa91d0d3378 depends: - __glibc >=2.17,<3.0.a0 - bzip2 >=1.0.8,<2.0a0 - ld_impl_linux-64 >=2.36.1 - libexpat >=2.7.1,<3.0a0 - - libffi >=3.4.6,<3.5.0a0 + - libffi >=3.5.2,<3.6.0a0 - libgcc >=14 - liblzma >=5.8.1,<6.0a0 - libmpdec >=4.0.0,<5.0a0 @@ -3031,18 +3049,18 @@ packages: - tzdata license: Python-2.0 purls: [] - size: 37323303 - timestamp: 1760612239629 + size: 37174029 + timestamp: 1761178179147 python_site_packages_path: lib/python3.13/site-packages -- conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.13.9-h2bd861f_100_cp313.conda - build_number: 100 - sha256: c5ae352b7ac8412ed0e9ca8cac2f36d767e96d8e3efb014f47fd103be7447f22 - md5: 9f7e2b7871a35025f30a890492a36578 +- conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.13.9-h17c18a5_101_cp313.conda + build_number: 101 + sha256: b56484229cf83f6c84e8b138dc53f7f2fa9ee850f42bf1f6d6fa1c03c044c2d3 + md5: fb1e51574ce30d2a4d5e4facb9b2cbd5 depends: - __osx >=10.13 - bzip2 >=1.0.8,<2.0a0 - libexpat >=2.7.1,<3.0a0 - - libffi >=3.4.6,<3.5.0a0 + - libffi >=3.5.2,<3.6.0a0 - liblzma >=5.8.1,<6.0a0 - libmpdec >=4.0.0,<5.0a0 - libsqlite >=3.50.4,<4.0a0 @@ -3055,18 +3073,18 @@ packages: - tzdata license: Python-2.0 purls: [] - size: 17336745 - timestamp: 1760613619143 + size: 17521522 + timestamp: 1761177097697 python_site_packages_path: lib/python3.13/site-packages -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.13.9-h09175d0_100_cp313.conda - build_number: 100 - sha256: ba1121e96d034129832eff1bde7bba35f186acfc51fce1d7bacd29a544906f1b - md5: a2e4526d795a64fbd9581333482e07ee +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.13.9-hfc2f54d_101_cp313.conda + build_number: 101 + sha256: 516229f780b98783a5ef4112a5a4b5e5647d4f0177c4621e98aa60bb9bc32f98 + md5: a4241bce59eecc74d4d2396e108c93b8 depends: - __osx >=11.0 - bzip2 >=1.0.8,<2.0a0 - libexpat >=2.7.1,<3.0a0 - - libffi >=3.4.6,<3.5.0a0 + - libffi >=3.5.2,<3.6.0a0 - liblzma >=5.8.1,<6.0a0 - libmpdec >=4.0.0,<5.0a0 - libsqlite >=3.50.4,<4.0a0 @@ -3079,17 +3097,17 @@ packages: - tzdata license: Python-2.0 purls: [] - size: 12802912 - timestamp: 1760613485744 + size: 11915380 + timestamp: 1761176793936 python_site_packages_path: lib/python3.13/site-packages -- conda: https://conda.anaconda.org/conda-forge/win-64/python-3.13.9-hdf00ec1_100_cp313.conda - build_number: 100 - sha256: 2d6d9d5c641d4a11b5bef148813b83eef4e2dffd68e1033362bad85924837f29 - md5: 89c006f6748c7e0fc7950ae0c80df0d5 +- conda: https://conda.anaconda.org/conda-forge/win-64/python-3.13.9-h09917c8_101_cp313.conda + build_number: 101 + sha256: bc855b513197637c2083988d5cbdcc407a23151cdecff381bd677df33d516a01 + md5: 89d992b9d4b9e88ed54346c9c4a24c1c depends: - bzip2 >=1.0.8,<2.0a0 - libexpat >=2.7.1,<3.0a0 - - libffi >=3.4.6,<3.5.0a0 + - libffi >=3.5.2,<3.6.0a0 - liblzma >=5.8.1,<6.0a0 - libmpdec >=4.0.0,<5.0a0 - libsqlite >=3.50.4,<4.0a0 @@ -3103,8 +3121,8 @@ packages: - vc14_runtime >=14.44.35208 license: Python-2.0 purls: [] - size: 16503717 - timestamp: 1760610876821 + size: 16613183 + timestamp: 1761175050438 python_site_packages_path: Lib/site-packages - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl name: python-dateutil @@ -3124,10 +3142,10 @@ packages: - aiohttp>=3.4 ; extra == 'asyncio-client' - sphinx ; extra == 'docs' requires_python: '>=3.6' -- pypi: https://files.pythonhosted.org/packages/d7/5b/821733876bad200638237d1cab671b46cfdafb73c0b4094f59c5947155ae/python_socketio-5.14.2-py3-none-any.whl +- pypi: https://files.pythonhosted.org/packages/c0/1a/b393a06aa6f2f6ab4a9c5c160a62d488b17d6da5cf93a67bc13a6e3239cd/python_socketio-5.14.3-py3-none-any.whl name: python-socketio - version: 5.14.2 - sha256: d7133f040ac7ba540f9a907cb4c36d6c4d1d54eb35e482aad9d45c22fca10654 + version: 5.14.3 + sha256: a5208c1bbf45a8d6328d01ed67e3fa52ec8b186fd3ea44cfcfcbd120f0c71fbe requires_dist: - bidict>=0.21.0 - python-engineio>=4.11.0 @@ -3221,30 +3239,30 @@ packages: - pyright==1.1.394 ; extra == 'lint' - pytest>=8 ; extra == 'test' requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/02/88/0ee4ca507d4aa05f67e292d2e5eb0b3e358fbcfe527554a2eda9ac422d6b/ruff-0.14.1-py3-none-win_amd64.whl +- pypi: https://files.pythonhosted.org/packages/03/15/51960ae340823c9859fb60c63301d977308735403e2134e17d1d2858c7fb/ruff-0.14.3-py3-none-win_amd64.whl name: ruff - version: 0.14.1 - sha256: 59d599cdff9c7f925a017f6f2c256c908b094e55967f93f2821b1439928746a1 + version: 0.14.3 + sha256: d7b7006ac0756306db212fd37116cce2bd307e1e109375e1c6c106002df0ae5f requires_python: '>=3.7' -- pypi: https://files.pythonhosted.org/packages/c1/ea/fd9e95863124ed159cd0667ec98449ae461de94acda7101f1acb6066da00/ruff-0.14.1-py3-none-macosx_11_0_arm64.whl +- pypi: https://files.pythonhosted.org/packages/a7/e7/138b883f0dfe4ad5b76b58bf4ae675f4d2176ac2b24bdd81b4d966b28c61/ruff-0.14.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl name: ruff - version: 0.14.1 - sha256: d6191903d39ac156921398e9c86b7354d15e3c93772e7dbf26c9fcae59ceccd5 + version: 0.14.3 + sha256: 0e2f8a0bbcffcfd895df39c9a4ecd59bb80dca03dc43f7fb63e647ed176b741e requires_python: '>=3.7' -- pypi: https://files.pythonhosted.org/packages/e0/35/266a80d0eb97bd224b3265b9437bd89dde0dcf4faf299db1212e81824e7e/ruff-0.14.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/d3/c8/6724f4634c1daf52409fbf13fefda64aa9c8f81e44727a378b7b73dc590b/ruff-0.14.3-py3-none-macosx_10_12_x86_64.whl name: ruff - version: 0.14.1 - sha256: cabcaa9ccf8089fb4fdb78d17cc0e28241520f50f4c2e88cb6261ed083d85151 + version: 0.14.3 + sha256: b6fd8c79b457bedd2abf2702b9b472147cd860ed7855c73a5247fa55c9117654 requires_python: '>=3.7' -- pypi: https://files.pythonhosted.org/packages/ef/2e/1226961855ccd697255988f5a2474890ac7c5863b080b15bd038df820818/ruff-0.14.1-py3-none-macosx_10_12_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/de/03/db1bce591d55fd5f8a08bb02517fa0b5097b2ccabd4ea1ee29aa72b67d96/ruff-0.14.3-py3-none-macosx_11_0_arm64.whl name: ruff - version: 0.14.1 - sha256: f6fa757cd717f791009f7669fefb09121cc5f7d9bd0ef211371fad68c2b8b224 + version: 0.14.3 + sha256: 71ff6edca490c308f083156938c0c1a66907151263c4abdcb588602c6e696a14 requires_python: '>=3.7' -- pypi: https://files.pythonhosted.org/packages/88/3b/1815d8914c70257173ec307d3b7f8016c878a1542a195a18de25c63e2ec7/scipp-25.8.0-cp313-cp313-macosx_11_0_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/64/7c/d8a343b0a622987335a1ac848084079c47c21e44fcc450f9c145b11a56f6/scipp-25.11.0-cp313-cp313-macosx_11_0_arm64.whl name: scipp - version: 25.8.0 - sha256: ca7f360197bde23a21b757c9f6b92a204807927f465caf31452b4899714e2cae + version: 25.11.0 + sha256: 9b082fc7fd29919b4fee007f63db265176becb06c669a4b709feb741b76c612a requires_dist: - numpy>=1.20 - pytest ; extra == 'test' @@ -3267,10 +3285,10 @@ packages: - nodejs ; extra == 'all' - pythreejs ; extra == 'all' requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/9b/70/10c2358156874a645f5556c4bdcddd01cf10c9b73b15434e04512be5101b/scipp-25.8.0-cp313-cp313-macosx_11_0_arm64.whl +- pypi: https://files.pythonhosted.org/packages/71/f2/18d5be10ac890ce7490451eb55d41bf9d96e481751362a30ed1a8bc176fa/scipp-25.11.0-cp313-cp313-macosx_11_0_x86_64.whl name: scipp - version: 25.8.0 - sha256: 4b0df001f6fdcb697d64f50adfdc5dad1ba01ea30164ad22161d317072ad1c4f + version: 25.11.0 + sha256: fd7788e3ea3dd5334ed7fb53a249413469edc5d836ca5d68b1f271691cf11269 requires_dist: - numpy>=1.20 - pytest ; extra == 'test' @@ -3293,10 +3311,10 @@ packages: - nodejs ; extra == 'all' - pythreejs ; extra == 'all' requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/c3/cf/4c3853de982ba47f94493c90fb4bf0a2164ca5b48a769b4facd6c28c9f6b/scipp-25.8.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/77/34/1956aed61c4abb91926f9513330afac4654cc2a711ecb73085dc4e2e5c1d/scipp-25.11.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl name: scipp - version: 25.8.0 - sha256: cc9343a1369922197a2e43bc0ce2457639ec7e61b06ec5938db4decdee422188 + version: 25.11.0 + sha256: 3e91c8093dc83d433a2e53708561228a06a7e34d8775a20118d391f5b891a6e6 requires_dist: - numpy>=1.20 - pytest ; extra == 'test' @@ -3319,10 +3337,10 @@ packages: - nodejs ; extra == 'all' - pythreejs ; extra == 'all' requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/ca/3b/8d206694f1dfe8c6305d8c13d9d71fcb3962543b99d6ca8df76fcee5964d/scipp-25.8.0-cp313-cp313-win_amd64.whl +- pypi: https://files.pythonhosted.org/packages/f6/f3/9d1bb423a2dc0bbebfc98191095dd410a1268397b9c692d76a3ea971c790/scipp-25.11.0-cp313-cp313-win_amd64.whl name: scipp - version: 25.8.0 - sha256: 7b5934c188a4fadd857cc43e7befb061f7995a3c706bcee5e0013bdf20ce7c4a + version: 25.11.0 + sha256: d44d2aa3f6634ac750a126e50a740c487aa8a2181fcb03764b29ddceeea611cf requires_dist: - numpy>=1.20 - pytest ; extra == 'test' @@ -3345,10 +3363,10 @@ packages: - nodejs ; extra == 'all' - pythreejs ; extra == 'all' requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/32/a9/15c20d08e950b540184caa8ced675ba1128accb0e09c653780ba023a4110/scipy-1.16.2-cp313-cp313-macosx_12_0_arm64.whl +- pypi: https://files.pythonhosted.org/packages/21/f6/4bfb5695d8941e5c570a04d9fcd0d36bce7511b7d78e6e75c8f9791f82d0/scipy-1.16.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl name: scipy - version: 1.16.2 - sha256: 5c39026d12edc826a1ef2ad35ad1e6d7f087f934bb868fc43fa3049c8b8508f9 + version: 1.16.3 + sha256: 7dc1360c06535ea6116a2220f760ae572db9f661aba2d88074fe30ec2aa1ff88 requires_dist: - numpy>=1.25.2,<2.6 - pytest>=8.0.0 ; extra == 'test' @@ -3389,10 +3407,10 @@ packages: - doit>=0.36.0 ; extra == 'dev' - pydevtool ; extra == 'dev' requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/a1/57/0f38e396ad19e41b4c5db66130167eef8ee620a49bc7d0512e3bb67e0cab/scipy-1.16.2-cp313-cp313-win_amd64.whl +- pypi: https://files.pythonhosted.org/packages/44/13/7e63cfba8a7452eb756306aa2fd9b37a29a323b672b964b4fdeded9a3f21/scipy-1.16.3-cp313-cp313-macosx_12_0_arm64.whl name: scipy - version: 1.16.2 - sha256: fda714cf45ba43c9d3bae8f2585c777f64e3f89a2e073b668b32ede412d8f52c + version: 1.16.3 + sha256: 16b8bc35a4cc24db80a0ec836a9286d0e31b2503cb2fd7ff7fb0e0374a97081d requires_dist: - numpy>=1.25.2,<2.6 - pytest>=8.0.0 ; extra == 'test' @@ -3433,10 +3451,10 @@ packages: - doit>=0.36.0 ; extra == 'dev' - pydevtool ; extra == 'dev' requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/c1/27/c5b52f1ee81727a9fc457f5ac1e9bf3d6eab311805ea615c83c27ba06400/scipy-1.16.2-cp313-cp313-macosx_10_14_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/72/f1/57e8327ab1508272029e27eeef34f2302ffc156b69e7e233e906c2a5c379/scipy-1.16.3-cp313-cp313-macosx_10_14_x86_64.whl name: scipy - version: 1.16.2 - sha256: 84f7bf944b43e20b8a894f5fe593976926744f6c185bacfcbdfbb62736b5cc70 + version: 1.16.3 + sha256: d2ec56337675e61b312179a1ad124f5f570c00f920cc75e1000025451b88241c requires_dist: - numpy>=1.25.2,<2.6 - pytest>=8.0.0 ; extra == 'test' @@ -3477,10 +3495,10 @@ packages: - doit>=0.36.0 ; extra == 'dev' - pydevtool ; extra == 'dev' requires_python: '>=3.11' -- pypi: https://files.pythonhosted.org/packages/da/6a/1a927b14ddc7714111ea51f4e568203b2bb6ed59bdd036d62127c1a360c8/scipy-1.16.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl +- pypi: https://files.pythonhosted.org/packages/cd/01/1204382461fcbfeb05b6161b594f4007e78b6eba9b375382f79153172b4d/scipy-1.16.3-cp313-cp313-win_amd64.whl name: scipy - version: 1.16.2 - sha256: c2275ff105e508942f99d4e3bc56b6ef5e4b3c0af970386ca56b777608ce95b7 + version: 1.16.3 + sha256: 062246acacbe9f8210de8e751b16fc37458213f124bef161a5a02c7a39284304 requires_dist: - numpy>=1.25.2,<2.6 - pytest>=8.0.0 ; extra == 'test' @@ -3863,10 +3881,10 @@ packages: version: 0.10.2 sha256: 806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b requires_python: '>=2.6,!=3.0.*,!=3.1.*,!=3.2.*' -- pypi: https://files.pythonhosted.org/packages/3e/84/1691aae773dccff72c866ad19af7adb12d4fb8b439c8bfb36ffc429c8c27/tox-4.31.0-py3-none-any.whl +- pypi: https://files.pythonhosted.org/packages/fc/cc/e09c0d663a004945f82beecd4f147053567910479314e8d01ba71e5d5dea/tox-4.32.0-py3-none-any.whl name: tox - version: 4.31.0 - sha256: 328f392e6567e46cb0f9b625679456744dde940287dd1b39117627dc4b21d5da + version: 4.32.0 + sha256: 451e81dc02ba8d1ed20efd52ee409641ae4b5d5830e008af10fe8823ef1bd551 requires_dist: - cachetools>=6.2 - chardet>=5.2 @@ -3880,10 +3898,10 @@ packages: - typing-extensions>=4.15 ; python_full_version < '3.11' - virtualenv>=20.34 requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/40/17/3dd6f646da0c2b5f47950f6a8259082f0e5de1a6a2f2d8e91dae6ff8efb0/tox_gh_actions-3.4.0-py3-none-any.whl +- pypi: https://files.pythonhosted.org/packages/fd/9e/8d50f3b3fc4af8c73154f64d4a2293bfa2d517a19000e70ef2d614254084/tox_gh_actions-3.5.0-py3-none-any.whl name: tox-gh-actions - version: 3.4.0 - sha256: 31abb90827472181c17ed07385493e4614fd8c03955e43fef42c06a366712850 + version: 3.5.0 + sha256: 070790114c92f4c94337047515ca5e077ceb269a5cb9366e0a0b3440a024eca1 requires_dist: - tox>=4,<5 - devpi-process ; extra == 'testing' @@ -3988,10 +4006,10 @@ packages: purls: [] size: 114846 timestamp: 1760418593847 -- pypi: https://files.pythonhosted.org/packages/27/73/d9a94da0e9d470a543c1b9d3ccbceb0f59455983088e727b8a1824ed90fb/virtualenv-20.35.3-py3-none-any.whl +- pypi: https://files.pythonhosted.org/packages/79/0c/c05523fa3181fdf0c9c52a6ba91a23fbf3246cc095f26f6516f9c60e6771/virtualenv-20.35.4-py3-none-any.whl name: virtualenv - version: 20.35.3 - sha256: 63d106565078d8c8d0b206d48080f938a8b25361e19432d2c9db40d2899c810a + version: 20.35.4 + sha256: c21c9cede36c9753eeade68ba7d523529f228a403463376cf821eaae2b650f1b requires_dist: - distlib>=0.3.7,<1 - filelock>=3.12.2,<4 @@ -4061,3 +4079,16 @@ packages: - multidict>=4.0 - propcache>=0.2.1 requires_python: '>=3.9' +- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb8e6e7a_2.conda + sha256: a4166e3d8ff4e35932510aaff7aa90772f84b4d07e9f6f83c614cba7ceefe0eb + md5: 6432cb5d4ac0046c3ac0a8a0f95842f9 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - libstdcxx >=13 + - libzlib >=1.3.1,<2.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 567578 + timestamp: 1742433379869 diff --git a/src/easyscience/global_object/map.py b/src/easyscience/global_object/map.py index 53a3aac4..0088862d 100644 --- a/src/easyscience/global_object/map.py +++ b/src/easyscience/global_object/map.py @@ -24,10 +24,10 @@ def __repr__(self) -> str: s += ', '.join(self._type) else: s += 'Undefined' - s += '. With' if self.finalizer is None: - s += 'out' - s += 'a finalizer.' + s += '. Without a finalizer.' + else: + s += '. With a finalizer.' return s def __delitem__(self, key): diff --git a/tests/unit_tests/fitting/calculators/__init__.py b/tests/unit_tests/fitting/calculators/__init__.py new file mode 100644 index 00000000..867a21c4 --- /dev/null +++ b/tests/unit_tests/fitting/calculators/__init__.py @@ -0,0 +1,4 @@ +# SPDX-FileCopyrightText: 2025 EasyScience contributors +# SPDX-License-Identifier: BSD-3-Clause +# © 2021-2025 Contributors to the EasyScience project +# SPDX-License-Identifier: BSD-3-Clause +# © 2021-2025 Contributors to the EasyScience project +# SPDX-License-Identifier: BSD-3-Clause +# © 2021-2025 Contributors to the EasyScience project +# SPDX-License-Identifier: BSD-3-Clause +# © 2021-2025 Contributors to the EasyScience project sub_container -> parameter + param = Parameter(name="value", value=42.0) + sub_container = ObjBase(name="sub", value=param) + main_container = ObjBase(name="main", sub=sub_container) + + # When - Find path from main to parameter + path = global_obj.map.find_path( + main_container.unique_name, + param.unique_name + ) + + # Then - Should find the path through the hierarchy + assert len(path) >= 2 + assert path[0] == main_container.unique_name + assert path[-1] == param.unique_name + + # When - Find reverse path + reverse_path = global_obj.map.reverse_route( + param.unique_name, + main_container.unique_name + ) + + # Then - Should be the reverse + assert reverse_path[0] == param.unique_name + assert reverse_path[-1] == main_container.unique_name + + def test_map_connectivity_with_isolated_objects(self, clear_all): + """Test map connectivity detection""" + # Given + global_obj = GlobalObject() + + # When - Create connected objects + param1 = Parameter(name="connected1", value=1.0) + param2 = Parameter(name="connected2", value=2.0) + container = ObjBase(name="container", p1=param1, p2=param2) + + # Then - Map should be connected + # TODO: Depending on implementation, connectivity might vary + # assert global_obj.map.is_connected() + + # When - Create isolated object + isolated = Parameter(name="isolated", value=99.0) + # Remove its automatic connection by clearing edges + # (In real usage, isolated objects would be rare) + + # Then - Map might still be connected depending on implementation + # This tests the connectivity algorithm + connectivity = global_obj.map.is_connected() + assert isinstance(connectivity, bool) + + def test_error_handling_integration(self, clear_all): + """Test error handling across the global object system""" + # Given + global_obj = GlobalObject() + + # When - Try to get non-existent object + with pytest.raises(ValueError, match="Item not in map"): + global_obj.map.get_item_by_key("non_existent") + + # When - Try to add object with duplicate name + param1 = Parameter(name="test", value=1.0) + param1_name = param1.unique_name + + # Create another with same unique name (should fail in add_vertex) + with pytest.raises(ValueError, match="already exists"): + # This simulates what would happen if we tried to add duplicate + global_obj.map.add_vertex(param1) # param1 already added during creation + + def test_memory_pressure_simulation(self, clear_all): + """Test system behavior under memory pressure""" + # Given + global_obj = GlobalObject() + + # When - Create many objects + objects = [] + for i in range(100): + param = Parameter(name=f"param_{i}", value=float(i)) + obj = ObjBase(name=f"obj_{i}", param=param) + objects.append((param, obj)) + + initial_vertex_count = len(global_obj.map.vertices()) + assert initial_vertex_count == 200 # 100 params + 100 objs + + # When - Delete half the objects + objects_to_delete = [objects[i] for i in range(0, 100, 2)] + for item in objects_to_delete: + objects.remove(item) + del item + + # Force garbage collection + gc.collect() + + # Then - Map should have fewer vertices + current_vertex_count = len(global_obj.map.vertices()) + assert current_vertex_count <= initial_vertex_count + + # When - Delete all remaining objects + del objects + gc.collect() + + # Then - Map should be mostly empty (might have some remaining references) + final_vertex_count = len(global_obj.map.vertices()) + assert final_vertex_count < initial_vertex_count + + def test_serialization_integration_with_global_state(self, clear_all): + """Test serialization integration with global state management""" + # Given + global_obj = GlobalObject() + + # Create objects + param = Parameter(name="test_param", value=123.45, unit="kg") + obj = ObjBase(name="test_obj", param=param) + + original_vertex_count = len(global_obj.map.vertices()) + + # When - Serialize objects + param_dict = param.as_dict() + obj_dict = obj.as_dict() + + # Clear global state + global_obj.map._clear() + assert len(global_obj.map.vertices()) == 0 + + # When - Deserialize objects + new_param = Parameter.from_dict(param_dict) + _ = obj_dict['param'].pop('unique_name') # Avoid duplicate name error + new_obj = ObjBase.from_dict(obj_dict) + + # Then - Should be registered in global map again + assert len(global_obj.map.vertices()) >= 2 + assert global_obj.map.is_known(new_param) + assert global_obj.map.is_known(new_obj) + + # Objects should be functionally equivalent + assert new_param.name == param.name + assert new_param.value == param.value + assert new_param.unit == param.unit + + def test_debug_mode_integration(self, clear_all): + """Test debug mode behavior across the system""" + # Given + global_obj = GlobalObject() + original_debug = global_obj.debug + + try: + # When - Enable debug mode + global_obj.debug = True + + if not global_obj.stack: + global_obj.instantiate_stack() + global_obj.stack.enabled = True + + # Create and modify objects + param = Parameter(name="debug_test", value=1.0) + + # This should trigger debug output in property_stack decorator + with patch('builtins.print') as mock_print: + param.value = 2.0 + + # Should have printed debug info (if debug mode works) + # Note: This depends on the debug implementation details + + # Test that operations still work normally + assert param.value == 2.0 + assert global_obj.stack.canUndo() + + finally: + # Restore original debug state + global_obj.debug = original_debug + + def test_concurrent_access_simulation(self, clear_all): + """Simulate concurrent access patterns""" + import threading + import time + + # Given + global_obj = GlobalObject() + results = [] + errors = [] + + def create_objects(thread_id, count=10): + """Create objects in a thread""" + try: + for i in range(count): + param = Parameter(name=f"thread_{thread_id}_param_{i}", value=float(i)) + results.append(param.unique_name) + time.sleep(0.001) # Small delay to encourage race conditions + except Exception as e: + errors.append(f"Thread {thread_id}: {e}") + + # When - Create objects concurrently + threads = [] + for thread_id in range(3): + thread = threading.Thread(target=create_objects, args=(thread_id, 5)) + threads.append(thread) + + for thread in threads: + thread.start() + + for thread in threads: + thread.join() + + # Then - Should not have errors and all objects should be created + assert len(errors) == 0, f"Errors occurred: {errors}" + assert len(results) == 15 # 3 threads * 5 objects each + assert len(set(results)) == 15 # All unique names should be unique + + # All objects should be in the map + for unique_name in results: + assert unique_name in global_obj.map.vertices() \ No newline at end of file diff --git a/tests/unit_tests/global_object/test_map.py b/tests/unit_tests/global_object/test_map.py index df344aed..05eec1a8 100644 --- a/tests/unit_tests/global_object/test_map.py +++ b/tests/unit_tests/global_object/test_map.py @@ -6,7 +6,127 @@ from easyscience import ObjBase import pytest import gc +import weakref +import numpy as np +from unittest.mock import MagicMock, patch from easyscience import global_object +from easyscience.global_object.map import _EntryList, Map + +class TestEntryList: + """Test the _EntryList helper class""" + + def test_init_default(self): + """Test _EntryList initialization with defaults""" + entry = _EntryList() + assert entry._type == [] + assert entry.finalizer is None + + def test_init_with_known_type(self): + """Test _EntryList initialization with known type""" + entry = _EntryList(my_type='created') + assert 'created' in entry._type + + def test_init_with_unknown_type(self): + """Test _EntryList initialization with unknown type""" + entry = _EntryList(my_type='unknown') + assert entry._type == [] + + def test_repr(self): + """Test string representation""" + entry = _EntryList() + repr_str = str(entry) + assert 'Undefined' in repr_str + assert 'finalizer' in repr_str + + entry.type = 'created' + repr_str = str(entry) + assert 'created' in repr_str + assert 'finalizer' in repr_str + + def test_type_property_getter(self): + """Test type property getter""" + entry = _EntryList() + assert entry.type == [] + + def test_type_property_setter_valid(self): + """Test type property setter with valid types""" + entry = _EntryList() + entry.type = 'created' + assert 'created' in entry.type + + entry.type = 'argument' + assert 'argument' in entry.type + assert 'created' in entry.type # Should be additive + + def test_type_property_setter_invalid(self): + """Test type property setter with invalid type""" + entry = _EntryList() + entry.type = 'invalid' + assert entry.type == [] + + def test_type_property_setter_duplicate(self): + """Test type property setter doesn't add duplicates""" + entry = _EntryList() + entry.type = 'created' + entry.type = 'created' # Try to add again + assert entry.type.count('created') == 1 + + def test_remove_type(self): + """Test removing a type""" + entry = _EntryList() + entry.type = 'created' + entry.type = 'argument' + + entry.remove_type('created') + assert 'created' not in entry.type + assert 'argument' in entry.type + + def test_remove_type_not_present(self): + """Test removing a type that's not present""" + entry = _EntryList() + entry.type = 'created' + entry.remove_type('argument') # Not present + assert 'created' in entry.type + + def test_reset_type(self): + """Test resetting types""" + entry = _EntryList() + entry.type = 'created' + entry.type = 'argument' + + entry.reset_type('returned') + assert entry.type == ['returned'] + + def test_reset_type_default_none(self): + """Test resetting types with no default""" + entry = _EntryList() + entry.type = 'created' + + entry.reset_type() + assert entry.type == [] + + def test_boolean_properties(self): + """Test boolean property helpers""" + entry = _EntryList() + + # Test all false initially + assert not entry.is_argument + assert not entry.is_created + assert not entry.is_created_internal + assert not entry.is_returned + + # Test each property + entry.type = 'argument' + assert entry.is_argument + + entry.type = 'created' + assert entry.is_created + + entry.type = 'created_internal' + assert entry.is_created_internal + + entry.type = 'returned' + assert entry.is_returned class TestMap: @pytest.fixture @@ -19,7 +139,7 @@ def base_object(self): @pytest.fixture def parameter_object(self): - return Parameter(value=2.0, name="test2") + return Parameter(name="test2", value=2) def test_add_vertex(self, clear, base_object, parameter_object): # When Then Expect @@ -78,3 +198,289 @@ def test_unique_name_change_still_in_map(self, clear, base_object, parameter_obj assert global_object.map.get_item_by_key("test3") == base_object assert global_object.map.get_item_by_key("test4") == parameter_object + def test_add_vertex_duplicate_name_error(self, clear, base_object): + """Test that adding vertex with duplicate name raises error""" + # When/Then + with pytest.raises(ValueError, match="already exists"): + # Try to add another object with same unique_name + duplicate_obj = ObjBase(name="duplicate", unique_name=base_object.unique_name) + + def test_add_vertex_with_object_type(self, clear): + """Test adding vertex with specific object type""" + # Given + obj = ObjBase(name="test") + + # When - Object is automatically added during construction + # Then + assert global_object.map.is_known(obj) + assert 'created' in global_object.map.find_type(obj) + + def test_is_known_object(self, clear, base_object): + """Test is_known method""" + # When/Then + assert global_object.map.is_known(base_object) is True + + # Test with unknown object + unknown_obj = MagicMock() + unknown_obj.unique_name = "unknown" + assert global_object.map.is_known(unknown_obj) is False + + def test_find_type_known_object(self, clear, base_object): + """Test find_type method""" + # When/Then + types = global_object.map.find_type(base_object) + assert isinstance(types, list) + assert 'created' in types + + def test_find_type_unknown_object(self, clear): + """Test find_type with unknown object""" + # Given + unknown_obj = MagicMock() + unknown_obj.unique_name = "unknown" + + # When/Then + result = global_object.map.find_type(unknown_obj) + assert result is None + + def test_reset_type(self, clear, base_object): + """Test resetting object type""" + # Given + original_types = global_object.map.find_type(base_object) + + # When + global_object.map.reset_type(base_object, 'argument') + + # Then + new_types = global_object.map.find_type(base_object) + assert new_types == ['argument'] + assert new_types != original_types + + def test_change_type(self, clear, base_object): + """Test changing object type""" + # Given + original_types = global_object.map.find_type(base_object) + original_count = len(original_types) + + # When + global_object.map.change_type(base_object, 'argument') + + # Then + new_types = global_object.map.find_type(base_object) + assert 'argument' in new_types + assert len(new_types) >= original_count # Should be at least the same or more + + def test_add_edge(self, clear, base_object, parameter_object): + """Test adding edges between objects""" + # When + global_object.map.add_edge(base_object, parameter_object) + + # Then + edges = global_object.map.get_edges(base_object) + assert parameter_object.unique_name in edges + + def test_add_edge_unknown_start_object(self, clear, parameter_object): + """Test adding edge with unknown start object""" + # Given + unknown_obj = MagicMock() + unknown_obj.unique_name = "unknown" + + # When/Then + with pytest.raises(AttributeError, match="Start object not in map"): + global_object.map.add_edge(unknown_obj, parameter_object) + + def test_get_edges(self, clear, base_object, parameter_object): + """Test getting edges for an object""" + # Given + global_object.map.add_edge(base_object, parameter_object) + + # When + edges = global_object.map.get_edges(base_object) + + # Then + assert isinstance(edges, list) + assert parameter_object.unique_name in edges + + def test_get_edges_unknown_object(self, clear): + """Test getting edges for unknown object""" + # Given + unknown_obj = MagicMock() + unknown_obj.unique_name = "unknown" + + # When/Then + with pytest.raises(AttributeError): + global_object.map.get_edges(unknown_obj) + + def test_prune_vertex_from_edge(self, clear, base_object, parameter_object): + """Test removing edge between objects""" + # Given + global_object.map.add_edge(base_object, parameter_object) + assert parameter_object.unique_name in global_object.map.get_edges(base_object) + + # When + global_object.map.prune_vertex_from_edge(base_object, parameter_object) + + # Then + edges = global_object.map.get_edges(base_object) + assert parameter_object.unique_name not in edges + + def test_prune_vertex_from_edge_none_child(self, clear, base_object): + """Test pruning edge with None child""" + # When/Then - Should not raise error + global_object.map.prune_vertex_from_edge(base_object, None) + + def test_prune_vertex(self, clear, base_object): + """Test pruning a vertex completely""" + # Given + unique_name = base_object.unique_name + assert global_object.map.is_known(base_object) + + # When + global_object.map.prune(unique_name) + + # Then + assert not global_object.map.is_known(base_object) + assert unique_name not in global_object.map.vertices() + + def test_edges_generation(self, clear, base_object, parameter_object): + """Test edge generation""" + # Given + global_object.map.add_edge(base_object, parameter_object) + + # When + edges = global_object.map.edges() + + # Then + assert isinstance(edges, list) + expected_edge = {base_object.unique_name, parameter_object.unique_name} + assert expected_edge in edges + + def test_type_filtering_properties(self, clear): + """Test type filtering properties""" + # Given + obj1 = ObjBase(name="obj1") # 'created' type + obj2 = Parameter(name="obj2", value=1) # 'created' type + + global_object.map.change_type(obj1, 'argument') + global_object.map.change_type(obj2, 'returned') + + # When/Then + argument_objs = global_object.map.argument_objs + created_objs = global_object.map.created_objs + returned_objs = global_object.map.returned_objs + + assert obj1.unique_name in argument_objs + assert obj1.unique_name in created_objs # Should still be there + assert obj2.unique_name in created_objs + assert obj2.unique_name in returned_objs + + def test_find_path_simple(self, clear, base_object, parameter_object): + """Test finding path between objects""" + # Given + global_object.map.add_edge(base_object, parameter_object) + + # When + path = global_object.map.find_path(base_object.unique_name, parameter_object.unique_name) + + # Then + assert path == [base_object.unique_name, parameter_object.unique_name] + + def test_find_path_same_vertex(self, clear, base_object): + """Test finding path to same vertex""" + # When + path = global_object.map.find_path(base_object.unique_name, base_object.unique_name) + + # Then + assert path == [base_object.unique_name] + + def test_find_path_no_path(self, clear, base_object, parameter_object): + """Test finding path when no path exists""" + # When - No edge added + path = global_object.map.find_path(base_object.unique_name, parameter_object.unique_name) + + # Then + assert path == [] + + def test_find_all_paths(self, clear, base_object, parameter_object): + """Test finding all paths between objects""" + # Given + global_object.map.add_edge(base_object, parameter_object) + + # When + paths = global_object.map.find_all_paths(base_object.unique_name, parameter_object.unique_name) + + # Then + assert len(paths) == 1 + assert paths[0] == [base_object.unique_name, parameter_object.unique_name] + + def test_reverse_route_with_start(self, clear, base_object, parameter_object): + """Test reverse route with specified start""" + # Given + global_object.map.add_edge(base_object, parameter_object) + + # When + route = global_object.map.reverse_route(parameter_object.unique_name, base_object.unique_name) + + # Then + assert route == [parameter_object.unique_name, base_object.unique_name] + + def test_reverse_route_without_start(self, clear, base_object, parameter_object): + """Test reverse route without specified start""" + # Given + global_object.map.add_edge(base_object, parameter_object) + + # When + route = global_object.map.reverse_route(parameter_object.unique_name) + + # Then + assert len(route) >= 1 + assert route[0] == parameter_object.unique_name + + def test_is_connected_single_vertex(self, clear, base_object): + """Test connectivity with single vertex""" + # When/Then + assert global_object.map.is_connected() is True + + def test_is_connected_multiple_vertices(self, clear, base_object, parameter_object): + """Test connectivity with multiple connected vertices""" + # Given + global_object.map.add_edge(base_object, parameter_object) + + # When/Then + assert global_object.map.is_connected() is True + + def test_map_repr(self, clear, base_object, parameter_object): + """Test map string representation""" + # When + repr_str = str(global_object.map) + + # Then + assert "Map object" in repr_str + assert "2" in repr_str # Should show vertex count + + def test_get_item_by_key_not_found(self, clear): + """Test getting item by non-existent key""" + # When/Then + with pytest.raises(ValueError, match="Item not in map"): + global_object.map.get_item_by_key("non_existent") + + def test_clear_with_finalizers(self, clear): + """Test clearing map properly calls finalizers""" + # Given + obj = ObjBase(name="test") + original_count = len(global_object.map.vertices()) + + # When + global_object.map._clear() + + # Then + assert len(global_object.map.vertices()) == 0 + + def test_map_initialization(self): + """Test Map initialization""" + # When + test_map = Map() + + # Then + assert len(test_map.vertices()) == 0 + assert test_map.edges() == [] + diff --git a/tests/unit_tests/global_object/test_undo_redo_comprehensive.py b/tests/unit_tests/global_object/test_undo_redo_comprehensive.py new file mode 100644 index 00000000..67d0df5b --- /dev/null +++ b/tests/unit_tests/global_object/test_undo_redo_comprehensive.py @@ -0,0 +1,686 @@ +# SPDX-FileCopyrightText: 2025 EasyScience contributors +# SPDX-License-Identifier: BSD-3-Clause +# © 2021-2025 Contributors to the EasyScience project Any: + return self._convert_to_dict(obj, skip=skip, **kwargs) + + @classmethod + def decode(cls, obj: Any) -> Any: + return cls._convert_from_dict(obj) + + +class TestSerializerBase: + + @pytest.fixture + def clear(self): + """Clear everything before and after each test""" + global_object.map._clear() + if global_object.stack: + global_object.stack.clear() + yield + global_object.map._clear() + if global_object.stack: + global_object.stack.clear() + + @pytest.fixture + def serializer(self): + return ConcreteSerializer() + + @pytest.fixture + def mock_obj(self): + return MockSerializerComponent("test_obj", 42, "optional_value") + + def test_abstract_methods_are_placeholders(self): + """Test that SerializerBase can be instantiated but abstract methods just pass""" + # SerializerBase can actually be instantiated (abstract methods just pass) + base = SerializerBase() + + # Abstract methods don't raise exceptions - they just pass/return None + result = base.encode(Mock()) + assert result is None + + result = SerializerBase.decode({}) + assert result is None + + def test_get_arg_spec(self): + """Test get_arg_spec static method""" + def example_func(self, arg1, arg2, arg3="default"): + pass + + spec, args = SerializerBase.get_arg_spec(example_func) + + assert args == ['arg1', 'arg2', 'arg3'] + assert hasattr(spec, 'args') + assert hasattr(spec, 'defaults') + + def test_encode_objs_datetime(self): + """Test _encode_objs with datetime objects""" + dt = datetime.datetime(2023, 10, 17, 14, 30, 45, 123456) + result = SerializerBase._encode_objs(dt) + + expected = { + '@module': 'datetime', + '@class': 'datetime', + 'string': '2023-10-17 14:30:45.123456' + } + assert result == expected + + def test_encode_objs_numpy_array_real(self): + """Test _encode_objs with real numpy arrays""" + arr = np.array([1, 2, 3], dtype=np.int32) + result = SerializerBase._encode_objs(arr) + + expected = { + '@module': 'numpy', + '@class': 'array', + 'dtype': 'int32', + 'data': [1, 2, 3] + } + assert result == expected + + def test_encode_objs_numpy_array_complex(self): + """Test _encode_objs with complex numpy arrays""" + arr = np.array([1+2j, 3+4j], dtype=np.complex128) + result = SerializerBase._encode_objs(arr) + + expected = { + '@module': 'numpy', + '@class': 'array', + 'dtype': 'complex128', + 'data': [[1.0, 3.0], [2.0, 4.0]] # [real, imag] + } + assert result == expected + + def test_encode_objs_numpy_scalar(self): + """Test _encode_objs with numpy scalars""" + scalar = np.int32(42) + result = SerializerBase._encode_objs(scalar) + + assert result == 42 + assert isinstance(result, int) + + def test_encode_objs_json_serializable(self): + """Test _encode_objs with JSON serializable objects""" + # Should return the object unchanged if it's JSON serializable + data = {"key": "value", "number": 42} + result = SerializerBase._encode_objs(data) + assert result == data + + def test_encode_objs_non_serializable(self): + """Test _encode_objs with non-serializable objects""" + class NonSerializable: + def __init__(self): + self.value = "test" + + obj = NonSerializable() + result = SerializerBase._encode_objs(obj) + # Should return the object unchanged if not serializable + assert result is obj + + def test_convert_from_dict_datetime(self): + """Test _convert_from_dict with datetime objects""" + dt_dict = { + '@module': 'datetime', + '@class': 'datetime', + 'string': '2023-10-17 14:30:45.123456' + } + + result = SerializerBase._convert_from_dict(dt_dict) + expected = datetime.datetime(2023, 10, 17, 14, 30, 45, 123456) + assert result == expected + + def test_convert_from_dict_datetime_no_microseconds(self): + """Test _convert_from_dict with datetime without microseconds""" + dt_dict = { + '@module': 'datetime', + '@class': 'datetime', + 'string': '2023-10-17 14:30:45' + } + + result = SerializerBase._convert_from_dict(dt_dict) + expected = datetime.datetime(2023, 10, 17, 14, 30, 45) + assert result == expected + + def test_convert_from_dict_numpy_array_real(self): + """Test _convert_from_dict with real numpy arrays""" + arr_dict = { + '@module': 'numpy', + '@class': 'array', + 'dtype': 'int32', + 'data': [1, 2, 3] + } + + result = SerializerBase._convert_from_dict(arr_dict) + expected = np.array([1, 2, 3], dtype=np.int32) + np.testing.assert_array_equal(result, expected) + assert result.dtype == expected.dtype + + def test_convert_from_dict_numpy_array_complex(self): + """Test _convert_from_dict with complex numpy arrays""" + arr_dict = { + '@module': 'numpy', + '@class': 'array', + 'dtype': 'complex128', + 'data': [[1.0, 3.0], [2.0, 4.0]] + } + + result = SerializerBase._convert_from_dict(arr_dict) + expected = np.array([1+2j, 3+4j], dtype=np.complex128) + np.testing.assert_array_equal(result, expected) + assert result.dtype == expected.dtype + + def test_convert_from_dict_easyscience_object(self, clear): + """Test _convert_from_dict with EasyScience objects""" + param_dict = { + '@module': 'easyscience.variable.parameter', + '@class': 'Parameter', + '@version': '0.6.0', + 'name': 'test_param', + 'value': 5.0, + 'unit': 'm', + 'variance': 0.1, + 'min': 0.0, + 'max': 10.0, + 'fixed': False, + 'url': '', + 'description': '', + 'display_name': 'test_param' + } + + result = SerializerBase._convert_from_dict(param_dict) + assert isinstance(result, Parameter) + assert result.name == 'test_param' + assert result.value == 5.0 + assert str(result.unit) == 'm' + + def test_convert_from_dict_list(self): + """Test _convert_from_dict with lists""" + data = [ + {'@module': 'datetime', '@class': 'datetime', 'string': '2023-10-17 14:30:45'}, + {'key': 'value'}, + 42 + ] + + result = SerializerBase._convert_from_dict(data) + assert isinstance(result, list) + assert len(result) == 3 + assert isinstance(result[0], datetime.datetime) + assert result[1] == {'key': 'value'} + assert result[2] == 42 + + def test_convert_from_dict_regular_dict(self): + """Test _convert_from_dict with regular dictionaries""" + data = {'key': 'value', 'number': 42} + result = SerializerBase._convert_from_dict(data) + assert result == data + + def test_convert_to_dict_basic(self, serializer, mock_obj, clear): + """Test _convert_to_dict with basic object""" + result = serializer._convert_to_dict(mock_obj) + + assert '@module' in result + assert '@class' in result + assert '@version' in result + assert result['name'] == 'test_obj' + assert result['value'] == 42 + assert result['optional_param'] == 'optional_value' + assert result['unique_name'] == 'mock_test_obj' + + def test_convert_to_dict_with_skip(self, serializer, mock_obj, clear): + """Test _convert_to_dict with skip parameter""" + result = serializer._convert_to_dict(mock_obj, skip=['value', 'optional_param']) + + assert 'name' in result + assert 'value' not in result + assert 'optional_param' not in result + + def test_convert_to_dict_with_redirect(self, serializer, clear): + """Test _convert_to_dict with _REDIRECT""" + obj = MockSerializerWithRedirect("redirect_test", 10) + result = serializer._convert_to_dict(obj) + + assert result['special_attr'] == 20 # 10 * 2 from redirect + assert 'none_attr' not in result # Should be skipped due to None redirect + + def test_convert_to_dict_with_custom_convert_to_dict(self, serializer, clear): + """Test _convert_to_dict with custom _convert_to_dict method""" + obj = MockSerializerWithConvertToDict("custom_test", 5) + result = serializer._convert_to_dict(obj) + + assert result['custom_field'] == 'added_by_convert_to_dict' + assert result['name'] == 'custom_test' + assert result['value'] == 5 + + def test_convert_to_dict_with_enum_object(self, serializer, clear): + """Test _convert_to_dict when the object itself is an enum""" + + # Test that enum values in objects remain as enums without full_encode + class MockObjWithEnum(SerializerComponent): + def __init__(self, name: str, enum_val: TestEnum): + self.name = name + self.enum_val = enum_val + self.unique_name = f"obj_{name}" + self._global_object = True + + obj = MockObjWithEnum("test", TestEnum.TEST_VALUE) + result = serializer._convert_to_dict(obj) + + # The enum field should remain as an enum object (not encoded as dict) + assert isinstance(result['enum_val'], TestEnum) + assert result['enum_val'] == TestEnum.TEST_VALUE + + def test_convert_to_dict_full_encode(self, serializer, clear): + """Test _convert_to_dict with full_encode=True""" + dt = datetime.datetime(2023, 10, 17, 14, 30, 45) + + class MockObjWithDateTime(SerializerComponent): + def __init__(self, name: str, dt: datetime.datetime): + self.name = name + self.dt = dt + self.unique_name = f"dt_{name}" + self._global_object = True + + obj = MockObjWithDateTime("test", dt) + result = serializer._convert_to_dict(obj, full_encode=True) + + assert isinstance(result['dt'], dict) + assert result['dt']['@module'] == 'datetime' + assert result['dt']['@class'] == 'datetime' + + def test_convert_to_dict_without_global_object(self, serializer): + """Test _convert_to_dict with object without _global_object""" + + class MockObjNoGlobal(SerializerComponent): + def __init__(self, name: str): + self.name = name + + obj = MockObjNoGlobal("test") + result = serializer._convert_to_dict(obj) + + assert result['name'] == 'test' + assert 'unique_name' not in result + + def test_convert_to_dict_with_arg_spec(self, serializer, clear): + """Test _convert_to_dict with custom _arg_spec""" + + class MockObjCustomArgSpec(SerializerComponent): + def __init__(self, name: str, value: int, extra: str = "default"): + self.name = name + self.value = value + self.extra = extra + self._arg_spec = ['name', 'value'] # Skip 'extra' + self.unique_name = f"custom_spec_{name}" + self._global_object = True + + obj = MockObjCustomArgSpec("test", 42, "not_default") + result = serializer._convert_to_dict(obj) + + assert 'name' in result + assert 'value' in result + assert 'extra' not in result + + def test_recursive_encoder_with_lists(self, serializer, clear): + """Test _recursive_encoder with lists""" + mock_obj = MockSerializerComponent("list_test", 1) + data = [mock_obj, "string", 42, {"key": "value"}] + + result = serializer._recursive_encoder(data) + + assert isinstance(result, list) + assert len(result) == 4 + assert isinstance(result[0], dict) # Encoded mock object + assert result[0]['name'] == 'list_test' + assert result[1] == "string" + assert result[2] == 42 + assert result[3] == {"key": "value"} + + def test_recursive_encoder_with_dicts(self, serializer, clear): + """Test _recursive_encoder with dictionaries""" + mock_obj = MockSerializerComponent("dict_test", 2) + data = {"obj": mock_obj, "simple": "value"} + + result = serializer._recursive_encoder(data) + + assert isinstance(result, dict) + assert isinstance(result['obj'], dict) # Encoded mock object + assert result['obj']['name'] == 'dict_test' + assert result['simple'] == "value" + + def test_recursive_encoder_with_tuples(self, serializer, clear): + """Test _recursive_encoder with tuples""" + mock_obj = MockSerializerComponent("tuple_test", 3) + data = (mock_obj, "string", 42) + + result = serializer._recursive_encoder(data) + + assert isinstance(result, list) # Tuples become lists + assert len(result) == 3 + assert isinstance(result[0], dict) # Encoded mock object + assert result[0]['name'] == 'tuple_test' + + def test_recursive_encoder_builtin_encode_method(self, serializer): + """Test _recursive_encoder doesn't encode builtin objects with encode method""" + # Strings have an encode method but are builtin + data = ["test_string", b"bytes"] + + result = serializer._recursive_encoder(data) + + assert result == ["test_string", b"bytes"] + + def test_recursive_encoder_with_mutable_sequence(self, serializer, clear): + """Test _recursive_encoder with MutableSequence objects""" + from easyscience.base_classes import CollectionBase + + d0 = DescriptorNumber("a", 0) # type: ignore + d1 = DescriptorNumber("b", 1) # type: ignore + collection = CollectionBase("test_collection", d0, d1) + + result = serializer._recursive_encoder(collection) + + assert isinstance(result, dict) + assert result['@class'] == 'CollectionBase' + assert 'data' in result + + @patch('easyscience.io.serializer_base.import_module') + def test_convert_to_dict_no_version(self, mock_import, serializer, clear): + """Test _convert_to_dict when module has no __version__""" + mock_module = Mock() + del mock_module.__version__ # Remove version attribute + mock_import.return_value = mock_module + + mock_obj = MockSerializerComponent("no_version", 1) + result = serializer._convert_to_dict(mock_obj) + + assert result['@version'] is None + + @patch('easyscience.io.serializer_base.import_module') + def test_convert_to_dict_import_error(self, mock_import, serializer, clear): + """Test _convert_to_dict when import_module raises ImportError""" + mock_import.side_effect = ImportError("Module not found") + + mock_obj = MockSerializerComponent("import_error", 1) + result = serializer._convert_to_dict(mock_obj) + + assert result['@version'] is None + + def test_convert_to_dict_attribute_error_handling(self, serializer, clear): + """Test _convert_to_dict handles AttributeError for missing attributes""" + + class MockObjMissingAttrs(SerializerComponent): + def __init__(self, name: str, missing_param: str = "default"): + self.name = name + self.unique_name = f"missing_{name}" + self._global_object = True + # Don't set missing_param attribute to trigger AttributeError + + obj = MockObjMissingAttrs("test") + + with pytest.raises(NotImplementedError, match="Unable to automatically determine as_dict"): + serializer._convert_to_dict(obj) + + def test_convert_to_dict_with_kwargs_attribute(self, serializer, clear): + """Test _convert_to_dict with _kwargs attribute handling""" + + class MockObjWithKwargs(SerializerComponent): + def __init__(self, name: str, value: int): + self.name = name + self.value = value + self.unique_name = f"kwargs_{name}" + self._global_object = True + # Set up _kwargs to test the kwargs handling path + self._kwargs = {'extra_param': 'extra_value'} + + obj = MockObjWithKwargs("test", 42) + result = serializer._convert_to_dict(obj) + + # The extra_param from _kwargs should be included + assert result['extra_param'] == 'extra_value' + + def test_convert_to_dict_varargs_handling(self, serializer, clear): + """Test _convert_to_dict with varargs (*args) handling""" + + class MockObjWithVarargs(SerializerComponent): + def __init__(self, name: str, *args): + self.name = name + self.args = args + self.unique_name = f"varargs_{name}" + self._global_object = True + + obj = MockObjWithVarargs("test", "arg1", "arg2", "arg3") + result = serializer._convert_to_dict(obj) + + assert result['name'] == 'test' + if 'args' in result: + assert result['args'] == ("arg1", "arg2", "arg3") + + def test_encode_objs_edge_cases(self): + """Test _encode_objs with edge cases""" + # Test with None + assert SerializerBase._encode_objs(None) is None + + # Test with empty numpy array + empty_arr = np.array([]) + result = SerializerBase._encode_objs(empty_arr) + assert result['@module'] == 'numpy' + assert result['data'] == [] + + def test_convert_from_dict_edge_cases(self): + """Test _convert_from_dict with edge cases""" + # Test with None + assert SerializerBase._convert_from_dict(None) is None + + # Test with empty dict + assert SerializerBase._convert_from_dict({}) == {} + + # Test with empty list + assert SerializerBase._convert_from_dict([]) == [] + + # Test with bson.objectid (should not be processed) + bson_dict = { + '@module': 'bson.objectid', + '@class': 'ObjectId', + 'value': 'some_id' + } + result = SerializerBase._convert_from_dict(bson_dict) + assert result == bson_dict + + def test_concrete_serializer_implementation(self, clear): + """Test that ConcreteSerializer works correctly""" + serializer = ConcreteSerializer() + mock_obj = MockSerializerComponent("concrete_test", 100) + + # Test encode + encoded = serializer.encode(mock_obj) + assert isinstance(encoded, dict) + assert encoded['name'] == 'concrete_test' + assert encoded['value'] == 100 + + # Test decode + global_object.map._clear() # Clear before decode + decoded = ConcreteSerializer.decode(encoded) + assert isinstance(decoded, MockSerializerComponent) + assert decoded.name == 'concrete_test' + assert decoded.value == 100 + + def test_get_arg_spec_with_complex_function(self): + """Test get_arg_spec with more complex function signatures""" + def complex_func(self, required_arg, optional_arg="default", *args, **kwargs): + pass + + spec, args = SerializerBase.get_arg_spec(complex_func) + + assert args == ['required_arg', 'optional_arg'] + assert spec.varargs == 'args' + assert spec.varkw == 'kwargs' + assert spec.defaults == ("default",) + + @patch('easyscience.io.serializer_base.np', None) + def test_encode_objs_without_numpy(self): + """Test _encode_objs when numpy is not available""" + # This test patches np to None to simulate numpy not being installed + dt = datetime.datetime(2023, 10, 17, 14, 30, 45) + result = SerializerBase._encode_objs(dt) + + expected = { + '@module': 'datetime', + '@class': 'datetime', + 'string': '2023-10-17 14:30:45' + } + assert result == expected + + def test_recursive_encoder_with_nested_structures(self, serializer, clear): + """Test _recursive_encoder with deeply nested structures""" + mock_obj = MockSerializerComponent("nested", 1) + + data = { + "level1": { + "level2": [mock_obj, {"level3": mock_obj}] + } + } + + result = serializer._recursive_encoder(data) + + assert isinstance(result, dict) + assert isinstance(result["level1"], dict) + assert isinstance(result["level1"]["level2"], list) + assert isinstance(result["level1"]["level2"][0], dict) # Encoded object + assert result["level1"]["level2"][0]["name"] == "nested" + assert isinstance(result["level1"]["level2"][1]["level3"], dict) # Encoded object \ No newline at end of file diff --git a/tests/unit_tests/models/test_polynomial.py b/tests/unit_tests/models/test_polynomial.py index 799a917a..2493cd11 100644 --- a/tests/unit_tests/models/test_polynomial.py +++ b/tests/unit_tests/models/test_polynomial.py @@ -6,7 +6,17 @@ import numpy as np import pytest +from easyscience import global_object +from easyscience.base_classes import CollectionBase from easyscience.models.polynomial import Polynomial +from easyscience.variable import Parameter + + +@pytest.fixture +def clear(): + """Clear global object map before each test.""" + global_object.map._clear() + poly_test_cases = ( (1.,), @@ -19,8 +29,9 @@ (0.72, 6.48, -0.48), ) + @pytest.mark.parametrize("coo", poly_test_cases) -def test_Polynomial_pars(coo): +def test_Polynomial_pars(clear, coo): poly = Polynomial(coefficients=coo) vals = {coo.value for coo in poly.coefficients} @@ -29,3 +40,155 @@ def test_Polynomial_pars(coo): x = np.linspace(0, 10, 100) y = np.polyval(coo, x) assert np.allclose(poly(x), y) + + +def test_Polynomial_default_initialization(clear): + """Test Polynomial with no coefficients.""" + poly = Polynomial(name='test_poly') + + assert poly.name == 'test_poly' + assert len(poly.coefficients) == 0 + + # Test that calling the polynomial with empty coefficients works + x = np.array([1, 2, 3]) + result = poly(x) + assert len(result) == len(x) + + +def test_Polynomial_with_Parameter_objects(clear): + """Test Polynomial with Parameter objects as coefficients.""" + p0 = Parameter('c0', value=1.0) + p1 = Parameter('c1', value=2.0) + p2 = Parameter('c2', value=3.0) + + poly = Polynomial(coefficients=[p0, p1, p2]) + + assert len(poly.coefficients) == 3 + assert poly.coefficients[0].name == 'c0' + assert poly.coefficients[1].name == 'c1' + assert poly.coefficients[2].name == 'c2' + assert poly.coefficients[0].value == 1.0 + assert poly.coefficients[1].value == 2.0 + assert poly.coefficients[2].value == 3.0 + + # Test evaluation - coefficients passed directly to polyval + # polyval([1.0, 2.0, 3.0], x) = 1.0*x^2 + 2.0*x + 3.0 + x = np.array([0, 1, 2]) + expected = np.polyval([1.0, 2.0, 3.0], x) + assert np.allclose(poly(x), expected) + + +def test_Polynomial_with_mixed_coefficients(clear): + """Test Polynomial with mixed float and Parameter coefficients.""" + p0 = Parameter('c0', value=5.0) + + poly = Polynomial(coefficients=[p0, 2.0, 1.0]) + + assert len(poly.coefficients) == 3 + assert poly.coefficients[0].name == 'c0' + assert poly.coefficients[1].name == 'c1' + assert poly.coefficients[2].name == 'c2' + + # polyval([5.0, 2.0, 1.0], x) = 5.0*x^2 + 2.0*x + 1.0 + x = np.array([1, 2, 3]) + expected = np.polyval([5.0, 2.0, 1.0], x) + assert np.allclose(poly(x), expected) + + +def test_Polynomial_with_CollectionBase(clear): + """Test Polynomial initialized with a CollectionBase.""" + collection = CollectionBase('coeffs') + collection.append(Parameter('c0', value=1.0)) + collection.append(Parameter('c1', value=2.0)) + collection.append(Parameter('c2', value=3.0)) + + poly = Polynomial(coefficients=collection) + + assert poly.coefficients is collection + assert len(poly.coefficients) == 3 + + # polyval([1.0, 2.0, 3.0], x) = 1.0*x^2 + 2.0*x + 3.0 + x = np.array([0, 1, 2]) + expected = np.polyval([1.0, 2.0, 3.0], x) + assert np.allclose(poly(x), expected) + + +def test_Polynomial_invalid_coefficient_type(clear): + """Test that invalid coefficient types raise TypeError.""" + with pytest.raises(TypeError, match='Coefficients must be floats or Parameters'): + Polynomial(coefficients=[1.0, 'invalid', 3.0]) + + with pytest.raises(TypeError, match='Coefficients must be floats or Parameters'): + Polynomial(coefficients=[1, 2, 3]) # integers, not floats + + +def test_Polynomial_invalid_coefficients_type(clear): + """Test that invalid coefficients argument type raises TypeError.""" + # String is iterable, so it will iterate over characters and fail with first error + with pytest.raises(TypeError, match='Coefficients must be floats or Parameters'): + Polynomial(coefficients="invalid") + + # Integer is not iterable, so it will fail with second error + with pytest.raises(TypeError, match='coefficients must be a list or a CollectionBase'): + Polynomial(coefficients=42) + + +def test_Polynomial_repr_no_coefficients(clear): + """Test __repr__ with no coefficients.""" + poly = Polynomial(name='empty') + + repr_str = repr(poly) + assert 'Polynomial(empty, )' == repr_str + + +def test_Polynomial_repr_one_coefficient(clear): + """Test __repr__ with one coefficient.""" + poly = Polynomial(coefficients=[5.0]) + + repr_str = repr(poly) + assert 'Polynomial(polynomial, 5.0)' == repr_str + + +def test_Polynomial_repr_two_coefficients(clear): + """Test __repr__ with two coefficients.""" + poly = Polynomial(coefficients=[3.0, 2.0]) + + repr_str = repr(poly) + assert 'Polynomial(polynomial, 2.0x + 3.0)' == repr_str + + +def test_Polynomial_repr_three_coefficients(clear): + """Test __repr__ with three coefficients.""" + poly = Polynomial(coefficients=[1.0, 2.0, 3.0]) + + repr_str = repr(poly) + assert 'Polynomial(polynomial, 3.0x^2 + 2.0x + 1.0)' == repr_str + + +def test_Polynomial_repr_with_zero_coefficients(clear): + """Test __repr__ with some zero coefficients.""" + poly = Polynomial(coefficients=[1.0, 0.0, 3.0, 0.0, 5.0]) + + repr_str = repr(poly) + # Zero coefficients for higher powers should be excluded + assert 'Polynomial(polynomial, 5.0x^4 + 3.0x^2 + 0.0x + 1.0)' == repr_str + + +def test_Polynomial_repr_negative_coefficients(clear): + """Test __repr__ with negative coefficients.""" + poly = Polynomial(coefficients=[-1.0, -2.0, -3.0]) + + repr_str = repr(poly) + assert 'Polynomial(polynomial, -3.0x^2 + -2.0x + -1.0)' == repr_str + + +def test_Polynomial_call_with_args_kwargs(clear): + """Test that __call__ accepts *args and **kwargs.""" + poly = Polynomial(coefficients=[1.0, 2.0, 3.0]) + + x = np.array([0, 1, 2]) + # These additional args/kwargs should be ignored + result = poly(x, "extra_arg", extra_kwarg="value") + # polyval([1.0, 2.0, 3.0], x) = 1.0*x^2 + 2.0*x + 3.0 + expected = np.polyval([1.0, 2.0, 3.0], x) + assert np.allclose(result, expected) diff --git a/tests/unit_tests/variable/test_parameter.py b/tests/unit_tests/variable/test_parameter.py index 6b4b5f17..0ca8f85e 100644 --- a/tests/unit_tests/variable/test_parameter.py +++ b/tests/unit_tests/variable/test_parameter.py @@ -635,24 +635,6 @@ def test_set_value_dependent_parameter(self, normal_parameter: Parameter): with pytest.raises(AttributeError): dependent_parameter.value = 3 - @pytest.mark.skip(reason="No longer relevant") - def test_full_value_match_callback(self, parameter: Parameter): - # When - self.mock_callback.fget.return_value = sc.scalar(1, unit='m') - - # Then Expect - assert parameter.full_value == sc.scalar(1, unit='m') - assert parameter._callback.fget.call_count == 1 - - @pytest.mark.skip(reason="No longer relevant") - def test_full_value_no_match_callback(self, parameter: Parameter): - # When - self.mock_callback.fget.return_value = sc.scalar(2, unit='m') - - # Then Expect - assert parameter.full_value == sc.scalar(2, unit='m') - assert parameter._callback.fget.call_count == 1 - def test_set_full_value(self, parameter: Parameter): # When Then Expect with pytest.raises(AttributeError):