From b86c59f42bc0f803e474e2a07b1bcf92abdd56bd Mon Sep 17 00:00:00 2001 From: David Vesterlund Date: Tue, 27 Oct 2026 17:32:16 +0100 Subject: [PATCH 1/2] Make nightly CI fail visibly and keep one publish path Release review 2026-10-24 found two CI problems shared by all SDK repos: - nightly.yml used continue-on-error, "|| true" and "|| echo", so a broken install or failing test suite still produced a green run. - publish.yml (release published) and release.yml (v* tag) could both try to upload the same version. Only publish.yml is registered as a PyPI Trusted Publisher; release.yml uploads failed with invalid-publisher. Nightly now upgrades all dependencies eagerly, runs pip check and fails on test failures. release.yml is removed; publish.yml is the single path and is gated on tests.yml (now reusable via workflow_call), a tag/version match and twine check --strict. No package code or version change. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/workflows/nightly.yml | 28 +++------ .github/workflows/publish.yml | 59 ++++++++++++------ .github/workflows/release.yml | 54 ---------------- .github/workflows/tests.yml | 1 + .../__pycache__/__init__.cpython-310.pyc | Bin 1412 -> 1510 bytes .../__pycache__/dataset.cpython-310.pyc | Bin 2376 -> 2447 bytes .../__pycache__/model.cpython-310.pyc | Bin 3917 -> 5007 bytes .../__pycache__/plugin.cpython-310.pyc | Bin 3738 -> 3809 bytes .../__pycache__/registry.cpython-310.pyc | Bin 2323 -> 2394 bytes .../__pycache__/repgraph.cpython-310.pyc | Bin 4122 -> 4193 bytes .../__pycache__/search.cpython-310.pyc | Bin 17564 -> 17635 bytes .../__pycache__/validation.cpython-310.pyc | Bin 1190 -> 1261 bytes 12 files changed, 51 insertions(+), 91 deletions(-) delete mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index dc48ffd..6738b57 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -1,5 +1,8 @@ name: Nightly SDK Breakage Detection +# Installs the newest releases of every dependency and fails visibly when the +# install, dependency resolution or tests break. Do not add continue-on-error, +# "|| true" or "|| echo" here: a red nightly run is the signal. on: schedule: - cron: "0 2 * * *" @@ -9,27 +12,16 @@ jobs: nightly: name: Test against latest SDK versions runs-on: ubuntu-latest - continue-on-error: true steps: - uses: actions/checkout@v4 - - name: Checkout WestQuant Core - uses: actions/checkout@v4 - with: - repository: WestQuantOpen/westquant-core - path: _westquant-core - uses: actions/setup-python@v5 with: - python-version: "3.10" - - name: Install latest SDKs + python-version: "3.12" + - name: Install latest dependencies run: | - pip install --upgrade pip - pip install -e ./_westquant-core[test] - pip install --upgrade qiskit pytket pennylane pulser 2>/dev/null || true - pip install -e .[test] 2>/dev/null || pip install -e . + python -m pip install --upgrade pip + pip install --upgrade --upgrade-strategy eager -e ".[test]" + pip check + pip freeze - name: Run tests - run: | - pytest tests/ -v || echo "Nightly tests failed — SDK breakage detected" - - name: Report status - if: always() - run: | - echo "Nightly run completed. Check for SDK breakage above." + run: pytest tests/ -v diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index a05c99c..40a9cc5 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,34 +1,55 @@ name: Publish to PyPI +# Single publication path. PyPI Trusted Publishing is bound to this file name +# (publish.yml) and the "pypi" environment. Tests must pass and the release tag +# must match the pyproject version before anything is uploaded. on: release: types: [published] workflow_dispatch: - inputs: - confirm: - description: 'Type "publish" to confirm' - required: true - default: 'publish' + +permissions: + contents: read jobs: - publish: - name: Build and publish + test: + uses: ./.github/workflows/tests.yml + + build: + needs: test runs-on: ubuntu-latest - environment: pypi - permissions: - id-token: write steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: - python-version: "3.10" - - name: Build package + python-version: "3.12" + - name: Check release tag matches package version + if: github.event_name == 'release' run: | - pip install build - python -m build - - name: Check package + version=$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml', 'rb'))['project']['version'])") + if [ "${GITHUB_REF_NAME#v}" != "$version" ]; then + echo "::error::Release tag $GITHUB_REF_NAME does not match pyproject version $version" + exit 1 + fi + - name: Build and check distributions run: | - pip install twine - twine check dist/* - - name: Publish to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 + python -m pip install --upgrade build twine + python -m build + twine check --strict dist/* + - uses: actions/upload-artifact@v4 + with: + name: python-package-distributions + path: dist/ + + publish: + needs: build + runs-on: ubuntu-latest + environment: pypi + permissions: + id-token: write + steps: + - uses: actions/download-artifact@v4 + with: + name: python-package-distributions + path: dist/ + - uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 16db53d..0000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,54 +0,0 @@ -name: Release to PyPI - -on: - push: - tags: - - "v*" - -permissions: - contents: read - -jobs: - test: - runs-on: ubuntu-latest - strategy: - matrix: - python-version: ["3.10", "3.11", "3.12"] - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python-version }} - - run: | - python -m pip install --upgrade pip - pip install pytest - pip install -e . - - run: pytest -q - - build: - needs: test - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: "3.12" - - run: python -m pip install --upgrade build - - run: python -m build - - uses: actions/upload-artifact@v4 - with: - name: python-package-distributions - path: dist/ - - publish: - needs: build - runs-on: ubuntu-latest - environment: pypi - permissions: - id-token: write - steps: - - uses: actions/download-artifact@v4 - with: - name: python-package-distributions - path: dist/ - - uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 77121f9..09f5748 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,6 +1,7 @@ name: Tests on: + workflow_call: push: pull_request: diff --git a/src/westquant_core/__pycache__/__init__.cpython-310.pyc b/src/westquant_core/__pycache__/__init__.cpython-310.pyc index f55f9aa241cab7b60396ce8aaa57714b8ac7e3ec..d2ec7ed793ce14e718d00950ae1d282b46dee949 100644 GIT binary patch delta 591 zcmYk1J#W)M7{`5%-x}L_QBhG*Q__UKxNYJz5+E_PDn&?0EQsYgSXSsUt$QHaV6Zep{%SJ?8rwaOc~fs{xg+9kqGY0=s8)7=Gc<96vX*cR{L4)5Y_ zS)1$*-^SZ~2k-D*yo(gtlws=<-B-%^3ftoz_MlIy(f_WE_lfgN@!UU1e$CU1`q^|A z&qGF&5q%OTq;SvP(9tZ5$I0V3$%3?eAy(nR`CO=_ETHGDvCG>mLd*SZ}AVSEGTI#~*{$xfzTc1{EN~Dx%jh0!3R9KZ%*%Dd8 z$jyqdKE%5yiI34`RwFg2J8AE)YLL2Po}jw*g~eEP`8{*cyY_Ev>IUcTksmnm9)8DG zye7|8IgHK?z!<;+XaF5x0>(#esfFc?*vHQ)691&;4@*MaYnvNe8=Lm_aeaj-tn0Xx zOAtr_WPl<-bnb>8x5G=Wf>c9#?fF4+OME7m;|DqS-@M7d?fLzP-|;+jSb&J;*pc0L zBfbcw0-y->w0M*+&irn`VIpF5IyWxw3*G6wAYKJ0;Jeibx%h&}ZA2_=-1gQl{J^I1 ZlhT}?l})vVbz?u9#Z%anOeu|Z=@(0XYj*$u diff --git a/src/westquant_core/__pycache__/dataset.cpython-310.pyc b/src/westquant_core/__pycache__/dataset.cpython-310.pyc index 087fbe2cb5977897900ad3de64a78d3d9f4d3880..363d44ad29ec6e1ba5fed9bc1098b7ff8bcfee5f 100644 GIT binary patch delta 125 zcmX>h)Gy4P&&$ij00jHaKG?`Tn<=(aKeRZts8~NGu`DyCEVZ~KwJ4`FFGWACC^a=D zKQ}o)B^8BT4pdTDnwVFjTa=oUnpm8wYh++#rfX=RkB}+MEY8j>(bv=4yoX7Njq%px H`y817`dckd delta 54 zcmeAdJ|V=N&&$ij00ig4wr%8|%_QceUr>};mRORiUy@s(UtXx2mYJ8BvzeJ$iH$L8 IvKnV50I?Mi1poj5 diff --git a/src/westquant_core/__pycache__/model.cpython-310.pyc b/src/westquant_core/__pycache__/model.cpython-310.pyc index ff8c326ea36bef3a99329f98584b119256852d00..9b2d5e08fe0091cd0e597c64257a3152e6c33785 100644 GIT binary patch delta 2241 zcmaJ>&2Jk;6yI5|*X#9XtTatX;!x7oHIO(7B~eQVE&U7>^HGA3FV<#foNjCHI!gyVJ=djTZu8e) zhC*Gkn=gNI{@VOS;cFN4piVAW zQ-(=y`@T{ju-n7vHW>_7)KQWT?yJLz-8=H0;Gue_I*2wy2rnYMgfNPbM>q*k)cCGa z7zM9w^Gm^T@Yd56Ubge z!-QEkT(`lz{0)clGbrykCYZ>?K(G}*F){$lCX78FZhcOYi2F_OG@frM6@?Ng=IE?M z)k>7cfNO%Qg2x4q39ipdOk;7HxJxQJO@d~sOOg~RAu+;%WAStf3SUk(8$ zaTpgcEGL5}$-&@EEYZ@yUAera@wZ@&pF?;X;UdB%gv$t55U^VLRfPRzh%!vwr!ZVR zPLUPT{Zs$>;z)N$ym8N|Qp<$UVBtN>6!xqZOc|ulKjhe-!u2MQHOZ6K2qgp3IuT5M z&b}u!LX{ujmGa~@0<$PpyJoRHGmWY(u^17maZBo&>FpWR0fs19-XEaz;72=37}-NZ z1O&{*jdhT97u%R13Xy6XoqJh~@J<2CLyFp6H8zX2xy zZOnO;X7)8Ep9Seomg`76X~w>3w`3>bm{%L;g)f79$!}Z2wxcXID5Kf?2p=GPi0~1@b%c)*MiCYO z;GO&bEv8WO@O^eSI?zuH_U+)W)P>er+(u+IcVPZ7cDxTkINr(J;YXt~UZL~U9{8@l zgDSz->0%36xtIy{YPIHjK45;cYIuftrJ2hksE_A|3bXwNk0MpQ)uv@HaTOOu z%45ic*Z5>}tQjtj$|CCkwnC`QHXM4wud_MqE>TxWB`af9zMmf>ulDEml)C=pRJE}Gt_r^Xu1+RN=r8?JA8yd-@Rp@))JHqx%YV|i|Ut*TKKd4qt) zSLNoUkzQF_zqh*bAQ9_97BM;gTOKF5gCn^@gxa)nK!*8GWrmdakusj?G(od`I=yEO zBWDCC180GAKnWNZsH(IR6c325BIm?dI*Y8{8X5KL(@uIj?=)ii6r$%*O`>V>6-%2A zqcd=%V#)SGI)|)Y<=Mf9tqC|M1>UDq8+d;_M{ZH~g`iJ>sj8k}@2d07RzzyK|+K8#=Law{T~FeV27jh(6|Diq#gZwQAnbOmib*5p~36q=e7N z)GcNut9L>wp$XJCWXF#hbU>J~!giakzeyE5CL6~sx4RyK1?_(2V|A$!)FaPXCb)$V Wf5@y{NM%Wu6s4lBY6YTJM#w)-q0+ek diff --git a/src/westquant_core/__pycache__/plugin.cpython-310.pyc b/src/westquant_core/__pycache__/plugin.cpython-310.pyc index 8c29561a6a818e7b157911fd1c615ac009cdec66..2b9fc371fc914ccc7be4bf58204cb71af1695d60 100644 GIT binary patch delta 119 zcmbOw`%soUpO=@50SNY;eXx;RhB>xFKeRZts8~NGu`DyCEVZ~KwJ4`FFGWACC^a=D zKQ}o)B^8BT4pdTDnwVFjTa=oUnpm8wYh++#rfX=RkB}+MEY8j>(bv=4Y|9+W4FK0& BDhvPs delta 48 zcmaDTJ4=>3pO=@50SGRHZQIB#!z|{gUr>};mRORiUy@s(UtXx2mYJ8Bv$=&imKy+5 C;12u% diff --git a/src/westquant_core/__pycache__/registry.cpython-310.pyc b/src/westquant_core/__pycache__/registry.cpython-310.pyc index 2c68e50cf90d854177a39a19b4c32df87f5ab450..c1437480c5892e450ced01ddaf54dcf559ebdbc7 100644 GIT binary patch delta 566 zcmZusy-vbV80EG?8!8Ke2}MysP{j6DLi7nVz5whEy(R>t@)a;9ChiO_H}M@h8fKYY ze1T5BfP;gJllQwMfW{7|=brC;KZmEIwBe^x$(Z7aCHX5uyE_{~xW#XkETaTqbQfwz8 zUD#WgO0v9 z21LjL2~9SLCpbU?AfFVef(W=Gpgh>goFGxKyTL5!$^IPj^l}N=r(MQYXLVFcSr-$1rHJ1*Z}K3`1C2 diff --git a/src/westquant_core/__pycache__/repgraph.cpython-310.pyc b/src/westquant_core/__pycache__/repgraph.cpython-310.pyc index 6d0920ccc30b925a0305e6ac62fd81eae9a06fee..d26b0fab4b20b040df1c5f0e3e7c4ee98f758ead 100644 GIT binary patch delta 515 zcmbQG@KAv}pO=@50SNY;eXx=H9#d?WerR!OQL%nXVp(QNS!!`fYEe#UUW$HNQEF;R zer|GpN-7Gw9H^wQG%>G4w)6WLwUtGdYu8R!9>h%AA=}TqFTe zrnz|ry9J|^3XoUC4bYgo5``< z(`3wnYJis6fRx&T2#~Qwk|081GCz;CA4owFC`^ikL4+xg&}1(Hn~$&#Y&*!hTg=6& zB}K|0mFge@Y??KQ1vXN3@(iAnqIPf@gk?ID%Xs~`9pEyKlh5`4UyQUlP~fWifVuq8-NHC5TObpoF<3!9|iz= CCvo8b delta 451 zcmaE;FiU|upO=@50SGRIZQICwk4el~zo00yEU_e2za+Onzr0X4Ei*4MXR{mgdPc^m z$=_IhG0H9e$jT_L0Mt{Y2qZL_ie!P*Eyh$$#v+Z$9PG;(wI^?2mle_gibgSKrW6-R zK$K~0zRzyKD5VVK74d@z1rWgpB0vTescbgnv}I(}n4Hg*%wh}_nf#GgbnXDj>pP I@;v^-0E?PdKmY&$ diff --git a/src/westquant_core/__pycache__/search.cpython-310.pyc b/src/westquant_core/__pycache__/search.cpython-310.pyc index 86300e55aee76ee70a959f86bb75c17356439c02..1d48b941679a28c1114eaad6eb9c4601b327106b 100644 GIT binary patch delta 4810 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 y>6w6Tz)CAW1@*KAtcsvk?|1(pTT62C<-Ysw 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 From 6acffe23bab498a8e37d43366f0a0a8212d8e00e Mon Sep 17 00:00:00 2001 From: David Vesterlund Date: Tue, 27 Oct 2026 17:33:04 +0100 Subject: [PATCH 2/2] Restore tracked bytecode files touched by a local test run --- .../__pycache__/__init__.cpython-310.pyc | Bin 1510 -> 1412 bytes .../__pycache__/dataset.cpython-310.pyc | Bin 2447 -> 2376 bytes .../__pycache__/model.cpython-310.pyc | Bin 5007 -> 3917 bytes .../__pycache__/plugin.cpython-310.pyc | Bin 3809 -> 3738 bytes .../__pycache__/registry.cpython-310.pyc | Bin 2394 -> 2323 bytes .../__pycache__/repgraph.cpython-310.pyc | Bin 4193 -> 4122 bytes .../__pycache__/search.cpython-310.pyc | Bin 17635 -> 17564 bytes .../__pycache__/validation.cpython-310.pyc | Bin 1261 -> 1190 bytes 8 files changed, 0 insertions(+), 0 deletions(-) diff --git a/src/westquant_core/__pycache__/__init__.cpython-310.pyc b/src/westquant_core/__pycache__/__init__.cpython-310.pyc index d2ec7ed793ce14e718d00950ae1d282b46dee949..f55f9aa241cab7b60396ce8aaa57714b8ac7e3ec 100644 GIT binary patch delta 475 zcmXw#y-UMD7{>3?eAy(nR`CO=_ETHGDvCG>mLd*SZ}AVSEGTI#~*{$xfzTc1{EN~Dx%jh0!3R9KZ%*%Dd8 z$jyqdKE%5yiI34`RwFg2J8AE)YLL2Po}jw*g~eEP`8{*cyY_Ev>IUcTksmnm9)8DG zye7|8IgHK?z!<;+XaF5x0>(#esfFc?*vHQ)691&;4@*MaYnvNe8=Lm_aeaj-tn0Xx zOAtr_WPl<-bnb>8x5G=Wf>c9#?fF4+OME7m;|DqS-@M7d?fLzP-|;+jSb&J;*pc0L zBfbcw0-y->w0M*+&irn`VIpF5IyWxw3*G6wAYKJ0;Jeibx%h&}ZA2_=-1gQl{J^I1 ZlhT}?l})vVbz?u9#Z%anOeu|Z=@(0XYj*$u delta 591 zcmYk1J#W)M7{`5%-x}L_QBhG*Q__UKxNYJz5+E_PDn&?0EQsYgSXSsUt$QHaV6Zep{%SJ?8rwaOc~fs{xg+9kqGY0=s8)7=Gc<96vX*cR{L4)5Y_ zS)1$*-^SZ~2k-D*yo(gtlws=<-B-%^3ftoz_MlIy(f_WE_lfgN@!UU1e$CU1`q^|A z&qGF&5q%OTq;SvP(9tZ5$I0V3$%};mRORiUy@s(UtXx2mYJ8BvzeJ$iH$L8 IvKnV50I?Mi1poj5 delta 125 zcmX>h)Gy4P&&$ij00jHaKG?`Tn<=(aKeRZts8~NGu`DyCEVZ~KwJ4`FFGWACC^a=D zKQ}o)B^8BT4pdTDnwVFjTa=oUnpm8wYh++#rfX=RkB}+MEY8j>(bv=4yoX7Njq%px H`y817`dckd diff --git a/src/westquant_core/__pycache__/model.cpython-310.pyc b/src/westquant_core/__pycache__/model.cpython-310.pyc index 9b2d5e08fe0091cd0e597c64257a3152e6c33785..ff8c326ea36bef3a99329f98584b119256852d00 100644 GIT binary patch delta 1174 zcmaKr&ubG=5XXJl?Pk0Av1!`IsQpPPF;zMmf>ulDEml)C=pRJE}Gt_r^Xu1+RN=r8?JA8yd-@Rp@))JHqx%YV|i|Ut*TKKd4qt) zSLNoUkzQF_zqh*bAQ9_97BM;gTOKF5gCn^@gxa)nK!*8GWrmdakusj?G(od`I=yEO zBWDCC180GAKnWNZsH(IR6c325BIm?dI*Y8{8X5KL(@uIj?=)ii6r$%*O`>V>6-%2A zqcd=%V#)SGI)|)Y<=Mf9tqC|M1>UDq8+d;_M{ZH~g`iJ>sj8k}@2d07RzzyK|+K8#=Law{T~FeV27jh(6|Diq#gZwQAnbOmib*5p~36q=e7N z)GcNut9L>wp$XJCWXF#hbU>J~!giakzeyE5CL6~sx4RyK1?_(2V|A$!)FaPXCb)$V Wf5@y{NM%Wu6s4lBY6YTJM#w)-q0+ek delta 2241 zcmaJ>&2Jk;6yI5|*X#9XtTatX;!x7oHIO(7B~eQVE&U7>^HGA3FV<#foNjCHI!gyVJ=djTZu8e) zhC*Gkn=gNI{@VOS;cFN4piVAW zQ-(=y`@T{ju-n7vHW>_7)KQWT?yJLz-8=H0;Gue_I*2wy2rnYMgfNPbM>q*k)cCGa z7zM9w^Gm^T@Yd56Ubge z!-QEkT(`lz{0)clGbrykCYZ>?K(G}*F){$lCX78FZhcOYi2F_OG@frM6@?Ng=IE?M z)k>7cfNO%Qg2x4q39ipdOk;7HxJxQJO@d~sOOg~RAu+;%WAStf3SUk(8$ zaTpgcEGL5}$-&@EEYZ@yUAera@wZ@&pF?;X;UdB%gv$t55U^VLRfPRzh%!vwr!ZVR zPLUPT{Zs$>;z)N$ym8N|Qp<$UVBtN>6!xqZOc|ulKjhe-!u2MQHOZ6K2qgp3IuT5M z&b}u!LX{ujmGa~@0<$PpyJoRHGmWY(u^17maZBo&>FpWR0fs19-XEaz;72=37}-NZ z1O&{*jdhT97u%R13Xy6XoqJh~@J<2CLyFp6H8zX2xy zZOnO;X7)8Ep9Seomg`76X~w>3w`3>bm{%L;g)f79$!}Z2wxcXID5Kf?2p=GPi0~1@b%c)*MiCYO z;GO&bEv8WO@O^eSI?zuH_U+)W)P>er+(u+IcVPZ7cDxTkINr(J;YXt~UZL~U9{8@l zgDSz->0%36xtIy{YPIHjK45;cYIuftrJ2hksE_A|3bXwNk0MpQ)uv@HaTOOu z%45ic*Z5>}tQjtj$|CCkwnC`QHXM4wud_MqE>TxWB`af93pO=@50SGRHZQIB#!z|{gUr>};mRORiUy@s(UtXx2mYJ8Bv$=&imKy+5 C;12u% delta 119 zcmbOw`%soUpO=@50SNY;eXx;RhB>xFKeRZts8~NGu`DyCEVZ~KwJ4`FFGWACC^a=D zKQ}o)B^8BT4pdTDnwVFjTa=oUnpm8wYh++#rfX=RkB}+MEY8j>(bv=4Y|9+W4FK0& BDhvPs diff --git a/src/westquant_core/__pycache__/registry.cpython-310.pyc b/src/westquant_core/__pycache__/registry.cpython-310.pyc index c1437480c5892e450ced01ddaf54dcf559ebdbc7..2c68e50cf90d854177a39a19b4c32df87f5ab450 100644 GIT binary patch delta 530 zcmca5G+Br{pO=@50SGRJZQIEGm60)OG9y!gx)4xgB}0(}kOC9Gob?NeGRqQ6QuRx6 z3-rqib<;BQ5_2}+XHsS4hN~))+|19y%V;hK)OL$2EHS4v)wQT7zo0v9 z21LjL2~9SLCpbU?AfFVef(W=Gpgh>goFGxKyTL5!$^IPj^l}N=r(MQYXLVFcSr-$1rHJ1*Z}K3`1C2 delta 566 zcmZusy-vbV80EG?8!8Ke2}MysP{j6DLi7nVz5whEy(R>t@)a;9ChiO_H}M@h8fKYY ze1T5BfP;gJllQwMfW{7|=brC;KZmEIwBe^x$(Z7aCHX5uyE_{~xW#XkETaTqbQfwz8 zUD#WgOXDj>pP I@;v^-0E?PdKmY&$ delta 515 zcmbQG@KAv}pO=@50SNY;eXx=H9#d?WerR!OQL%nXVp(QNS!!`fYEe#UUW$HNQEF;R zer|GpN-7Gw9H^wQG%>G4w)6WLwUtGdYu8R!9>h%AA=}TqFTe zrnz|ry9J|^3XoUC4bYgo5``< z(`3wnYJis6fRx&T2#~Qwk|081GCz;CA4owFC`^ikL4+xg&}1(Hn~$&#Y&*!hTg=6& zB}K|0mFge@Y??KQ1vXN3@(iAnqIPf@gk?ID%Xs~`9pEyKlh5`4UyQUlP~fWifVuq8-NHC5TObpoF<3!9|iz= CCvo8b diff --git a/src/westquant_core/__pycache__/search.cpython-310.pyc b/src/westquant_core/__pycache__/search.cpython-310.pyc index 1d48b941679a28c1114eaad6eb9c4601b327106b..86300e55aee76ee70a959f86bb75c17356439c02 100644 GIT binary patch delta 4780 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 y>6w6Tz)C&rSh0px$6r9k34kkVbn z5AYA1BSma6(vD_!c7BuhBr|!Qo`l&yeZ6J$QaHXq1#E-X38VdVi7hdqS&g9l2srg@ z(pXTqHFoJIj)0JfnV$xaXat9YWEl84`U#;`LWA_V#vQSLHD7>~sOJao*sVE7=k9#! z2-^@i!<{b_k`>&A@Wxp5`EiFPoDEWx$O&rsc^lnF(V$z!57DUmh|4JLzT@kwA{4V1 vJq&xu0z99WYVD}3v8;`e2-==?<>~9?W7S%*30*2uZM9w9H2vFMKKS_qAogmB delta 367 zcmY*UJ5Iwu6vT-_Vmpq26SzYZjzfe}!7(V2^}PF>tg@eEcb!BuTz~@PJJ6<}r=&xo z-YOU14s0R;;uWJO&Ac}=FX2}ht0akz{Jeeao@4vaGZrisjJp0D7q(!sC=rC~uTZm! z5wJ{2*EKaEXpHNV8E}qrdN}D>)PhOi?ik2H7#ZY9ER-BwSZNTrR(kFRhRjev;h&oQ zzkxuj88OAA#7b#&iNuX9ezPP$JXGGoMaJU7N29oL9WR=`UIo`dkTlEIO%OHPRvMf& zpRJ4Yt}mwJJ#_XEdbmGHMQv