diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d9f5dfa..0f55623 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,10 +11,36 @@ permissions: pull-requests: write jobs: + # -- Lint, Format & Typecheck ---------------------------------------------- + lint: + name: Lint, Format & Typecheck + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.13" + + - name: Install tools + run: pip install ruff mypy types-requests + + - name: Ruff lint + run: ruff check . + + - name: Ruff format check + run: ruff format --check . + + - name: Mypy typecheck + run: mypy lint_commits.py lint_local.py + # -- Unit tests (push + PR) ------------------------------------------------ test: name: Unit Tests runs-on: ubuntu-latest + needs: lint steps: - name: Checkout uses: actions/checkout@v4 diff --git a/.gitignore b/.gitignore index bf34d05..879c75a 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ __pycache__/ dist/ build/ .venv/ +.ruff_cache/ +.mypy_cache/ diff --git a/Pipfile b/Pipfile index 827a4f2..2ab9402 100644 --- a/Pipfile +++ b/Pipfile @@ -10,6 +10,9 @@ llm-ollama = "*" [dev-packages] pytest = "*" +ruff = "*" +mypy = "*" +types-requests = "*" [requires] python_version = "3.13" diff --git a/Pipfile.lock b/Pipfile.lock index e80495c..d97c5df 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "808478ef0aed446d81bbdb1a1066c50c4c9e5162a89a3f0bfdaa92a9f333d7f0" + "sha256": "b3d9b267f0cb31070fd126672a8138bda72e4151947b7574cf605ea2aa332dfa" }, "pipfile-spec": 6, "requires": { @@ -676,11 +676,11 @@ }, "tabulate": { "hashes": [ - "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c", - "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f" + "sha256:e2cfde8f79420f6deeffdeda9aaec3b6bc5abce947655d17ac662b126e48a60d", + "sha256:f0b0622e567335c8fabaaa659f1b33bcb6ddfe2e496071b743aa113f8774f2d3" ], - "markers": "python_version >= '3.7'", - "version": "==0.9.0" + "markers": "python_version >= '3.10'", + "version": "==0.10.0" }, "tqdm": { "hashes": [ @@ -716,1204 +716,253 @@ } }, "develop": { - "annotated-doc": { - "hashes": [ - "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320", - "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4" - ], - "markers": "python_version >= '3.8'", - "version": "==0.0.4" - }, - "annotated-types": { - "hashes": [ - "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", - "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89" - ], - "markers": "python_version >= '3.8'", - "version": "==0.7.0" - }, - "anyio": { - "hashes": [ - "sha256:41cfcc3a4c85d3f05c932da7c26d0201ac36f72abd4435ba90d0464a3ffed703", - "sha256:d405828884fc140aa80a3c667b8beed277f1dfedec42ba031bd6ac3db606ab6c" - ], - "markers": "python_version >= '3.9'", - "version": "==4.12.1" - }, - "certifi": { - "hashes": [ - "sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa", - "sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7" - ], - "markers": "python_version >= '3.7'", - "version": "==2026.2.25" - }, - "click": { + "iniconfig": { "hashes": [ - "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a", - "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6" + "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", + "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12" ], "markers": "python_version >= '3.10'", - "version": "==8.3.1" - }, - "click-default-group": { - "hashes": [ - "sha256:9b60486923720e7fc61731bdb32b617039aba820e22e1c88766b1125592eaa5f", - "sha256:eb3f3c99ec0d456ca6cd2a7f08f7d4e91771bef51b01bdd9580cc6450fe1251e" - ], - "markers": "python_version >= '2.7'", - "version": "==1.2.4" + "version": "==2.3.0" }, - "condense-json": { - "hashes": [ - "sha256:25fe8d434fdafd849e8d98f21a3e18f96ae2d6dbc2c17565f29e4843d039d2bc", - "sha256:e0a3d42db4f44a89e74af8737d8e517e97420be0f7e5437087f4decfd38c3366" + "librt": { + "hashes": [ + "sha256:01170b6729a438f0dedc4a26ed342e3dc4f02d1000b4b19f980e1877f0c297e6", + "sha256:039b9f2c506bd0ab0f8725aa5ba339c6f0cd19d3b514b50d134789809c24285d", + "sha256:05bd41cdee35b0c59c259f870f6da532a2c5ca57db95b5f23689fcb5c9e42440", + "sha256:086a32dbb71336627e78cc1d6ee305a68d038ef7d4c39aaff41ae8c9aa46e91a", + "sha256:08eec3a1fc435f0d09c87b6bf1ec798986a3544f446b864e4099633a56fcd9ed", + "sha256:0bf69d79a23f4f40b8673a947a234baeeb133b5078b483b7297c5916539cf5d5", + "sha256:0c3811485fccfda840861905b8c70bba5ec094e02825598bb9d4ca3936857a04", + "sha256:0d2f82168e55ddefd27c01c654ce52379c0750ddc31ee86b4b266bcf4d65f2a3", + "sha256:0f2ae3725904f7377e11cc37722d5d401e8b3d5851fb9273d7f4fe04f6b3d37d", + "sha256:10c42e1f6fd06733ef65ae7bebce2872bcafd8d6e6b0a08fe0a05a23b044fb14", + "sha256:153188fe98a72f206042be10a2c6026139852805215ed9539186312d50a8e972", + "sha256:172d57ec04346b047ca6af181e1ea4858086c80bdf455f61994c4aa6fc3f866c", + "sha256:190b109bb69592a3401fe1ffdea41a2e73370ace2ffdc4a0e8e2b39cdea81b78", + "sha256:1d3a7da44baf692f0c6aeb5b2a09c5e6fc7a703bca9ffa337ddd2e2da53f7732", + "sha256:228c2409c079f8c11fb2e5d7b277077f694cb93443eb760e00b3b83cb8b3176c", + "sha256:22b46eabd76c1986ee7d231b0765ad387d7673bbd996aa0d0d054b38ac65d8f6", + "sha256:237796479f4d0637d6b9cbcb926ff424a97735e68ade6facf402df4ec93375ed", + "sha256:2c74a2da57a094bd48d03fa5d196da83d2815678385d2978657499063709abe1", + "sha256:2cc68eeeef5e906839c7bb0815748b5b0a974ec27125beefc0f942715785b551", + "sha256:2eb345e8b33fb748227409c9f1233d4df354d6e54091f0e8fc53acdb2ffedeb7", + "sha256:31362dbfe297b23590530007062c32c6f6176f6099646bb2c95ab1b00a57c382", + "sha256:3dff3d3ca8db20e783b1bc7de49c0a2ab0b8387f31236d6a026597d07fcd68ac", + "sha256:43353b943613c5d9c49a25aaffdba46f888ec354e71e3529a00cca3f04d66a7a", + "sha256:439352ba9373f11cb8e1933da194dcc6206daf779ff8df0ed69c5e39113e6a99", + "sha256:4998009e7cb9e896569f4be7004f09d0ed70d386fa99d42b6d363f6d200501ac", + "sha256:4be2a5c926b9770c9e08e717f05737a269b9d0ebc5d2f0060f0fe3fe9ce47acb", + "sha256:4beb04b8c66c6ae62f8c1e0b2f097c1ebad9295c929a8d5286c05eae7c2fc7dc", + "sha256:4c8dfa264b9193c4ee19113c985c95f876fae5e51f731494fc4e0cf594990ba7", + "sha256:5212a5bd7fae98dae95710032902edcd2ec4dc994e883294f75c857b83f9aba0", + "sha256:52c224e14614b750c0a6d97368e16804a98c684657c7518752c356834fff83bb", + "sha256:56e04c14b696300d47b3bc5f1d10a00e86ae978886d0cee14e5714fafb5df5d2", + "sha256:5bb54f1205a3a6ab41a6fd71dfcdcbd278670d3a90ca502a30d9da583105b6f7", + "sha256:5cdc0f588ff4b663ea96c26d2a230c525c6fc62b28314edaaaca8ed5af931ad0", + "sha256:5db05697c82b3a2ec53f6e72b2ed373132b0c2e05135f0696784e97d7f5d48e7", + "sha256:5e4af413908f77294605e28cfd98063f54b2c790561383971d2f52d113d9c363", + "sha256:5fc48998000cbc39ec0d5311312dda93ecf92b39aaf184c5e817d5d440b29624", + "sha256:60a78b694c9aee2a0f1aaeaa7d101cf713e92e8423a941d2897f4fa37908dab9", + "sha256:64548cde61b692dc0dc379f4b5f59a2f582c2ebe7890d09c1ae3b9e66fa015b7", + "sha256:681dc2451d6d846794a828c16c22dc452d924e9f700a485b7ecb887a30aad1fd", + "sha256:6b1977c4ea97ce5eb7755a78fae68d87e4102e4aaf54985e8b56806849cc06a3", + "sha256:6cfa7fe54fd4d1f47130017351a959fe5804bda7a0bc7e07a2cdbc3fdd28d34f", + "sha256:738f08021b3142c2918c03692608baed43bc51144c29e35807682f8070ee2a3a", + "sha256:747328be0c5b7075cde86a0e09d7a9196029800ba75a1689332348e998fb85c0", + "sha256:758509ea3f1eba2a57558e7e98f4659d0ea7670bff49673b0dde18a3c7e6c0eb", + "sha256:785ae29c1f5c6e7c2cde2c7c0e148147f4503da3abc5d44d482068da5322fd9e", + "sha256:7aae78ab5e3206181780e56912d1b9bb9f90a7249ce12f0e8bf531d0462dd0fc", + "sha256:7b02679a0d783bdae30d443025b94465d8c3dc512f32f5b5031f93f57ac32071", + "sha256:7e2f3edca35664499fbb36e4770650c4bd4a08abc1f4458eab9df4ec56389730", + "sha256:7e6bad1cd94f6764e1e21950542f818a09316645337fd5ab9a7acc45d99a8f35", + "sha256:81fd938344fecb9373ba1b155968c8a329491d2ce38e7ddb76f30ffb938f12dc", + "sha256:82210adabbc331dbb65d7868b105185464ef13f56f7f76688565ad79f648b0fe", + "sha256:89815a22daf9c51884fb5dbe4f1ef65ee6a146e0b6a8df05f753e2e4a9359bf4", + "sha256:8f1125e6bbf2f1657d9a2f3ccc4a2c9b0c8b176965bb565dd4d86be67eddb4b6", + "sha256:8f4bb453f408137d7581be309b2fbc6868a80e7ef60c88e689078ee3a296ae71", + "sha256:924817ab3141aca17893386ee13261f1d100d1ef410d70afe4389f2359fea4f0", + "sha256:93c2af9e01e0ef80d95ae3c720be101227edae5f2fe7e3dc63d8857fadfc5a1d", + "sha256:97c2b54ff6717a7a563b72627990bec60d8029df17df423f0ed37d56a17a176b", + "sha256:9be2f15e53ce4e83cc08adc29b26fb5978db62ef2a366fbdf716c8a6c8901040", + "sha256:9e2c6f77b9ad48ce5603b83b7da9ee3e36b3ab425353f695cba13200c5d96596", + "sha256:a28f2612ab566b17f3698b0da021ff9960610301607c9a5e8eaca62f5e1c350a", + "sha256:a355d99c4c0d8e5b770313b8b247411ed40949ca44e33e46a4789b9293a907ee", + "sha256:a3b4350b13cc0e6f5bec8fa7caf29a8fb8cdc051a3bae45cfbfd7ce64f009965", + "sha256:aaab0e307e344cb28d800957ef3ec16605146ef0e59e059a60a176d19543d1b7", + "sha256:ac1e7817fd0ed3d14fd7c5df91daed84c48e4c2a11ee99c0547f9f62fdae13da", + "sha256:adfab487facf03f0d0857b8710cf82d0704a309d8ffc33b03d9302b4c64e91a9", + "sha256:b6d7ab1f01aa753188605b09a51faa44a3327400b00b8cce424c71910fc0a128", + "sha256:bacdb58d9939d95cc557b4dbaa86527c9db2ac1ed76a18bc8d26f6dc8647d851", + "sha256:be46a14693955b3bd96014ccbdb8339ee8c9346fbe11c1b78901b55125f14c73", + "sha256:bf512a71a23504ed08103a13c941f763db13fb11177beb3d9244c98c29fb4a61", + "sha256:c00e5c884f528c9932d278d5c9cbbea38a6b81eb62c02e06ae53751a83a4d52b", + "sha256:c25d9e338d5bed46c1632f851babf3d13c78f49a225462017cf5e11e845c5891", + "sha256:c336d61d2fe74a3195edc1646d53ff1cddd3a9600b09fa6ab75e5514ba4862a7", + "sha256:cc3656283d11540ab0ea01978378e73e10002145117055e03722417aeab30994", + "sha256:cf450f498c30af55551ba4f66b9123b7185362ec8b625a773b3d39aa1a717583", + "sha256:d0ee06b5b5291f609ddb37b9750985b27bc567791bc87c76a569b3feed8481ac", + "sha256:d480de377f5b687b6b1bc0c0407426da556e2a757633cc7e4d2e1a057aa688f3", + "sha256:d56bc4011975f7460bea7b33e1ff425d2f1adf419935ff6707273c77f8a4ada6", + "sha256:dd3c41254ee98604b08bd5b3af5bf0a89740d4ee0711de95b65166bf44091921", + "sha256:e0d138c7ae532908cbb342162b2611dbd4d90c941cd25ab82084aaf71d2c0bd0", + "sha256:e11769a1dbda4da7b00a76cfffa67aa47cfa66921d2724539eee4b9ede780b79", + "sha256:e3f0a41487fd5fad7e760b9e8a90e251e27c2816fbc2cff36a22a0e6bcbbd9dd", + "sha256:e692aa2d1d604e6ca12d35e51fdc36f4cda6345e28e36374579f7ef3611b3012", + "sha256:e70a57ecf89a0f64c24e37f38d3fe217a58169d2fe6ed6d70554964042474023", + "sha256:e96baa6820280077a78244b2e06e416480ed859bbd8e5d641cf5742919d8beb4", + "sha256:eb5656019db7c4deacf0c1a55a898c5bb8f989be904597fcb5232a2f4828fa05", + "sha256:eca45e982fa074090057132e30585a7e8674e9e885d402eae85633e9f449ce6c", + "sha256:f0af2bd2bc204fa27f3d6711d0f360e6b8c684a035206257a81673ab924aa11e", + "sha256:f7cdf7f26c2286ffb02e46d7bac56c94655540b26347673bea15fa52a6af17e9", + "sha256:fd1a720332ea335ceb544cf0a03f81df92abd4bb887679fd1e460976b0e6214b", + "sha256:ff8baf1f8d3f4b6b7257fcb75a501f2a5499d0dda57645baa09d4d0d34b19444" + ], + "markers": "python_version >= '3.9'", + "version": "==0.8.1" + }, + "mypy": { + "hashes": [ + "sha256:016f2246209095e8eda7538944daa1d60e1e8134d98983b9fc1e92c1fc0cb8dd", + "sha256:022ea7279374af1a5d78dfcab853fe6a536eebfda4b59deab53cd21f6cd9f00b", + "sha256:06e6170bd5836770e8104c8fdd58e5e725cfeb309f0a6c681a811f557e97eac1", + "sha256:19d88bb05303fe63f71dd2c6270daca27cb9401c4ca8255fe50d1d920e0eb9ba", + "sha256:21761006a7f497cb0d4de3d8ef4ca70532256688b0523eee02baf9eec895e27b", + "sha256:28902ee51f12e0f19e1e16fbe2f8f06b6637f482c459dd393efddd0ec7f82045", + "sha256:2899753e2f61e571b3971747e302d5f420c3fd09650e1951e99f823bc3089dac", + "sha256:2abb24cf3f17864770d18d673c85235ba52456b36a06b6afc1e07c1fdcd3d0e6", + "sha256:34c81968774648ab5ac09c29a375fdede03ba253f8f8287847bd480782f73a6a", + "sha256:409088884802d511ee52ca067707b90c883426bd95514e8cfda8281dc2effe24", + "sha256:481daf36a4c443332e2ae9c137dfee878fcea781a2e3f895d54bd3002a900957", + "sha256:4b84a7a18f41e167f7995200a1d07a4a6810e89d29859df936f1c3923d263042", + "sha256:4f28f99c824ecebcdaa2e55d82953e38ff60ee5ec938476796636b86afa3956e", + "sha256:5f05aa3d375b385734388e844bc01733bd33c644ab48e9684faa54e5389775ec", + "sha256:7bcfc336a03a1aaa26dfce9fff3e287a3ba99872a157561cbfcebe67c13308e3", + "sha256:804bd67b8054a85447c8954215a906d6eff9cabeabe493fb6334b24f4bfff718", + "sha256:8bb5c6f6d043655e055be9b542aa5f3bdd30e4f3589163e85f93f3640060509f", + "sha256:a009ffa5a621762d0c926a078c2d639104becab69e79538a494bcccb62cc0331", + "sha256:a8174a03289288c1f6c46d55cef02379b478bfbc8e358e02047487cad44c6ca1", + "sha256:ab43590f9cd5108f41aacf9fca31841142c786827a74ab7cc8a2eacb634e09a1", + "sha256:b10e7c2cd7870ba4ad9b2d8a6102eb5ffc1f16ca35e3de6bfa390c1113029d13", + "sha256:b13cfdd6c87fc3efb69ea4ec18ef79c74c3f98b4e5498ca9b85ab3b2c2329a67", + "sha256:b64d987153888790bcdb03a6473d321820597ab8dd9243b27a92153c4fa50fd2", + "sha256:b7951a701c07ea584c4fe327834b92a30825514c868b1f69c30445093fdd9d5a", + "sha256:bdb12f69bcc02700c2b47e070238f42cb87f18c0bc1fc4cdb4fb2bc5fd7a3b8b", + "sha256:c35d298c2c4bba75feb2195655dfea8124d855dfd7343bf8b8c055421eaf0cf8", + "sha256:c608937067d2fc5a4dd1a5ce92fd9e1398691b8c5d012d66e1ddd430e9244376", + "sha256:c9a6538e0415310aad77cb94004ca6482330fece18036b5f360b62c45814c4ef", + "sha256:d8dfc6ab58ca7dda47d9237349157500468e404b17213d44fc1cb77bce532288", + "sha256:da4869fc5e7f62a88f3fe0b5c919d1d9f7ea3cef92d3689de2823fd27e40aa75", + "sha256:de759aafbae8763283b2ee5869c7255391fbc4de3ff171f8f030b5ec48381b74", + "sha256:e3157c7594ff2ef1634ee058aafc56a82db665c9438fd41b390f3bde1ab12250", + "sha256:e3f276d8493c3c97930e354b2595a44a21348b320d859fb4a2b9f66da9ed27ab", + "sha256:ee4c11e460685c3e0c64a4c5de82ae143622410950d6be863303a1c4ba0e36d6", + "sha256:f1235f5ea01b7db5468d53ece6aaddf1ad0b88d9e7462b86ef96fe04995d7247", + "sha256:f7cee03c9a2e2ee26ec07479f38ea9c884e301d42c6d43a19d20fb014e3ba925", + "sha256:f859fb09d9583a985be9a493d5cfc5515b56b08f7447759a0c5deaf68d80506e", + "sha256:ffcebe56eb09ff0c0885e750036a095e23793ba6c2e894e7e63f6d89ad51f22e" ], + "index": "pypi", "markers": "python_version >= '3.9'", - "version": "==0.1.3" - }, - "distro": { - "hashes": [ - "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed", - "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2" - ], - "markers": "python_version >= '3.6'", - "version": "==1.9.0" - }, - "filelock": { - "hashes": [ - "sha256:5ccf8069f7948f494968fc0713c10e5c182a9c9d9eef3a636307a20c2490f047", - "sha256:8f00faf3abf9dc730a1ffe9c354ae5c04e079ab7d3a683b7c32da5dd05f26af3" - ], - "markers": "python_version >= '3.10'", - "version": "==3.25.0" + "version": "==1.19.1" }, - "fsspec": { + "mypy-extensions": { "hashes": [ - "sha256:6544e34b16869f5aacd5b90bdf1a71acb37792ea3ddf6125ee69a22a53fb8bff", - "sha256:98de475b5cb3bd66bedd5c4679e87b4fdfe1a3bf4d707b151b3c07e58c9a2437" - ], - "markers": "python_version >= '3.10'", - "version": "==2026.2.0" - }, - "h11": { - "hashes": [ - "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", - "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86" - ], - "markers": "python_version >= '3.8'", - "version": "==0.16.0" - }, - "hf-xet": { - "hashes": [ - "sha256:06b724a361f670ae557836e57801b82c75b534812e351a87a2c739f77d1e0635", - "sha256:06cdbde243c85f39a63b28e9034321399c507bcd5e7befdd17ed2ccc06dfe14e", - "sha256:1c88fbd90ad0d27c46b77a445f0a436ebaa94e14965c581123b68b1c52f5fd30", - "sha256:211f30098512d95e85ad03ae63bd7dd2c4df476558a5095d09f9e38e78cbf674", - "sha256:305f5489d7241a47e0458ef49334be02411d1d0f480846363c1c8084ed9916f7", - "sha256:3155a02e083aa21fd733a7485c7c36025e49d5975c8d6bda0453d224dd0b0ac4", - "sha256:31612ba0629046e425ba50375685a2586e11fb9144270ebabd75878c3eaf6378", - "sha256:335a8f36c55fd35a92d0062f4e9201b4015057e62747b7e7001ffb203c0ee1d2", - "sha256:35b855024ca37f2dd113ac1c08993e997fbe167b9d61f9ef66d3d4f84015e508", - "sha256:433c77c9f4e132b562f37d66c9b22c05b5479f243a1f06a120c1c06ce8b1502a", - "sha256:4a6817c41de7c48ed9270da0b02849347e089c5ece9a0e72ae4f4b3a57617f82", - "sha256:4bc995d6c41992831f762096020dc14a65fdf3963f86ffed580b596d04de32e3", - "sha256:7c2a054a97c44e136b1f7f5a78f12b3efffdf2eed3abc6746fc5ea4b39511633", - "sha256:83d8ec273136171431833a6957e8f3af496bee227a0fe47c7b8b39c106d1749a", - "sha256:91b1dc03c31cbf733d35dc03df7c5353686233d86af045e716f1e0ea4a2673cf", - "sha256:9298b47cce6037b7045ae41482e703c471ce36b52e73e49f71226d2e8e5685a1", - "sha256:959083c89dee30f7d6f890b36cdadda823386c4de63b1a30384a75bfd2ae995d", - "sha256:a85d3d43743174393afe27835bde0cd146e652b5fcfdbcd624602daef2ef3259", - "sha256:c1980abfb68ecf6c1c7983379ed7b1e2b49a1aaf1a5aca9acc7d48e5e2e0a961", - "sha256:c1ae4d3a716afc774e66922f3cac8206bfa707db13f6a7e62dfff74bfc95c9a8", - "sha256:c34e2c7aefad15792d57067c1c89b2b02c1bbaeabd7f8456ae3d07b4bbaf4094", - "sha256:cfa760888633b08c01b398d212ce7e8c0d7adac6c86e4b20dfb2397d8acd78ee", - "sha256:d6dbdf231efac0b9b39adcf12a07f0c030498f9212a18e8c50224d0e84ab803d", - "sha256:e130ee08984783d12717444e538587fa2119385e5bd8fc2bb9f930419b73a7af", - "sha256:f93b7595f1d8fefddfede775c18b5c9256757824f7f6832930b49858483cd56f" + "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", + "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558" ], "markers": "python_version >= '3.8'", - "version": "==1.3.2" + "version": "==1.1.0" }, - "httpcore": { + "packaging": { "hashes": [ - "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", - "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8" + "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4", + "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529" ], "markers": "python_version >= '3.8'", - "version": "==1.0.9" + "version": "==26.0" }, - "httpx": { + "pathspec": { "hashes": [ - "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", - "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad" + "sha256:0210e2ae8a21a9137c0d470578cb0e595af87edaa6ebf12ff176f14a02e0e645", + "sha256:fb6ae2fd4e7c921a165808a552060e722767cfa526f99ca5156ed2ce45a5c723" ], - "markers": "python_version >= '3.8'", - "version": "==0.28.1" + "markers": "python_version >= '3.9'", + "version": "==1.0.4" }, - "huggingface-hub": { + "pluggy": { "hashes": [ - "sha256:c9c0b3ab95a777fc91666111f3b3ede71c0cdced3614c553a64e98920585c4ee", - "sha256:f281838db29265880fb543de7a23b0f81d3504675de82044307ea3c6c62f799d" + "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", + "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746" ], - "markers": "python_full_version >= '3.9.0'", - "version": "==1.5.0" + "markers": "python_version >= '3.9'", + "version": "==1.6.0" }, - "idna": { + "pygments": { "hashes": [ - "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", - "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902" + "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", + "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b" ], "markers": "python_version >= '3.8'", - "version": "==3.11" + "version": "==2.19.2" }, - "iniconfig": { + "pytest": { "hashes": [ - "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", - "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12" + "sha256:711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b", + "sha256:75186651a92bd89611d1d9fc20f0b4345fd827c41ccd5c299a868a05d70edf11" ], + "index": "pypi", "markers": "python_version >= '3.10'", - "version": "==2.3.0" - }, - "jinja2": { - "hashes": [ - "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", - "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67" - ], - "markers": "python_version >= '3.7'", - "version": "==3.1.6" - }, - "jiter": { - "hashes": [ - "sha256:00203f47c214156df427b5989de74cb340c65c8180d09be1bf9de81d0abad599", - "sha256:04670992b576fa65bd056dbac0c39fe8bd67681c380cb2b48efa885711d9d726", - "sha256:0733312953b909688ae3c2d58d043aa040f9f1a6a75693defed7bc2cc4bf2654", - "sha256:07b75fe09a4ee8e0c606200622e571e44943f47254f95e2436c8bdcaceb36d7d", - "sha256:0a2bd69fc1d902e89925fc34d1da51b2128019423d7b339a45d9e99c894e0663", - "sha256:0a8d76c7524087272c8ae913f5d9d608bd839154b62c4322ef65723d2e5bb0b8", - "sha256:0b34c519e17658ed88d5047999a93547f8889f3c1824120c26ad6be5f27b6cf5", - "sha256:0bf670e3b1445fc4d31612199f1744f67f889ee1bbae703c4b54dc097e5dd394", - "sha256:0c365005b05505a90d1c47856420980d0237adf82f70c4aff7aebd3c1cc143ad", - "sha256:0e3a5f0cde8ff433b8e88e41aa40131455420fb3649a3c7abdda6145f8cb7202", - "sha256:0f0c065695f616a27c920a56ad0d4fc46415ef8b806bf8fc1cacf25002bd24e1", - "sha256:1211427574b17b633cfceba5040de8081e5abf114f7a7602f73d2e16f9fdaa59", - "sha256:1317fdffd16f5873e46ce27d0e0f7f4f90f0cdf1d86bf6abeaea9f63ca2c401d", - "sha256:15db60e121e11fe186c0b15236bd5d18381b9ddacdcf4e659feb96fc6c969c92", - "sha256:19928b5d1ce0ff8c1ee1b9bdef3b5bfc19e8304f1b904e436caf30bc15dc6cf5", - "sha256:19cd6f85e1dc090277c3ce90a5b7d96f32127681d825e71c9dce28788e39fc0c", - "sha256:1f4748aad1b4a93c8bdd70f604d0f748cdc0e8744c5547798acfa52f10e79228", - "sha256:1f8a55b848cbabf97d861495cd65f1e5c590246fabca8b48e1747c4dfc8f85bf", - "sha256:2113c17c9a67071b0f820733c0893ed1d467b5fcf4414068169e5c2cabddb1e2", - "sha256:24ab43126d5e05f3d53a36a8e11eb2f23304c6c1117844aaaf9a0aa5e40b5018", - "sha256:24dc96eca9f84da4131cdf87a95e6ce36765c3b156fc9ae33280873b1c32d5f6", - "sha256:2b4972c6df33731aac0742b64fd0d18e0a69bc7d6e03108ce7d40c85fd9e3e6d", - "sha256:2c26cf47e2cad140fa23b6d58d435a7c0161f5c514284802f25e87fddfe11024", - "sha256:2d08c9475d48b92892583df9da592a0e2ac49bcd41fae1fec4f39ba6cf107820", - "sha256:2ffc63785fd6c7977defe49b9824ae6ce2b2e2b77ce539bdaf006c26da06342e", - "sha256:309549b778b949d731a2f0e1594a3f805716be704a73bf3ad9a807eed5eb5721", - "sha256:3097d665a27bc96fd9bbf7f86178037db139f319f785e4757ce7ccbf390db6c2", - "sha256:36ebfbcffafb146d0e6ffb3e74d51e03d9c35ce7c625c8066cdbfc7b953bdc72", - "sha256:3b3fb8c2053acaef8580809ac1d1f7481a0a0bdc012fd7f5d8b18fb696a5a089", - "sha256:3d744a6061afba08dd7ae375dcde870cffb14429b7477e10f67e9e6d68772a0a", - "sha256:41f92313d17989102f3cb5dd533a02787cdb99454d494344b0361355da52fcb9", - "sha256:4397ee562b9f69d283e5674445551b47a5e8076fdde75e71bfac5891113dc543", - "sha256:45f6f8efb2f3b0603092401dc2df79fa89ccbc027aaba4174d2d4133ed661434", - "sha256:47455245307e4debf2ce6c6e65a717550a0244231240dcf3b8f7d64e4c2f22f4", - "sha256:4a638816427006c1e3f0013eb66d391d7a3acda99a7b0cf091eff4497ccea33a", - "sha256:5467696f6b827f1116556cb0db620440380434591e93ecee7fd14d1a491b6daa", - "sha256:57aab48f40be1db920a582b30b116fe2435d184f77f0e4226f546794cedd9cf0", - "sha256:597245258e6ad085d064780abfb23a284d418d3e61c57362d9449c6c7317ee2d", - "sha256:5a1aff1fbdb803a376d4d22a8f63f8e7ccbce0b4890c26cc7af9e501ab339ef0", - "sha256:5d9b34ad56761b3bf0fbe8f7e55468704107608512350962d3317ffd7a4382d5", - "sha256:6207fc61c395b26fffdcf637a0b06b4326f35bfa93c6e92fe1a166a21aeb6731", - "sha256:632bf7c1d28421c00dd8bbb8a3bac5663e1f57d5cd5ed962bce3c73bf62608e6", - "sha256:66aa3e663840152d18cc8ff1e4faad3dd181373491b9cfdc6004b92198d67911", - "sha256:682161a67adea11e3aae9038c06c8b4a9a71023228767477d683f69903ebc607", - "sha256:6c26a424569a59140fb51160a56df13f438a2b0967365e987889186d5fc2f6f9", - "sha256:6eeb7db8bc77dc20476bc2f7407a23dbe3d46d9cc664b166e3d474e1c1de4baa", - "sha256:701a1e77d1e593c1b435315ff625fd071f0998c5f02792038a5ca98899261b7d", - "sha256:775e10de3849d0631a97c603f996f518159272db00fdda0a780f81752255ee9d", - "sha256:7772115877c53f62beeb8fd853cab692dbc04374ef623b30f997959a4c0e7e95", - "sha256:7b88d649135aca526da172e48083da915ec086b54e8e73a425ba50999468cc08", - "sha256:7bb00b6d26db67a05fe3e12c76edc75f32077fb51deed13822dc648fa373bc19", - "sha256:7beae3a3d3b5212d3a55d2961db3c292e02e302feb43fce6a3f7a31b90ea6dfe", - "sha256:7c26ad6967c9dcedf10c995a21539c3aa57d4abad7001b7a84f621a263a6b605", - "sha256:7f90023f8f672e13ea1819507d2d21b9d2d1c18920a3b3a5f1541955a85b5504", - "sha256:879e768938e7b49b5e90b7e3fecc0dbec01b8cb89595861fb39a8967c5220d09", - "sha256:87ce0f14c6c08892b610686ae8be350bf368467b6acd5085a5b65441e2bf36d2", - "sha256:8d76029f077379374cf0dbc78dbe45b38dec4a2eb78b08b5194ce836b2517afc", - "sha256:9621ca242547edc16400981ca3231e0c91c0c4c1ab8573a596cd9bb3575d5c2b", - "sha256:964538479359059a35fb400e769295d4b315ae61e4105396d355a12f7fef09f0", - "sha256:9776ebe51713acf438fd9b4405fcd86893ae5d03487546dae7f34993217f8a91", - "sha256:98fbafb6e88256f4454de33c1f40203d09fc33ed19162a68b3b257b29ca7f663", - "sha256:9950290340acc1adaded363edd94baebcee7dabdfa8bee4790794cd5cfad2af6", - "sha256:9d01ecc3a8cbdb6f25a37bd500510550b64ddf9f7d64a107d92f3ccb25035d0f", - "sha256:9da38b4fedde4fb528c740c2564628fbab737166a0e73d6d46cb4bb5463ff411", - "sha256:9ffda299e417dc83362963966c50cb76d42da673ee140de8a8ac762d4bb2378b", - "sha256:a13b68cd1cd8cc9de8f244ebae18ccb3e4067ad205220ef324c39181e23bbf66", - "sha256:a3a377af27b236abbf665a69b2bdd680e3b5a0bd2af825cd3b81245279a7606c", - "sha256:a576f5dce9ac7de5d350b8e2f552cf364f32975ed84717c35379a51c7cb198bd", - "sha256:a7637d92b1c9d7a771e8c56f445c7f84396d48f2e756e5978840ecba2fac0894", - "sha256:ab1185ca5c8b9491b55ebf6c1e8866b8f68258612899693e24a92c5fdb9455d5", - "sha256:ab44b178f7981fcaea7e0a5df20e773c663d06ffda0198f1a524e91b2fde7e59", - "sha256:ade8cb6ff5632a62b7dbd4757d8c5573f7a2e9ae285d6b5b841707d8363205ef", - "sha256:aed40e099404721d7fcaf5b89bd3b4568a4666358bcac7b6b15c09fb6252ab68", - "sha256:b1cbfa133241d0e6bdab48dcdc2604e8ba81512f6bbd68ec3e8e1357dd3c316c", - "sha256:b22945be8425d161f2e536cdae66da300b6b000f1c0ba3ddf237d1bfd45d21b8", - "sha256:bb7613e1a427cfcb6ea4544f9ac566b93d5bf67e0d48c787eca673ff9c9dff2b", - "sha256:bcdabaea26cb04e25df3103ce47f97466627999260290349a88c8136ecae0060", - "sha256:bdaba7d87e66f26a2c45d8cbadcbfc4bf7884182317907baf39cfe9775bb4d93", - "sha256:c05b450d37ba0c9e21c77fef1f205f56bcee2330bddca68d344baebfc55ae0df", - "sha256:c1b609e5cbd2f52bb74fb721515745b407df26d7b800458bd97cb3b972c29e7d", - "sha256:c1e2b199f446d3e82246b4fd9236d7cb502dc2222b18698ba0d986d2fecc6152", - "sha256:c3524798e70655ff19aec58c7d05adb1f074fecff62da857ea9be2b908b6d701", - "sha256:cc5223ab19fe25e2f0bf2643204ad7318896fe3729bf12fde41b77bfc4fafff0", - "sha256:d2a6394e6af690d462310a86b53c47ad75ac8c21dc79f120714ea449979cb1d3", - "sha256:db367d8be9fad6e8ebbac4a7578b7af562e506211036cba2c06c3b998603c3d2", - "sha256:dc3ce84cfd4fa9628fe62c4f85d0d597a4627d4242cfafac32a12cc1455d00f7", - "sha256:e104da1db1c0991b3eaed391ccd650ae8d947eab1480c733e5a3fb28d4313e40", - "sha256:e404ea551d35438013c64b4f357b0474c7abf9f781c06d44fcaf7a14c69ff9e2", - "sha256:e5562a0f0e90a6223b704163ea28e831bd3a9faa3512a711f031611e6b06c939", - "sha256:ea026e70a9a28ebbdddcbcf0f1323128a8db66898a06eaad3a4e62d2f554d096", - "sha256:ec7e287d7fbd02cb6e22f9a00dd9c9cd504c40a61f2c61e7e1f9690a82726b4c", - "sha256:ed0240dd1536a98c3ab55e929c60dfff7c899fecafcb7d01161b21a99fc8c363", - "sha256:ed9bbc30f5d60a3bdf63ae76beb3f9db280d7f195dfcfa61af792d6ce912d159", - "sha256:ee9da221dca6e0429c2704c1b3655fe7b025204a71d4d9b73390c759d776d165", - "sha256:f22ef501c3f87ede88f23f9b11e608581c14f04db59b6a801f354397ae13739f", - "sha256:f2839f9c2c7e2dffc1bc5929a510e14ce0a946be9365fd1219e7ef342dae14f4", - "sha256:f556aa591c00f2c45eb1b89f68f52441a016034d18b65da60e2d2875bbbf344a", - "sha256:f7e1d61da332ec412350463891923f960c3073cf1aae93b538f0bb4c8cd46efb", - "sha256:f917a04240ef31898182f76a332f508f2cc4b57d2b4d7ad2dbfebbfe167eb505", - "sha256:fa476ab5dd49f3bf3a168e05f89358c75a17608dbabb080ef65f96b27c19ab10", - "sha256:fe49d3ff6db74321f144dff9addd4a5874d3105ac5ba7c5b77fac099cfae31ae", - "sha256:ff732bd0a0e778f43d5009840f20b935e79087b4dc65bd36f1cd0f9b04b8ff7f" - ], - "markers": "python_version >= '3.9'", - "version": "==0.13.0" + "version": "==9.0.2" }, - "llm": { - "hashes": [ - "sha256:7d70c22f2dbfe47123a67328eea9c25add8f0a3c6a439f7d452219edf2e4dd76", - "sha256:e3d8bcc0f016fae8aeca1d702491a1891523702983459cb66afec99d74cabfc1" + "ruff": { + "hashes": [ + "sha256:04196ad44f0df220c2ece5b0e959c2f37c777375ec744397d21d15b50a75264f", + "sha256:291258c917539e18f6ba40482fe31d6f5ac023994ee11d7bdafd716f2aab8a68", + "sha256:3412195319e42d634470cc97aa9803d07e9d5c9223b99bcb1518f0c725f26ae1", + "sha256:3f1c4893841ff2d54cbda1b2860fa3260173df5ddd7b95d370186f8a5e66a4ac", + "sha256:3f83c45911da6f2cd5936c436cf86b9f09f09165f033a99dcf7477e34041cbc3", + "sha256:451a2e224151729b3b6c9ffb36aed9091b2996fe4bdbd11f47e27d8f2e8888ec", + "sha256:5a1632c66672b8b4d3e1d1782859e98d6e0b4e70829530666644286600a33992", + "sha256:60d5177e8cfc70e51b9c5fad936c634872a74209f934c1e79107d11787ad5453", + "sha256:65594a2d557d4ee9f02834fcdf0a28daa8b3b9f6cb2cb93846025a36db47ef22", + "sha256:820b8766bd65503b6c30aaa6331e8ef3a6e564f7999c844e9a547c40179e440a", + "sha256:917cc68503357021f541e69b35361c99387cdbbf99bd0ea4aa6f28ca99ff5338", + "sha256:a1810931c41606c686bae8b5b9a8072adac2f611bb433c0ba476acba17a332e0", + "sha256:a4386ba2cd6c0f4ff75252845906acc7c7c8e1ac567b7bc3d373686ac8c222ba", + "sha256:a8f157f2e583c513c4f5f896163a93198297371f34c04220daf40d133fdd4f7f", + "sha256:b2496488bdfd3732747558b6f95ae427ff066d1fcd054daf75f5a50674411e75", + "sha256:c9fb74bab47139c1751f900f857fa503987253c3ef89129b24ed375e72873e85", + "sha256:e9737c8161da79fd7cfec19f1e35620375bd8b2a50c3e77fa3d2c16f574105cc", + "sha256:f80c98765949c518142b3a50a5db89343aa90f2c2bf7799de9986498ae6176db" ], "index": "pypi", - "markers": "python_version >= '3.10'", - "version": "==0.28" + "markers": "python_version >= '3.7'", + "version": "==0.15.4" }, - "llm-mlx": { + "types-requests": { "hashes": [ - "sha256:42b433a2e98eaaf3070d9186f4e961a5990507b73b848aa684612723afc3df34", - "sha256:ee3b1fb203c9bf18fe6a4b39d8a8787a2967429102baaf51f36d8090a9b257ba" + "sha256:018a11ac158f801bfa84857ddec1650750e393df8a004a8a9ae2a9bec6fcb24f", + "sha256:b703fe72f8ce5b31ef031264fe9395cac8f46a04661a79f7ed31a80fb308730d" ], "index": "pypi", "markers": "python_version >= '3.9'", - "version": "==0.4" - }, - "markdown-it-py": { - "hashes": [ - "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", - "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3" - ], - "markers": "python_version >= '3.10'", - "version": "==4.0.0" + "version": "==2.32.4.20260107" }, - "markupsafe": { + "typing-extensions": { "hashes": [ - "sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f", - "sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a", - "sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf", - "sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19", - "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf", - "sha256:0f4b68347f8c5eab4a13419215bdfd7f8c9b19f2b25520968adfad23eb0ce60c", - "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175", - "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219", - "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb", - "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6", - "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab", - "sha256:15d939a21d546304880945ca1ecb8a039db6b4dc49b2c5a400387cdae6a62e26", - "sha256:177b5253b2834fe3678cb4a5f0059808258584c559193998be2601324fdeafb1", - "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce", - "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218", - "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634", - "sha256:1ba88449deb3de88bd40044603fafffb7bc2b055d626a330323a9ed736661695", - "sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad", - "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73", - "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c", - "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe", - "sha256:2a15a08b17dd94c53a1da0438822d70ebcd13f8c3a95abe3a9ef9f11a94830aa", - "sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559", - "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", - "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37", - "sha256:3537e01efc9d4dccdf77221fb1cb3b8e1a38d5428920e0657ce299b20324d758", - "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f", - "sha256:38664109c14ffc9e7437e86b4dceb442b0096dfe3541d7864d9cbe1da4cf36c8", - "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d", - "sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c", - "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97", - "sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a", - "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19", - "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9", - "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9", - "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc", - "sha256:591ae9f2a647529ca990bc681daebdd52c8791ff06c2bfa05b65163e28102ef2", - "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4", - "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354", - "sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50", - "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", - "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9", - "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b", - "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc", - "sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115", - "sha256:7c3fb7d25180895632e5d3148dbdc29ea38ccb7fd210aa27acbd1201a1902c6e", - "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485", - "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f", - "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12", - "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025", - "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009", - "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d", - "sha256:949b8d66bc381ee8b007cd945914c721d9aba8e27f71959d750a46f7c282b20b", - "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a", - "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5", - "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f", - "sha256:a320721ab5a1aba0a233739394eb907f8c8da5c98c9181d1161e77a0c8e36f2d", - "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1", - "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287", - "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6", - "sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f", - "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581", - "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed", - "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b", - "sha256:c0c0b3ade1c0b13b936d7970b1d37a57acde9199dc2aecc4c336773e1d86049c", - "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026", - "sha256:c4ffb7ebf07cfe8931028e3e4c85f0357459a3f9f9490886198848f4fa002ec8", - "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676", - "sha256:d2ee202e79d8ed691ceebae8e0486bd9a2cd4794cec4824e1c99b6f5009502f6", - "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e", - "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d", - "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d", - "sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01", - "sha256:df2449253ef108a379b8b5d6b43f4b1a8e81a061d6537becd5582fba5f9196d7", - "sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419", - "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795", - "sha256:e2103a929dfa2fcaf9bb4e7c091983a49c9ac3b19c9061b6d5427dd7d14d81a1", - "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5", - "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d", - "sha256:e8fc20152abba6b83724d7ff268c249fa196d8259ff481f3b1476383f8f24e42", - "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe", - "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda", - "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e", - "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737", - "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523", - "sha256:f42d0984e947b8adf7dd6dde396e720934d12c506ce84eea8476409563607591", - "sha256:f71a396b3bf33ecaa1626c255855702aca4d3d9fea5e051b41ac59a9c1c41edc", - "sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a", - "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50" + "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", + "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548" ], "markers": "python_version >= '3.9'", - "version": "==3.0.3" - }, - "mdurl": { - "hashes": [ - "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", - "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba" - ], - "markers": "python_version >= '3.7'", - "version": "==0.1.2" - }, - "mlx": { - "hashes": [ - "sha256:18078bc67dfb7ed602fca233d00ce93e23d590d9347da5009472455a92831066", - "sha256:1ad14ddc3a15818f5bba0de35e88559ed8dcb93ccff2ef879ff604d02d663b25", - "sha256:242806b8ad6a4d3ce86cdff513f86520552de7592786712770b2e1ebd178816a", - "sha256:285313eaeba425e58cbb3238c2d1a3894e6252d58f243ce56681d5419a568d6c", - "sha256:363282eb094785f6aba27810ff89331c0f7829c6961f571cd0feaad09d2c809f", - "sha256:38680838e0dd9a621ed4adc5a9ed8b94aeb6a4798142fbe215b821b8c6b8fc36", - "sha256:4f33e9aafc6d3ad29e72743dfb786c4ce67397414f0a091469058626381fc1bc", - "sha256:5b5306a0934b15c4e3a1088a10066bdde3966c21b95006c63ecc38ca8e3891e0", - "sha256:6a4342027e6608ce69807a8f079c750a7c6161f543ebb49e55654edd03c178d6", - "sha256:6e3ae83607b798b44cb3e44437095cfd26886fecc15f90f29f9eafd206d4d170", - "sha256:7aded590bcf6839307c3acc899e196936991f97b499ddbdd0cd3b228bf10792f", - "sha256:7f0bdbac084017820ce513a12318771a06c7ec10fad159839e27c998bc5dad89", - "sha256:8642dda2b23195d9921973749ae9bf764e2c7d70bfc0e60b23b6335e660cc610", - "sha256:994fab25ff521621e03001177a8f0f1a7bf8294ff340f89910ec074f9f681ed9", - "sha256:a80754ecf64191f71da1946dc5de6cf903344cc90dd286c589792ee9d3fc62f9", - "sha256:acf4f04ff33a80784a0f15c492166dc889e65659b41c410ca5a7c2d78bee2a3a", - "sha256:b25f785c94eb47d8104604a5de0e7d749b801e7a40073cbf457aa94c372e5593", - "sha256:ba330fe40d73b202880bbb5cac62de0b639cf4c44a12853bcadb34a9e3ffe880", - "sha256:c3bb9961f40d098659326b0edb96e2a16adecfaf3c1f2518cad5a0b7e55a3a5d", - "sha256:c6daa671cfa3c194951d742aa09030c5008d9d9657034b2903389fa090b3ba92", - "sha256:cce3e15cf11c608c9e721502fe56e54f9f48b897e9b80f1204a48643d68710c0", - "sha256:d2014d113070846c6cdee980653f561c92a4a663a449f64e70c15bbf74d637e1", - "sha256:d6af01b15177da995336a6fd9878e7c5994720a9f1614d8f4d1dbe9293167c30", - "sha256:de6c0a3e8aa0e7d1365d46634fdbb3f835c164fbdb6ba8a239e039a4efa07fe2", - "sha256:f624571e23a86654496c42a507b4bb42ded0edb91f33161fabafdbf6b81ba024" - ], - "markers": "python_version >= '3.10'", - "version": "==0.31.0" - }, - "mlx-lm": { - "hashes": [ - "sha256:17442a4bf01c4c2d3bca1e647712fe44f19890c3f1eadc8589d389e57b44b9bf", - "sha256:e5f31ac58d9f2381f28e1ba639ff903e64f7cff1bdc245c0bc97f72264be329c" - ], - "markers": "python_version >= '3.8'", - "version": "==0.30.7" + "version": "==4.15.0" }, - "mlx-metal": { + "urllib3": { "hashes": [ - "sha256:1c572a6e3634a63060c103b0c38ac309e2d217be15519e3d8f0d6b452bb015f5", - "sha256:554dc7cb29e0ea5fb6941df42f11a1de385b095848e6183c7a99d7c1f1a11f5d", - "sha256:7fd412f55ddf9f1d90c2cd86ce281d19e8eb93d093c6dbd784a49f8bd7d0a22c" - ], - "markers": "python_version >= '3.10'", - "version": "==0.31.0" - }, - "numpy": { - "hashes": [ - "sha256:00ab83c56211a1d7c07c25e3217ea6695e50a3e2f255053686b081dc0b091a82", - "sha256:068cdb2d0d644cdb45670810894f6a0600797a69c05f1ac478e8d31670b8ee75", - "sha256:0f01dcf33e73d80bd8dc0f20a71303abbafa26a19e23f6b68d1aa9990af90257", - "sha256:0fece1d1f0a89c16b03442eae5c56dc0be0c7883b5d388e0c03f53019a4bfd71", - "sha256:12e26134a0331d8dbd9351620f037ec470b7c75929cb8a1537f6bfe411152a1a", - "sha256:1ae241bbfc6ae276f94a170b14785e561cb5e7f626b6688cf076af4110887413", - "sha256:1f92f53998a17265194018d1cc321b2e96e900ca52d54c7c77837b71b9465181", - "sha256:209fae046e62d0ce6435fcfe3b1a10537e858249b3d9b05829e2a05218296a85", - "sha256:20abd069b9cda45874498b245c8015b18ace6de8546bf50dfa8cea1696ed06ef", - "sha256:21982668592194c609de53ba4933a7471880ccbaadcc52352694a59ecc860b3a", - "sha256:25f2059807faea4b077a2b6837391b5d830864b3543627f381821c646f31a63c", - "sha256:2653de5c24910e49c2b106499803124dde62a5a1fe0eedeaecf4309a5f639390", - "sha256:2b8f157c8a6f20eb657e240f8985cc135598b2b46985c5bccbde7616dc9c6b1e", - "sha256:2fb882da679409066b4603579619341c6d6898fc83a8995199d5249f986e8e8f", - "sha256:40397bda92382fcec844066efb11f13e1c9a3e2a8e8f318fb72ed8b6db9f60f1", - "sha256:444be170853f1f9d528428eceb55f12918e4fda5d8805480f36a002f1415e09b", - "sha256:47c5a6ed21d9452b10227e5e8a0e1c22979811cad7dcc19d8e3e2fb8fa03f1a3", - "sha256:4f069069931240b3fc703f1e23df63443dbd6390614c8c44a87d96cd0ec81eb1", - "sha256:52b913ec40ff7ae845687b0b34d8d93b60cb66dcee06996dd5c99f2fc9328657", - "sha256:5633c0da313330fd20c484c78cdd3f9b175b55e1a766c4a174230c6b70ad8262", - "sha256:5daf6f3914a733336dab21a05cdec343144600e964d2fcdabaac0c0269874b2a", - "sha256:5eea80d908b2c1f91486eb95b3fb6fab187e569ec9752ab7d9333d2e66bf2d6b", - "sha256:602f65afdef699cda27ec0b9224ae5dc43e328f4c24c689deaf77133dbee74d0", - "sha256:659a6107e31a83c4e33f763942275fd278b21d095094044eb35569e86a21ddae", - "sha256:66cb9422236317f9d44b67b4d18f44efe6e9c7f8794ac0462978513359461554", - "sha256:6d82351358ffbcdcd7b686b90742a9b86632d6c1c051016484fa0b326a0a1548", - "sha256:6e9f61981ace1360e42737e2bae58b27bf28a1b27e781721047d84bd754d32e7", - "sha256:6ed0be1ee58eef41231a5c943d7d1375f093142702d5723ca2eb07db9b934b05", - "sha256:7cdde6de52fb6664b00b056341265441192d1291c130e99183ec0d4b110ff8b1", - "sha256:7df2de1e4fba69a51c06c28f5a3de36731eb9639feb8e1cf7e4a7b0daf4cf622", - "sha256:7edc794af8b36ca37ef5fcb5e0d128c7e0595c7b96a2318d1badb6fcd8ee86b1", - "sha256:7f54844851cdb630ceb623dcec4db3240d1ac13d4990532446761baede94996a", - "sha256:805cc8de9fd6e7a22da5aed858e0ab16be5a4db6c873dde1d7451c541553aa27", - "sha256:8906e71fd8afcb76580404e2a950caef2685df3d2a57fe82a86ac8d33cc007ba", - "sha256:89f7268c009bc492f506abd6f5265defa7cb3f7487dc21d357c3d290add45082", - "sha256:8c50dd1fc8826f5b26a5ee4d77ca55d88a895f4e4819c7ecc2a9f5905047a443", - "sha256:8e4549f8a3c6d13d55041925e912bfd834285ef1dd64d6bc7d542583355e2e98", - "sha256:8e9afaeb0beff068b4d9cd20d322ba0ee1cecfb0b08db145e4ab4dd44a6b5110", - "sha256:98f16a80e917003a12c0580f97b5f875853ebc33e2eaa4bccfc8201ac6869308", - "sha256:9e35d3e0144137d9fdae62912e869136164534d64a169f86438bc9561b6ad49f", - "sha256:9e4424677ce4b47fe73c8b5556d876571f7c6945d264201180db2dc34f676ab5", - "sha256:adb6ed2ad29b9e15321d167d152ee909ec73395901b70936f029c3bc6d7f4460", - "sha256:aea4f66ff44dfddf8c2cffd66ba6538c5ec67d389285292fe428cb2c738c8aef", - "sha256:b21041e8cb6a1eb5312dd1d2f80a94d91efffb7a06b70597d44f1bd2dfc315ab", - "sha256:b2f0073ed0868db1dcd86e052d37279eef185b9c8db5bf61f30f46adac63c909", - "sha256:b3a24467af63c67829bfaa61eecf18d5432d4f11992688537be59ecd6ad32f5e", - "sha256:b9c618d56a29c9cb1c4da979e9899be7578d2e0b3c24d52079c166324c9e8695", - "sha256:bba37bc29d4d85761deed3954a1bc62be7cf462b9510b51d367b769a8c8df325", - "sha256:bd3a7a9f5847d2fb8c2c6d1c862fa109c31a9abeca1a3c2bd5a64572955b2979", - "sha256:be71bf1edb48ebbbf7f6337b5bfd2f895d1902f6335a5830b20141fc126ffba0", - "sha256:c02ef4401a506fb60b411467ad501e1429a3487abca4664871d9ae0b46c8ba32", - "sha256:c3cd545784805de05aafe1dde61752ea49a359ccba9760c1e5d1c88a93bbf2b7", - "sha256:c7ac672d699bf36275c035e16b65539931347d68b70667d28984c9fb34e07fa7", - "sha256:cb7bbb88aa74908950d979eeaa24dbdf1a865e3c7e45ff0121d8f70387b55f73", - "sha256:cd2bd2bbed13e213d6b55dc1d035a4f91748a7d3edc9480c13898b0353708920", - "sha256:cda077c2e5b780200b6b3e09d0b42205a3d1c68f30c6dceb90401c13bff8fe74", - "sha256:cf28c0c1d4c4bf00f509fa7eb02c58d7caf221b50b467bcb0d9bbf1584d5c821", - "sha256:d0d9b7c93578baafcbc5f0b83eaf17b79d345c6f36917ba0c67f45226911d499", - "sha256:d1240d50adff70c2a88217698ca844723068533f3f5c5fa6ee2e3220e3bdb000", - "sha256:d30291931c915b2ab5717c2974bb95ee891a1cf22ebc16a8006bd59cd210d40a", - "sha256:d9f64d786b3b1dd742c946c42d15b07497ed14af1a1f3ce840cce27daa0ce913", - "sha256:da6cad4e82cb893db4b69105c604d805e0c3ce11501a55b5e9f9083b47d2ffe8", - "sha256:df1b10187212b198dd45fa943d8985a3c8cf854aed4923796e0e019e113a1bda", - "sha256:e04ae107ac591763a47398bb45b568fc38f02dbc4aa44c063f67a131f99346cb", - "sha256:e6dee3bb76aa4009d5a912180bf5b2de012532998d094acee25d9cb8dee3e44a", - "sha256:e7e88598032542bd49af7c4747541422884219056c268823ef6e5e89851c8825", - "sha256:e98c97502435b53741540a5717a6749ac2ada901056c7db951d33e11c885cc7d", - "sha256:ec055f6dae239a6299cace477b479cca2fc125c5675482daf1dd886933a1076f", - "sha256:f74f0f7779cc7ae07d1810aab8ac6b1464c3eafb9e283a40da7309d5e6e48fbb", - "sha256:fbde1b0c6e81d56f5dccd95dd4a711d9b95df1ae4009a60887e56b27e8d903fa", - "sha256:fcf92bee92742edd401ba41135185866f7026c502617f422eb432cfeca4fe236", - "sha256:fd49860271d52127d61197bb50b64f58454e9f578cb4b2c001a6de8b1f50b0b1" - ], - "markers": "python_version >= '3.11'", - "version": "==2.4.2" - }, - "openai": { - "hashes": [ - "sha256:1e5769f540dbd01cb33bc4716a23e67b9d695161a734aff9c5f925e2bf99a673", - "sha256:fed30480d7d6c884303287bde864980a4b137b60553ffbcf9ab4a233b7a73d94" - ], - "markers": "python_version >= '3.9'", - "version": "==2.24.0" - }, - "packaging": { - "hashes": [ - "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4", - "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529" - ], - "markers": "python_version >= '3.8'", - "version": "==26.0" - }, - "pip": { - "hashes": [ - "sha256:bdb1b08f4274833d62c1aa29e20907365a2ceb950410df15fc9521bad440122b", - "sha256:c4037d8a277c89b320abe636d59f91e6d0922d08a05b60e85e53b296613346d8" - ], - "markers": "python_version >= '3.9'", - "version": "==26.0.1" - }, - "pluggy": { - "hashes": [ - "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", - "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746" - ], - "markers": "python_version >= '3.9'", - "version": "==1.6.0" - }, - "protobuf": { - "hashes": [ - "sha256:3871a3df67c710aaf7bb8d214cc997342e63ceebd940c8c7fc65c9b3d697591a", - "sha256:4a72a8ec94e7a9f7ef7fe818ed26d073305f347f8b3b5ba31e22f81fd85fca02", - "sha256:8e329966799f2c271d5e05e236459fe1cbfdb8755aaa3b0914fa60947ddea408", - "sha256:964cf977e07f479c0697964e83deda72bcbc75c3badab506fb061b352d991b01", - "sha256:9d7a5005fb96f3c1e64f397f91500b0eb371b28da81296ae73a6b08a5b76cdd6", - "sha256:9f9079f1dde4e32342ecbd1c118d76367090d4aaa19da78230c38101c5b3dd40", - "sha256:e3b914dd77fa33fa06ab2baa97937746ab25695f389869afdf03e81f34e45dc7", - "sha256:f791ec509707a1d91bd02e07df157e75e4fb9fbdad12a81b7396201ec244e2e3" - ], - "markers": "python_version >= '3.10'", - "version": "==7.34.0" - }, - "puremagic": { - "hashes": [ - "sha256:224fe42b6b3467276a45914e12b5f40905dea0e87963adbe5289667e7c607851", - "sha256:c86aee5c15d6a346e72c5b964f1d930d42bc7dc058afdf4ac63ab92f26086aaf" - ], - "markers": "python_version >= '3.12'", - "version": "==2.0.0" - }, - "pydantic": { - "hashes": [ - "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49", - "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d" - ], - "markers": "python_version >= '3.9'", - "version": "==2.12.5" - }, - "pydantic-core": { - "hashes": [ - "sha256:0177272f88ab8312479336e1d777f6b124537d47f2123f89cb37e0accea97f90", - "sha256:01a3d0ab748ee531f4ea6c3e48ad9dac84ddba4b0d82291f87248f2f9de8d740", - "sha256:0384e2e1021894b1ff5a786dbf94771e2986ebe2869533874d7e43bc79c6f504", - "sha256:03b77d184b9eb40240ae9fd676ca364ce1085f203e1b1256f8ab9984dca80a84", - "sha256:03ca43e12fab6023fc79d28ca6b39b05f794ad08ec2feccc59a339b02f2b3d33", - "sha256:05a2c8852530ad2812cb7914dc61a1125dc4e06252ee98e5638a12da6cc6fb6c", - "sha256:070259a8818988b9a84a449a2a7337c7f430a22acc0859c6b110aa7212a6d9c0", - "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e", - "sha256:0cbaad15cb0c90aa221d43c00e77bb33c93e8d36e0bf74760cd00e732d10a6a0", - "sha256:100baa204bb412b74fe285fb0f3a385256dad1d1879f0a5cb1499ed2e83d132a", - "sha256:112e305c3314f40c93998e567879e887a3160bb8689ef3d2c04b6cc62c33ac34", - "sha256:16f80f7abe3351f8ea6858914ddc8c77e02578544a0ebc15b4c2e1a0e813b0b2", - "sha256:1746d4a3d9a794cacae06a5eaaccb4b8643a131d45fbc9af23e353dc0a5ba5c3", - "sha256:1962293292865bca8e54702b08a4f26da73adc83dd1fcf26fbc875b35d81c815", - "sha256:1d1d9764366c73f996edd17abb6d9d7649a7eb690006ab6adbda117717099b14", - "sha256:1f8d33a7f4d5a7889e60dc39856d76d09333d8a6ed0f5f1190635cbec70ec4ba", - "sha256:22f0fb8c1c583a3b6f24df2470833b40207e907b90c928cc8d3594b76f874375", - "sha256:239edca560d05757817c13dc17c50766136d21f7cd0fac50295499ae24f90fdf", - "sha256:242a206cd0318f95cd21bdacff3fcc3aab23e79bba5cac3db5a841c9ef9c6963", - "sha256:25e1c2af0fce638d5f1988b686f3b3ea8cd7de5f244ca147c777769e798a9cd1", - "sha256:266fb4cbf5e3cbd0b53669a6d1b039c45e3ce651fd5442eff4d07c2cc8d66808", - "sha256:2782c870e99878c634505236d81e5443092fba820f0373997ff75f90f68cd553", - "sha256:287dad91cfb551c363dc62899a80e9e14da1f0e2b6ebde82c806612ca2a13ef1", - "sha256:29452c56df2ed968d18d7e21f4ab0ac55e71dc59524872f6fc57dcf4a3249ed2", - "sha256:299e0a22e7ae2b85c1a57f104538b2656e8ab1873511fd718a1c1c6f149b77b5", - "sha256:2a5e06546e19f24c6a96a129142a75cee553cc018ffee48a460059b1185f4470", - "sha256:2b761d210c9ea91feda40d25b4efe82a1707da2ef62901466a42492c028553a2", - "sha256:2c010c6ded393148374c0f6f0bf89d206bf3217f201faa0635dcd56bd1520f6b", - "sha256:2ff4321e56e879ee8d2a879501c8e469414d948f4aba74a2d4593184eb326660", - "sha256:3006c3dd9ba34b0c094c544c6006cc79e87d8612999f1a5d43b769b89181f23c", - "sha256:33cb885e759a705b426baada1fe68cbb0a2e68e34c5d0d0289a364cf01709093", - "sha256:346285d28e4c8017da95144c7f3acd42740d637ff41946af5ce6e5e420502dd5", - "sha256:34a64bc3441dc1213096a20fe27e8e128bd3ff89921706e83c0b1ac971276594", - "sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008", - "sha256:378bec5c66998815d224c9ca994f1e14c0c21cb95d2f52b6021cc0b2a58f2a5a", - "sha256:3f37a19d7ebcdd20b96485056ba9e8b304e27d9904d233d7b1015db320e51f0a", - "sha256:3f84d5c1b4ab906093bdc1ff10484838aca54ef08de4afa9de0f5f14d69639cd", - "sha256:4009935984bd36bd2c774e13f9a09563ce8de4abaa7226f5108262fa3e637284", - "sha256:406bf18d345822d6c21366031003612b9c77b3e29ffdb0f612367352aab7d586", - "sha256:4819fa52133c9aa3c387b3328f25c1facc356491e6135b459f1de698ff64d869", - "sha256:482c982f814460eabe1d3bb0adfdc583387bd4691ef00b90575ca0d2b6fe2294", - "sha256:4bc36bbc0b7584de96561184ad7f012478987882ebf9f9c389b23f432ea3d90f", - "sha256:506d766a8727beef16b7adaeb8ee6217c64fc813646b424d0804d67c16eddb66", - "sha256:56121965f7a4dc965bff783d70b907ddf3d57f6eba29b6d2e5dabfaf07799c51", - "sha256:58133647260ea01e4d0500089a8c4f07bd7aa6ce109682b1426394988d8aaacc", - "sha256:5921a4d3ca3aee735d9fd163808f5e8dd6c6972101e4adbda9a4667908849b97", - "sha256:5a4e67afbc95fa5c34cf27d9089bca7fcab4e51e57278d710320a70b956d1b9a", - "sha256:5cb1b2f9742240e4bb26b652a5aeb840aa4b417c7748b6f8387927bc6e45e40d", - "sha256:62de39db01b8d593e45871af2af9e497295db8d73b085f6bfd0b18c83c70a8f9", - "sha256:634e8609e89ceecea15e2d61bc9ac3718caaaa71963717bf3c8f38bfde64242c", - "sha256:63510af5e38f8955b8ee5687740d6ebf7c2a0886d15a6d65c32814613681bc07", - "sha256:650ae77860b45cfa6e2cdafc42618ceafab3a2d9a3811fcfbd3bbf8ac3c40d36", - "sha256:6561e94ba9dacc9c61bce40e2d6bdc3bfaa0259d3ff36ace3b1e6901936d2e3e", - "sha256:65840751b72fbfd82c3c640cff9284545342a4f1eb1586ad0636955b261b0b05", - "sha256:6cb58b9c66f7e4179a2d5e0f849c48eff5c1fca560994d6eb6543abf955a149e", - "sha256:6f52298fbd394f9ed112d56f3d11aabd0d5bd27beb3084cc3d8ad069483b8941", - "sha256:707625ef0983fcfb461acfaf14de2067c5942c6bb0f3b4c99158bed6fedd3cf3", - "sha256:72f6c8b11857a856bcfa48c86f5368439f74453563f951e473514579d44aa612", - "sha256:753e230374206729bf0a807954bcc6c150d3743928a73faffee51ac6557a03c3", - "sha256:76d0819de158cd855d1cbb8fcafdf6f5cf1eb8e470abe056d5d161106e38062b", - "sha256:76ee27c6e9c7f16f47db7a94157112a2f3a00e958bc626e2f4ee8bec5c328fbe", - "sha256:77b63866ca88d804225eaa4af3e664c5faf3568cea95360d21f4725ab6e07146", - "sha256:79ec52ec461e99e13791ec6508c722742ad745571f234ea6255bed38c6480f11", - "sha256:7b93a4d08587e2b7e7882de461e82b6ed76d9026ce91ca7915e740ecc7855f60", - "sha256:7da7087d756b19037bc2c06edc6c170eeef3c3bafcb8f532ff17d64dc427adfd", - "sha256:7f3bf998340c6d4b0c9a2f02d6a400e51f123b59565d74dc60d252ce888c260b", - "sha256:80aa89cad80b32a912a65332f64a4450ed00966111b6615ca6816153d3585a8c", - "sha256:8566def80554c3faa0e65ac30ab0932b9e3a5cd7f8323764303d468e5c37595a", - "sha256:873e0d5b4fb9b89ef7c2d2a963ea7d02879d9da0da8d9d4933dee8ee86a8b460", - "sha256:88942d3a3dff3afc8288c21e565e476fc278902ae4d6d134f1eeda118cc830b1", - "sha256:8bfeaf8735be79f225f3fefab7f941c712aaca36f1128c9d7e2352ee1aa87bdf", - "sha256:8e7c86f27c585ef37c35e56a96363ab8de4e549a95512445b85c96d3e2f7c1bf", - "sha256:915c3d10f81bec3a74fbd4faebe8391013ba61e5a1a8d48c4455b923bdda7858", - "sha256:93e8740d7503eb008aa2df04d3b9735f845d43ae845e6dcd2be0b55a2da43cd2", - "sha256:941103c9be18ac8daf7b7adca8228f8ed6bb7a1849020f643b3a14d15b1924d9", - "sha256:97aeba56665b4c3235a0e52b2c2f5ae9cd071b8a8310ad27bddb3f7fb30e9aa2", - "sha256:a39455728aabd58ceabb03c90e12f71fd30fa69615760a075b9fec596456ccc3", - "sha256:a3a52f6156e73e7ccb0f8cced536adccb7042be67cb45f9562e12b319c119da6", - "sha256:a668ce24de96165bb239160b3d854943128f4334822900534f2fe947930e5770", - "sha256:a75dafbf87d6276ddc5b2bf6fae5254e3d0876b626eb24969a574fff9149ee5d", - "sha256:aabf5777b5c8ca26f7824cb4a120a740c9588ed58df9b2d196ce92fba42ff8dc", - "sha256:aec5cf2fd867b4ff45b9959f8b20ea3993fc93e63c7363fe6851424c8a7e7c23", - "sha256:b2379fa7ed44ddecb5bfe4e48577d752db9fc10be00a6b7446e9663ba143de26", - "sha256:b4ececa40ac28afa90871c2cc2b9ffd2ff0bf749380fbdf57d165fd23da353aa", - "sha256:b5819cd790dbf0c5eb9f82c73c16b39a65dd6dd4d1439dcdea7816ec9adddab8", - "sha256:b74557b16e390ec12dca509bce9264c3bbd128f8a2c376eaa68003d7f327276d", - "sha256:b80aa5095cd3109962a298ce14110ae16b8c1aece8b72f9dafe81cf597ad80b3", - "sha256:b93590ae81f7010dbe380cdeab6f515902ebcbefe0b9327cc4804d74e93ae69d", - "sha256:b96d5f26b05d03cc60f11a7761a5ded1741da411e7fe0909e27a5e6a0cb7b034", - "sha256:bd3d54f38609ff308209bd43acea66061494157703364ae40c951f83ba99a1a9", - "sha256:bfea2a5f0b4d8d43adf9d7b8bf019fb46fdd10a2e5cde477fbcb9d1fa08c68e1", - "sha256:c007fe8a43d43b3969e8469004e9845944f1a80e6acd47c150856bb87f230c56", - "sha256:c1df3d34aced70add6f867a8cf413e299177e0c22660cc767218373d0779487b", - "sha256:c23e27686783f60290e36827f9c626e63154b82b116d7fe9adba1fda36da706c", - "sha256:c8d8b4eb992936023be7dee581270af5c6e0697a8559895f527f5b7105ecd36a", - "sha256:c9e19dd6e28fdcaa5a1de679aec4141f691023916427ef9bae8584f9c2fb3b0e", - "sha256:d0d2568a8c11bf8225044aa94409e21da0cb09dcdafe9ecd10250b2baad531a9", - "sha256:d38548150c39b74aeeb0ce8ee1d8e82696f4a4e16ddc6de7b1d8823f7de4b9b5", - "sha256:d3a978c4f57a597908b7e697229d996d77a6d3c94901e9edee593adada95ce1a", - "sha256:d5160812ea7a8a2ffbe233d8da666880cad0cbaf5d4de74ae15c313213d62556", - "sha256:dc799088c08fa04e43144b164feb0c13f9a0bc40503f8df3e9fde58a3c0c101e", - "sha256:df3959765b553b9440adfd3c795617c352154e497a4eaf3752555cfb5da8fc49", - "sha256:dfa8a0c812ac681395907e71e1274819dec685fec28273a28905df579ef137e2", - "sha256:e25c479382d26a2a41b7ebea1043564a937db462816ea07afa8a44c0866d52f9", - "sha256:e4f4a984405e91527a0d62649ee21138f8e3d0ef103be488c1dc11a80d7f184b", - "sha256:e536c98a7626a98feb2d3eaf75944ef6f3dbee447e1f841eae16f2f0a72d8ddc", - "sha256:e56ba91f47764cc14f1daacd723e3e82d1a89d783f0f5afe9c364b8bb491ccdb", - "sha256:e672ba74fbc2dc8eea59fb6d4aed6845e6905fc2a8afe93175d94a83ba2a01a0", - "sha256:e7b576130c69225432866fe2f4a469a85a54ade141d96fd396dffcf607b558f8", - "sha256:e8465ab91a4bd96d36dde3263f06caa6a8a6019e4113f24dc753d79a8b3a3f82", - "sha256:e96cea19e34778f8d59fe40775a7a574d95816eb150850a85a7a4c8f4b94ac69", - "sha256:ece5c59f0ce7d001e017643d8d24da587ea1f74f6993467d85ae8a5ef9d4f42b", - "sha256:eceb81a8d74f9267ef4081e246ffd6d129da5d87e37a77c9bde550cb04870c1c", - "sha256:ed2e99c456e3fadd05c991f8f437ef902e00eedf34320ba2b0842bd1c3ca3a75", - "sha256:f0cd744688278965817fd0839c4a4116add48d23890d468bc436f78beb28abf5", - "sha256:f14f8f046c14563f8eb3f45f499cc658ab8d10072961e07225e507adb700e93f", - "sha256:f15489ba13d61f670dcc96772e733aad1a6f9c429cc27574c6cdaed82d0146ad", - "sha256:f31d95a179f8d64d90f6831d71fa93290893a33148d890ba15de25642c5d075b", - "sha256:f41a7489d32336dbf2199c8c0a215390a751c5b014c2c1c5366e817202e9cdf7", - "sha256:f41eb9797986d6ebac5e8edff36d5cef9de40def462311b3eb3eeded1431e425", - "sha256:f547144f2966e1e16ae626d8ce72b4cfa0caedc7fa28052001c94fb2fcaa1c52" + "sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed", + "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4" ], "markers": "python_version >= '3.9'", - "version": "==2.41.5" - }, - "pygments": { - "hashes": [ - "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", - "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b" - ], - "markers": "python_version >= '3.8'", - "version": "==2.19.2" - }, - "pytest": { - "hashes": [ - "sha256:711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b", - "sha256:75186651a92bd89611d1d9fc20f0b4345fd827c41ccd5c299a868a05d70edf11" - ], - "index": "pypi", - "markers": "python_version >= '3.10'", - "version": "==9.0.2" - }, - "python-dateutil": { - "hashes": [ - "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", - "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", - "version": "==2.9.0.post0" - }, - "python-ulid": { - "hashes": [ - "sha256:e2cdc979c8c877029b4b7a38a6fba3bc4578e4f109a308419ff4d3ccf0a46619", - "sha256:ff0410a598bc5f6b01b602851a3296ede6f91389f913a5d5f8c496003836f636" - ], - "markers": "python_version >= '3.9'", - "version": "==3.1.0" - }, - "pyyaml": { - "hashes": [ - "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", - "sha256:0150219816b6a1fa26fb4699fb7daa9caf09eb1999f3b70fb6e786805e80375a", - "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", - "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956", - "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", - "sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c", - "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", - "sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a", - "sha256:1ebe39cb5fc479422b83de611d14e2c0d3bb2a18bbcb01f229ab3cfbd8fee7a0", - "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b", - "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", - "sha256:22ba7cfcad58ef3ecddc7ed1db3409af68d023b7f940da23c6c2a1890976eda6", - "sha256:27c0abcb4a5dac13684a37f76e701e054692a9b2d3064b70f5e4eb54810553d7", - "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e", - "sha256:2e71d11abed7344e42a8849600193d15b6def118602c4c176f748e4583246007", - "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", - "sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4", - "sha256:3c5677e12444c15717b902a5798264fa7909e41153cdf9ef7ad571b704a63dd9", - "sha256:3ff07ec89bae51176c0549bc4c63aa6202991da2d9a6129d7aef7f1407d3f295", - "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea", - "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0", - "sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e", - "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", - "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", - "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", - "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", - "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", - "sha256:5cf4e27da7e3fbed4d6c3d8e797387aaad68102272f8f9752883bc32d61cb87b", - "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69", - "sha256:5ed875a24292240029e4483f9d4a4b8a1ae08843b9c54f43fcc11e404532a8a5", - "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b", - "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c", - "sha256:6344df0d5755a2c9a276d4473ae6b90647e216ab4757f8426893b5dd2ac3f369", - "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd", - "sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824", - "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198", - "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", - "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", - "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", - "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", - "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196", - "sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b", - "sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00", - "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", - "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", - "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e", - "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28", - "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", - "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5", - "sha256:9c57bb8c96f6d1808c030b1687b9b5fb476abaa47f0db9c0101f5e9f394e97f4", - "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b", - "sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf", - "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", - "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", - "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8", - "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", - "sha256:b865addae83924361678b652338317d1bd7e79b1f4596f96b96c77a5a34b34da", - "sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d", - "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc", - "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c", - "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", - "sha256:c2514fceb77bc5e7a2f7adfaa1feb2fb311607c9cb518dbc378688ec73d8292f", - "sha256:c3355370a2c156cffb25e876646f149d5d68f5e0a3ce86a5084dd0b64a994917", - "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", - "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", - "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", - "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", - "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", - "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", - "sha256:efd7b85f94a6f21e4932043973a7ba2613b059c4a000551892ac9f1d11f5baf3", - "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", - "sha256:fa160448684b4e94d80416c0fa4aac48967a969efe22931448d853ada8baf926", - "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0" - ], - "markers": "python_version >= '3.8'", - "version": "==6.0.3" - }, - "regex": { - "hashes": [ - "sha256:00945d007fd74a9084d2ab79b695b595c6b7ba3698972fadd43e23230c6979c1", - "sha256:00f2b8d9615aa165fdff0a13f1a92049bfad555ee91e20d246a51aa0b556c60a", - "sha256:01d65fd24206c8e1e97e2e31b286c59009636c022eb5d003f52760b0f42155d4", - "sha256:02473c954af35dd2defeb07e44182f5705b30ea3f351a7cbffa9177beb14da5d", - "sha256:03a83cc26aa2acda6b8b9dfe748cf9e84cbd390c424a1de34fdcef58961a297a", - "sha256:09500be324f49b470d907b3ef8af9afe857f5cca486f853853f7945ddbf75911", - "sha256:0b1d2b07614d95fa2bf8a63fd1e98bd8fa2b4848dc91b1efbc8ba219fdd73952", - "sha256:0d25a10811de831c2baa6aef3c0be91622f44dd8d31dd12e69f6398efb15e48b", - "sha256:0d5bef2031cbf38757a0b0bc4298bb4824b6332d28edc16b39247228fbdbad97", - "sha256:10d28e19bd4888e4abf43bd3925f3c134c52fdf7259219003588a42e24c2aa25", - "sha256:180e08a435a0319e6a4821c3468da18dc7001987e1c17ae1335488dfe7518dd8", - "sha256:195237dc327858a7721bf8b0bbbef797554bc13563c3591e91cd0767bacbe359", - "sha256:19a9c9e0a8f24f39d575a6a854d516b48ffe4cbdcb9de55cb0570a032556ecff", - "sha256:1c2c95e1a2b0f89d01e821ff4de1be4b5d73d1f4b0bf679fa27c1ad8d2327f1a", - "sha256:1d367257cd86c1cbb97ea94e77b373a0bbc2224976e247f173d19e8f18b4afa7", - "sha256:1e496956106fd59ba6322a8ea17141a27c5040e5ee8f9433ae92d4e5204462a0", - "sha256:1f8b17be5c27a684ea6759983c13506bd77bfc7c0347dff41b18ce5ddd2ee09a", - "sha256:2234059cfe33d9813a3677ef7667999caea9eeaa83fef98eb6ce15c6cf9e0215", - "sha256:25b6eb660c5cf4b8c3407a1ed462abba26a926cc9965e164268a3267bcc06a43", - "sha256:2954379dd20752e82d22accf3ff465311cbb2bac6c1f92c4afd400e1757f7451", - "sha256:2afa673660928d0b63d84353c6c08a8a476ddfc4a47e11742949d182e6863ce8", - "sha256:2b2b23587b26496ff5fd40df4278becdf386813ec00dc3533fa43a4cf0e2ad3c", - "sha256:2fb950ac1d88e6b6a9414381f403797b236f9fa17e1eee07683af72b1634207b", - "sha256:3935174fa4d9f70525a4367aaff3cb8bc0548129d114260c29d9dfa4a5b41692", - "sha256:39bb5727650b9a0275c6a6690f9bb3fe693a7e6cc5c3155b1240aedf8926423e", - "sha256:3b24bd7e9d85dc7c6a8bd2aa14ecd234274a0248335a02adeb25448aecdd420d", - "sha256:4390c365fd2d45278f45afd4673cb90f7285f5701607e3ad4274df08e36140ae", - "sha256:481df4623fa4969c8b11f3433ed7d5e3dc9cec0f008356c3212b3933fb77e3d8", - "sha256:4f5c0b182ad4269e7381b7c27fdb0408399881f7a92a4624fd5487f2971dfc11", - "sha256:50c2fc924749543e0eacc93ada6aeeb3ea5f6715825624baa0dccaec771668ae", - "sha256:511f7419f7afab475fd4d639d4aedfc54205bcb0800066753ef68a59f0f330b5", - "sha256:516604edd17b1c2c3e579cf4e9b25a53bf8fa6e7cedddf1127804d3e0140ca64", - "sha256:52b017b35ac2214d0db5f4f90e303634dc44e4aba4bd6235a27f97ecbe5b0472", - "sha256:5a932ea8ad5d0430351ff9c76c8db34db0d9f53c1d78f06022a21f4e290c5c18", - "sha256:5cdcc17d935c8f9d3f4db5c2ebe2640c332e3822ad5d23c2f8e0228e6947943a", - "sha256:5d10303dd18cedfd4d095543998404df656088240bcfd3cd20a8f95b861f74bd", - "sha256:5e68192bb3a1d6fb2836da24aa494e413ea65853a21505e142e5b1064a595f3d", - "sha256:64e7c6ad614573e0640f271e811a408d79a9e1fe62a46adb602f598df42a818d", - "sha256:6591f281cb44dc13de9585b552cec6fc6cf47fb2fe7a48892295ee9bc4a612f9", - "sha256:69fc560ccbf08a09dc9b52ab69cacfae51e0ed80dc5693078bdc97db2f91ae96", - "sha256:6d63a07e5ec8ce7184452cb00c41c37b49e67dc4f73b2955b5b8e782ea970784", - "sha256:6db7bfae0f8a2793ff1f7021468ea55e2699d0790eb58ee6ab36ae43aa00bc5b", - "sha256:71a911098be38c859ceb3f9a9ce43f4ed9f4c6720ad8684a066ea246b76ad9ff", - "sha256:73cdcdbba8028167ea81490c7f45280113e41db2c7afb65a276f4711fa3bcbff", - "sha256:78454178c7df31372ea737996fb7f36b3c2c92cccc641d251e072478afb4babc", - "sha256:7900157786428a79615a8264dac1f12c9b02957c473c8110c6b1f972dcecaddf", - "sha256:7ab218076eb0944549e7fe74cf0e2b83a82edb27e81cc87411f76240865e04d5", - "sha256:7c1b34dfa72f826f535b20712afa9bb3ba580020e834f3c69866c5bddbf10098", - "sha256:851fa70df44325e1e4cdb79c5e676e91a78147b1b543db2aec8734d2add30ec2", - "sha256:864cdd1a2ef5716b0ab468af40139e62ede1b3a53386b375ec0786bb6783fc05", - "sha256:8710d61737b0c0ce6836b1da7109f20d495e49b3809f30e27e9560be67a257bf", - "sha256:9036b400b20e4858d56d117108d7813ed07bb7803e3eed766675862131135ca6", - "sha256:9185cc63359862a6e80fe97f696e04b0ad9a11c4ac0a4a927f979f611bfe3768", - "sha256:948c12ef30ecedb128903c2c2678b339746eb7c689c5c21957c4a23950c96d15", - "sha256:94d63db12e45a9b9f064bfe4800cefefc7e5f182052e4c1b774d46a40ab1d9bb", - "sha256:96f6269a2882fbb0ee76967116b83679dc628e68eaea44e90884b8d53d833881", - "sha256:97054c55db06ab020342cc0d35d6f62a465fa7662871190175f1ad6c655c028f", - "sha256:98adf340100cbe6fbaf8e6dc75e28f2c191b1be50ffefe292fb0e6f6eefdb0d8", - "sha256:99985a2c277dcb9ccb63f937451af5d65177af1efdeb8173ac55b61095a0a05c", - "sha256:9b65d33a17101569f86d9c5966a8b1d7fbf8afdda5a8aa219301b0a80f58cf7d", - "sha256:9dd450db6458387167e033cfa80887a34c99c81d26da1bf8b0b41bf8c9cac88e", - "sha256:a25c7701e4f7a70021db9aaf4a4a0a67033c6318752146e03d1b94d32006217e", - "sha256:a448af01e3d8031c89c5d902040b124a5e921a25c4e5e07a861ca591ce429341", - "sha256:a5dac14d0872eeb35260a8e30bac07ddf22adc1e3a0635b52b02e180d17c9c7e", - "sha256:a729e47d418ea11d03469f321aaf67cdee8954cde3ff2cf8403ab87951ad10f2", - "sha256:aaffaecffcd2479ce87aa1e74076c221700b7c804e48e98e62500ee748f0f550", - "sha256:b059e71ec363968671693a78c5053bd9cb2fe410f9b8e4657e88377ebd603a2e", - "sha256:b387a0d092dac157fb026d737dde35ff3e49ef27f285343e7c6401851239df27", - "sha256:b389c61aa28a79c2e0527ac36da579869c2e235a5b208a12c5b5318cda2501d8", - "sha256:b42f7466e32bf15a961cf09f35fa6323cc72e64d3d2c990b10de1274a5da0a59", - "sha256:b49eb78048c6354f49e91e4b77da21257fecb92256b6d599ae44403cab30b05b", - "sha256:b5acd4b6a95f37c3c3828e5d053a7d4edaedb85de551db0153754924cb7c83e3", - "sha256:b8b3f1be1738feadc69f62daa250c933e85c6f34fa378f54a7ff43807c1b9117", - "sha256:b8cf76f1a29f0e99dcfd7aef1551a9827588aae5a737fe31442021165f1920dc", - "sha256:ba55c50f408fb5c346a3a02d2ce0ebc839784e24f7c9684fde328ff063c3cdea", - "sha256:bba2b18d70eeb7b79950f12f633beeecd923f7c9ad6f6bae28e59b4cb3ab046b", - "sha256:bbb882061f742eb5d46f2f1bd5304055be0a66b783576de3d7eef1bed4778a6e", - "sha256:bcb399ed84eabf4282587ba151f2732ad8168e66f1d3f85b1d038868fe547703", - "sha256:bd477d5f79920338107f04aa645f094032d9e3030cc55be581df3d1ef61aa318", - "sha256:bec23c11cbbf09a4df32fe50d57cbdd777bc442269b6e39a1775654f1c95dee2", - "sha256:c0b5ccbb8ffb433939d248707d4a8b31993cb76ab1a0187ca886bf50e96df952", - "sha256:c15af43c72a7fb0c97cbc66fa36a43546eddc5c06a662b64a0cbf30d6ac40944", - "sha256:c7815afb0ca45456613fdaf60ea9c993715511c8d53a83bc468305cbc0ee23c7", - "sha256:cb3b1db8ff6c7b8bf838ab05583ea15230cb2f678e569ab0e3a24d1e8320940b", - "sha256:d0b02e8b7e5874b48ae0f077ecca61c1a6a9f9895e9c6dfb191b55b242862033", - "sha256:d6b08a06976ff4fb0d83077022fde3eca06c55432bb997d8c0495b9a4e9872f4", - "sha256:d6cfe798d8da41bb1862ed6e0cba14003d387c3c0c4a5d45591076ae9f0ce2f8", - "sha256:d8511a01d0e4ee1992eb3ba19e09bc1866fe03f05129c3aec3fdc4cbc77aad3f", - "sha256:dc8ed8c3f41c27acb83f7b6a9eb727a73fc6663441890c5cb3426a5f6a91ce7d", - "sha256:dd8847c4978bc3c7e6c826fb745f5570e518b8459ac2892151ce6627c7bc00d5", - "sha256:de0cf053139f96219ccfabb4a8dd2d217c8c82cb206c91d9f109f3f552d6b43d", - "sha256:dee50f1be42222f89767b64b283283ef963189da0dda4a515aa54a5563c62dec", - "sha256:e1e7b24cb3ae9953a560c563045d1ba56ee4749fbd05cf21ba571069bd7be81b", - "sha256:e59bc8f30414d283ae8ee1617b13d8112e7135cb92830f0ec3688cb29152585a", - "sha256:e61eea47230eba62a31f3e8a0e3164d0f37ef9f40529fb2c79361bc6b53d2a92", - "sha256:e621fb7c8dc147419b28e1702f58a0177ff8308a76fa295c71f3e7827849f5d9", - "sha256:e71dcecaa113eebcc96622c17692672c2d104b1d71ddf7adeda90da7ddeb26fc", - "sha256:e7ce83654d1ab701cb619285a18a8e5a889c1216d746ddc710c914ca5fd71022", - "sha256:e8c8cb2deba42f5ec1ede46374e990f8adc5e6456a57ac1a261b19be6f28e4e6", - "sha256:ec0c608b7a7465ffadb344ed7c987ff2f11ee03f6a130b569aa74d8a70e8333c", - "sha256:ec6f5674c5dc836994f50f1186dd1fafde4be0666aae201ae2fcc3d29d8adf27", - "sha256:edb1b1b3a5576c56f08ac46f108c40333f222ebfd5cf63afdfa3aab0791ebe5b", - "sha256:ef77bdde9c9eba3f7fa5b58084b29bbcc74bcf55fdbeaa67c102a35b5bd7e7cc", - "sha256:f2791948f7c70bb9335a9102df45e93d428f4b8128020d85920223925d73b9e1", - "sha256:f467cb602f03fbd1ab1908f68b53c649ce393fde056628dc8c7e634dab6bfc07", - "sha256:f8ed9a5d4612df9d4de15878f0bc6aa7a268afbe5af21a3fdd97fa19516e978c", - "sha256:fa539be029844c0ce1114762d2952ab6cfdd7c7c9bd72e0db26b94c3c36dcc5a", - "sha256:fb1c4ff62277d87a7335f2c1ea4e0387b8f2b3ad88a64efd9943906aafad4f33", - "sha256:fb4db2f17e6484904f986c5a657cec85574c76b5c5e61c7aae9ffa1bc6224f95", - "sha256:fb66e5245db9652abd7196ace599b04d9c0e4aa7c8f0e2803938377835780081", - "sha256:fc48c500838be6882b32748f60a15229d2dea96e59ef341eaa96ec83538f498d", - "sha256:fcf26c3c6d0da98fada8ae4ef0aa1c3405a431c0a77eb17306d38a89b02adcd7", - "sha256:fd0ce43e71d825b7c0661f9c54d4d74bd97c56c3fd102a8985bcfea48236bacb", - "sha256:fd63453f10d29097cc3dc62d070746523973fb5aa1c66d25f8558bebd47fed61" - ], - "markers": "python_version >= '3.10'", - "version": "==2026.2.28" - }, - "rich": { - "hashes": [ - "sha256:793431c1f8619afa7d3b52b2cdec859562b950ea0d4b6b505397612db8d5362d", - "sha256:b8daa0b9e4eef54dd8cf7c86c03713f53241884e814f4e2f5fb342fe520f639b" - ], - "markers": "python_full_version >= '3.8.0'", - "version": "==14.3.3" - }, - "safetensors": { - "hashes": [ - "sha256:0071bffba4150c2f46cae1432d31995d77acfd9f8db598b5d1a2ce67e8440ad2", - "sha256:07663963b67e8bd9f0b8ad15bb9163606cd27cc5a1b96235a50d8369803b96b0", - "sha256:12f49080303fa6bb424b362149a12949dfbbf1e06811a88f2307276b0c131afd", - "sha256:1d060c70284127fa805085d8f10fbd0962792aed71879d00864acda69dbab981", - "sha256:42cb091236206bb2016d245c377ed383aa7f78691748f3bb6ee1bfa51ae2ce6a", - "sha256:473b32699f4200e69801bf5abf93f1a4ecd432a70984df164fc22ccf39c4a6f3", - "sha256:54bef08bf00a2bff599982f6b08e8770e09cc012d7bba00783fc7ea38f1fb37d", - "sha256:5d72abdb8a4d56d4020713724ba81dac065fedb7f3667151c4a637f1d3fb26c0", - "sha256:672132907fcad9f2aedcb705b2d7b3b93354a2aec1b2f706c4db852abe338f85", - "sha256:6999421eb8ba9df4450a16d9184fcb7bef26240b9f98e95401f17af6c2210b71", - "sha256:7b95a3fa7b3abb9b5b0e07668e808364d0d40f6bbbf9ae0faa8b5b210c97b140", - "sha256:8469155f4cb518bafb4acf4865e8bb9d6804110d2d9bdcaa78564b9fd841e104", - "sha256:94fd4858284736bb67a897a41608b5b0c2496c9bdb3bf2af1fa3409127f20d57", - "sha256:b0f6d66c1c538d5a94a73aa9ddca8ccc4227e6c9ff555322ea40bdd142391dd4", - "sha256:c74af94bf3ac15ac4d0f2a7c7b4663a15f8c2ab15ed0fc7531ca61d0835eccba", - "sha256:c82f4d474cf725255d9e6acf17252991c3c8aac038d6ef363a4bf8be2f6db517", - "sha256:cdab83a366799fa730f90a4ebb563e494f28e9e92c4819e556152ad55e43591b", - "sha256:cfdead2f57330d76aa7234051dadfa7d4eedc0e5a27fd08e6f96714a92b00f09", - "sha256:d1239932053f56f3456f32eb9625590cc7582e905021f94636202a864d470755", - "sha256:dac7252938f0696ddea46f5e855dd3138444e82236e3be475f54929f0c510d48", - "sha256:dc92bc2db7b45bda4510e4f51c59b00fe80b2d6be88928346e4294ce1c2abe7c", - "sha256:e07d91d0c92a31200f25351f4acb2bc6aff7f48094e13ebb1d0fb995b54b6542", - "sha256:f4729811a6640d019a4b7ba8638ee2fd21fa5ca8c7e7bdf0fed62068fcaac737" - ], - "markers": "python_version >= '3.9'", - "version": "==0.7.0" - }, - "sentencepiece": { - "hashes": [ - "sha256:010f025a544ef770bb395091d57cb94deb9652d8972e0d09f71d85d5a0816c8c", - "sha256:017f97b274d4b0baa84b2dc743bf4517be81156f413bb24f12aacacde378e5ab", - "sha256:01e6912125cb45d3792f530a4d38f8e21bf884d6b4d4ade1b2de5cf7a8d2a52b", - "sha256:02593eca45440ef39247cee8c47322a34bdcc1d8ae83ad28ba5a899a2cf8d79a", - "sha256:097f3394e99456e9e4efba1737c3749d7e23563dd1588ce71a3d007f25475fff", - "sha256:0a0d15781a171d188b661ae4bde1d998c303f6bd8621498c50c671bd45a4798e", - "sha256:0a81799d0a68d618e89063fb423c3001a034c893069135ffe51fee439ae474d6", - "sha256:0c0f672da370cc490e4c59d89e12289778310a0e71d176c541e4834759e1ae07", - "sha256:0cdfecef430d985f1c2bcbfff3defd1d95dae876fbd0173376012d2d7d24044b", - "sha256:105e36e75cbac1292642045458e8da677b2342dcd33df503e640f0b457cb6751", - "sha256:10ed3dab2044c47f7a2e7b4969b0c430420cdd45735d78c8f853191fa0e3148b", - "sha256:1855f57db07b51fb51ed6c9c452f570624d2b169b36f0f79ef71a6e6c618cd8b", - "sha256:2005242a16d2dc3ac5fe18aa7667549134d37854823df4c4db244752453b78a8", - "sha256:22c4ebcb3c6ab1496ab1c37c79ef7bb563b8726f29548c30773b7a4cb152df1a", - "sha256:251874d720ac7f28024a168501f3c7bb15d1802245f6e66de565f18bbb9b5eaa", - "sha256:27e38eee653abc3d387862e67bc5c8b6f428cd604e688b85d29170b7e725c26c", - "sha256:2af5a1fb05013332ad94343b8b5f3973e006a2dde2dfba55a819549e054e2f0f", - "sha256:2f27ae6deea72efdb6f361750c92f6c21fd0ad087445082770cc34015213c526", - "sha256:33f068c9382dc2e7c228eedfd8163b52baa86bb92f50d0488bf2b7da7032e484", - "sha256:39f8651bd10974eafb9834ce30d9bcf5b73e1fc798a7f7d2528f9820ca86e119", - "sha256:3d165fbb9bf8fba35f1946ba2617c3f9995679f07438325f07c026d53f33e746", - "sha256:477c81505db072b3ab627e7eab972ea1025331bd3a92bacbf798df2b75ea86ec", - "sha256:4cdc7c36234fda305e85c32949c5211faaf8dd886096c7cea289ddc12a2d02de", - "sha256:4f5a3e0d9f445ed9d66c0fec47d4b23d12cfc858b407a03c194c1b26c2ac2a63", - "sha256:56dd39a3c4d6493db3cdca7e8cc68c6b633f0d4195495cbadfcf5af8a22d05a6", - "sha256:57cae326c8727de58c85977b175af132a7138d84c764635d7e71bbee7e774133", - "sha256:5d0350b686c320068702116276cfb26c066dc7e65cfef173980b11bb4d606719", - "sha256:5e4366c97b68218fd30ea72d70c525e6e78a6c0a88650f57ac4c43c63b234a9d", - "sha256:60937c959e6f44159fdd9f56fbdd302501f96114a5ba436829496d5f32d8de3f", - "sha256:6356d0986b8b8dc351b943150fcd81a1c6e6e4d439772e8584c64230e58ca987", - "sha256:6d297a1748d429ba8534eebe5535448d78b8acc32d00a29b49acf28102eeb094", - "sha256:733e59ff1794d26db706cd41fc2d7ca5f6c64a820709cb801dc0ea31780d64ab", - "sha256:8138cec27c2f2282f4a34d9a016e3374cd40e5c6e9cb335063db66a0a3b71fad", - "sha256:814978ac05130dd5812b4b03215c766bc6abaef13e7bd72bc534e4d1e12e9a4c", - "sha256:82d9ead6591015f009cb1be1cb1c015d5e6f04046dbb8c9588b931e869a29728", - "sha256:881b2e44b14fc19feade3cbed314be37de639fc415375cefaa5bc81a4be137fd", - "sha256:891ade6503dd93d418c03993f7d6a8aa20260c422cefff5096b9068185e67642", - "sha256:89a3ea015517c42c0341d0d962f3e6aaf2cf10d71b1932d475c44ba48d00aa2b", - "sha256:8dd4b477a7b069648d19363aad0cab9bad2f4e83b2d179be668efa672500dc94", - "sha256:8f8ba89a3acb3dc1ae90f65ec1894b0b9596fdb98ab003ff38e058f898b39bc7", - "sha256:9076430ac25dfa7147d9d05751dbc66a04bc1aaac371c07f84952979ea59f0d0", - "sha256:92b3816aa2339355fda2c8c4e021a5de92180b00aaccaf5e2808972e77a4b22f", - "sha256:99f955df238021bf11f0fc37cdb54fd5e5b5f7fd30ecc3d93fb48b6815437167", - "sha256:a19adcec27c524cb7069a1c741060add95f942d1cbf7ad0d104dffa0a7d28a2b", - "sha256:a483fd29a34c3e34c39ac5556b0a90942bec253d260235729e50976f5dba1068", - "sha256:ac650534e2251083c5f75dde4ff28896ce7c8904133dc8fef42780f4d5588fcd", - "sha256:ad8493bea8432dae8d6830365352350f3b4144415a1d09c4c8cb8d30cf3b6c3c", - "sha256:afefe50a0cdcb4f2fd9733cb52001a2c164181ee2d82c32d38f5b1b326a8528c", - "sha256:b3616ad246f360e52c85781e47682d31abfb6554c779e42b65333d4b5f44ecc0", - "sha256:b81a24733726e3678d2db63619acc5a8dccd074f7aa7a54ecd5ca33ca6d2d596", - "sha256:c415c9de1447e0a74ae3fdb2e52f967cb544113a3a5ce3a194df185cbc1f962f", - "sha256:c6c8f42949f419ff8c7e9960dbadcfbc982d7b5efc2f6748210d3dd53a7de062", - "sha256:c7f0fd2f2693309e6628aeeb2e2faf6edd221134dfccac3308ca0de01f8dab47", - "sha256:c7f54a31cde6fa5cb030370566f68152a742f433f8d2be458463d06c208aef33", - "sha256:c83b85ab2d6576607f31df77ff86f28182be4a8de6d175d2c33ca609925f5da1", - "sha256:caa4e560c72c151da80036aecc2159e51a7fd8ae9efebefd96860460ce6bd025", - "sha256:d3233770f78e637dc8b1fda2cd7c3b99ec77e7505041934188a4e7fe751de3b0", - "sha256:d7b670879c370d350557edabadbad1f6561a9e6968126e6debca4029e5547820", - "sha256:d8b1d91545578852f128650b8cce4ec20f93d39b378ff554ebe66290f2dabb92", - "sha256:d9381351182ff9888cc80e41c632e7e274b106f450de33d67a9e8f6043da6f76", - "sha256:daeb5e9e9fcad012324807856113708614d534f596d5008638eb9b40112cd9e4", - "sha256:dcd8161eee7b41aae57ded06272905dbd680a0a04b91edd0f64790c796b2f706", - "sha256:e10fa50bdbaa5e2445dbd387979980d391760faf0ec99a09bd7780ff37eaec44", - "sha256:e37e4b4c4a11662b5db521def4e44d4d30ae69a1743241412a93ae40fdcab4bb", - "sha256:e52144670738b4b477fade6c2a9b6af71a8d0094514c9853ac9f6fc1fcfabae7" - ], - "markers": "python_version >= '3.9'", - "version": "==0.2.1" - }, - "setuptools": { - "hashes": [ - "sha256:22e0a2d69474c6ae4feb01951cb69d515ed23728cf96d05513d36e42b62b37cb", - "sha256:70b18734b607bd1da571d097d236cfcfacaf01de45717d59e6e04b96877532e0" - ], - "markers": "python_version >= '3.9'", - "version": "==82.0.0" - }, - "shellingham": { - "hashes": [ - "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", - "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de" - ], - "markers": "python_version >= '3.7'", - "version": "==1.5.4" - }, - "six": { - "hashes": [ - "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", - "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", - "version": "==1.17.0" - }, - "sniffio": { - "hashes": [ - "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", - "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc" - ], - "markers": "python_version >= '3.7'", - "version": "==1.3.1" - }, - "sqlite-fts4": { - "hashes": [ - "sha256:0359edd8dea6fd73c848989e1e2b1f31a50fe5f9d7272299ff0e8dbaa62d035f", - "sha256:78b05eeaf6680e9dbed8986bde011e9c086a06cb0c931b3cf7da94c214e8930c" - ], - "version": "==1.0.3" - }, - "sqlite-migrate": { - "hashes": [ - "sha256:8d502b3ca4b9c45e56012bd35c03d23235f0823c976d4ce940cbb40e33087ded", - "sha256:a4125e35e1de3dc56b6b6ec60e9833ce0ce20192b929ddcb2d4246c5098859c6" - ], - "version": "==0.1b0" - }, - "sqlite-utils": { - "hashes": [ - "sha256:349c099c0cd60d4ee9139a24d5c9cb64af3906c3e90832fcbbd74da49333374d", - "sha256:bfa2eac29b3e3eb5c9647283797527febcf4efd4a9bbb31d979a14a11ef9dbcd" - ], - "markers": "python_version >= '3.10'", - "version": "==3.39" - }, - "tabulate": { - "hashes": [ - "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c", - "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f" - ], - "markers": "python_version >= '3.7'", - "version": "==0.9.0" - }, - "tokenizers": { - "hashes": [ - "sha256:143b999bdc46d10febb15cbffb4207ddd1f410e2c755857b5a0797961bbdc113", - "sha256:1a62ba2c5faa2dd175aaeed7b15abf18d20266189fb3406c5d0550dd34dd5f37", - "sha256:1c774b1276f71e1ef716e5486f21e76333464f47bece56bbd554485982a9e03e", - "sha256:1e418a55456beedca4621dbab65a318981467a2b188e982a23e117f115ce5001", - "sha256:1e50f8554d504f617d9e9d6e4c2c2884a12b388a97c5c77f0bc6cf4cd032feee", - "sha256:2249487018adec45d6e3554c71d46eb39fa8ea67156c640f7513eb26f318cec7", - "sha256:25b85325d0815e86e0bac263506dd114578953b7b53d7de09a6485e4a160a7dd", - "sha256:29c30b83d8dcd061078b05ae0cb94d3c710555fbb44861139f9f83dcca3dc3e4", - "sha256:319f659ee992222f04e58f84cbf407cfa66a65fe3a8de44e8ad2bc53e7d99012", - "sha256:369cc9fc8cc10cb24143873a0d95438bb8ee257bb80c71989e3ee290e8d72c67", - "sha256:37ae80a28c1d3265bb1f22464c856bd23c02a05bb211e56d0c5301a435be6c1a", - "sha256:38337540fbbddff8e999d59970f3c6f35a82de10053206a7562f1ea02d046fa5", - "sha256:473b83b915e547aa366d1eee11806deaf419e17be16310ac0a14077f1e28f917", - "sha256:544dd704ae7238755d790de45ba8da072e9af3eea688f698b137915ae959281c", - "sha256:64d94e84f6660764e64e7e0b22baa72f6cd942279fdbb21d46abd70d179f0195", - "sha256:753d47ebd4542742ef9261d9da92cd545b2cacbb48349a1225466745bb866ec4", - "sha256:791135ee325f2336f498590eb2f11dc5c295232f288e75c99a36c5dbce63088a", - "sha256:9ce725d22864a1e965217204946f830c37876eee3b2ba6fc6255e8e903d5fcbc", - "sha256:a6bf3f88c554a2b653af81f3204491c818ae2ac6fbc09e76ef4773351292bc92", - "sha256:bfb88f22a209ff7b40a576d5324bf8286b519d7358663db21d6246fb17eea2d5", - "sha256:c9ea31edff2968b44a88f97d784c2f16dc0729b8b143ed004699ebca91f05c48", - "sha256:df6c4265b289083bf710dff49bc51ef252f9d5be33a45ee2bed151114a56207b", - "sha256:e10bf9113d209be7cd046d40fbabbaf3278ff6d18eb4da4c500443185dc1896c", - "sha256:f01a9c019878532f98927d2bacb79bbb404b43d3437455522a00a30718cdedb5" - ], - "markers": "python_version >= '3.9'", - "version": "==0.22.2" - }, - "tqdm": { - "hashes": [ - "sha256:7d825f03f89244ef73f1d4ce193cb1774a8179fd96f31d7e1dcde62092b960bb", - "sha256:ee1e4c0e59148062281c49d80b25b67771a127c85fc9676d3be5f243206826bf" - ], - "markers": "python_version >= '3.7'", - "version": "==4.67.3" - }, - "transformers": { - "hashes": [ - "sha256:0088b8b46ccc9eff1a1dca72b5d618a5ee3b1befc3e418c9512b35dea9f9a650", - "sha256:9ecaf243dc45bee11a7d93f8caf03746accc0cb069181bbf4ad8566c53e854b4" - ], - "markers": "python_full_version >= '3.10.0'", - "version": "==5.2.0" - }, - "typer": { - "hashes": [ - "sha256:112c1f0ce578bfb4cab9ffdabc68f031416ebcc216536611ba21f04e9aa84c9e", - "sha256:e39b4732d65fbdcde189ae76cf7cd48aeae72919dea1fdfc16593be016256b45" - ], - "markers": "python_version >= '3.10'", - "version": "==0.24.1" - }, - "typer-slim": { - "hashes": [ - "sha256:d5d7ee1ee2834d5020c7c616ed5e0d0f29b9a4b1dd283bdebae198ec09778d0e", - "sha256:f0ed36127183f52ae6ced2ecb2521789995992c521a46083bfcdbb652d22ad34" - ], - "markers": "python_version >= '3.10'", - "version": "==0.24.0" - }, - "typing-extensions": { - "hashes": [ - "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", - "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548" - ], - "markers": "python_version >= '3.9'", - "version": "==4.15.0" - }, - "typing-inspection": { - "hashes": [ - "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", - "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464" - ], - "markers": "python_version >= '3.9'", - "version": "==0.4.2" + "version": "==2.6.3" } } } diff --git a/lint_commits.py b/lint_commits.py index 1706ce4..ee76ba0 100644 --- a/lint_commits.py +++ b/lint_commits.py @@ -13,6 +13,7 @@ import re import sys from dataclasses import dataclass, field +from typing import Any import llm import requests @@ -235,7 +236,7 @@ def _extract_flagged_word(match: dict, text: str) -> str: offset = match.get("offset", 0) length = match.get("length", 0) if offset >= 0 and length > 0 and offset + length <= len(text): - return text[offset:offset + length] + return text[offset : offset + length] return "" @@ -322,9 +323,9 @@ def get_llm_model(model_id: str, api_key: str = "") -> llm.Model: return model -def _parse_llm_json(text: str) -> dict: +def _parse_llm_json(text: str) -> dict[str, Any]: """Strip optional markdown fences and parse JSON from an LLM response. - + Handles common issues with small models producing malformed JSON. """ text = text.strip() @@ -333,7 +334,7 @@ def _parse_llm_json(text: str) -> dict: if text.endswith("```"): text = "\n".join(text.split("\n")[:-1]) text = text.strip() - + # Try to parse as-is first try: return json.loads(text) @@ -341,9 +342,10 @@ def _parse_llm_json(text: str) -> dict: # Small models sometimes produce invalid JSON with unescaped quotes # Try some basic fixes import re + # Fix common issue: "word" inside a string value (should be \"word\") # This is a heuristic - may not catch all cases - lines = text.split('\n') + lines = text.split("\n") fixed_lines = [] for line in lines: # If line contains a key-value pair with quotes in the value @@ -357,11 +359,11 @@ def _parse_llm_json(text: str) -> dict: value = value.replace('"', '\\"') line = prefix + value + suffix fixed_lines.append(line) - text = '\n'.join(fixed_lines) + text = "\n".join(fixed_lines) return json.loads(text) -def check_structure(message: str, model: llm.Model | None = None) -> dict: +def check_structure(message: str, model: llm.Model | None = None) -> dict[str, Any]: """Use an LLM to evaluate whether a commit message explains *why*. Returns a dict with keys: explains_why, score, feedback, suggestion. @@ -374,12 +376,12 @@ def check_structure(message: str, model: llm.Model | None = None) -> dict: response = model.prompt(message, system=SYSTEM_PROMPT) text = response.text() result = _parse_llm_json(text) - + # Enforce the rule: only suggest rewrites for scores < 7 # Small models sometimes don't follow instructions perfectly if result.get("score", 0) >= 7: result["suggestion"] = None - + return result except Exception as exc: print(f"WARNING: LLM structure check failed: {exc}", file=sys.stderr) @@ -419,8 +421,8 @@ def build_report(results: list[CommitIssue]) -> str: for gi in r.grammar_issues: suggestion = "" if gi["replacements"]: - suggestion = f' -> try: *{", ".join(gi["replacements"])}*' - lines.append(f'- {gi["message"]}{suggestion} (`{gi["rule"]}`)') + suggestion = f" -> try: *{', '.join(gi['replacements'])}*" + lines.append(f"- {gi['message']}{suggestion} (`{gi['rule']}`)") lines.append("") if r.structure_issues: @@ -480,12 +482,12 @@ def main() -> int: ci.score = result.get("score") ci.suggestion = result.get("suggestion") feedback = result.get("feedback", "") - + # Only treat feedback as an issue if the commit doesn't explain why # or if it scores below 7 (our threshold for "good enough") explains_why = result.get("explains_why", True) score = result.get("score", 0) - + if not explains_why or score < 7: if feedback: ci.structure_issues = [feedback] diff --git a/lint_local.py b/lint_local.py index ffd1f88..ba46583 100644 --- a/lint_local.py +++ b/lint_local.py @@ -29,11 +29,11 @@ import argparse import json -import os import re import subprocess import sys from dataclasses import dataclass, field +from typing import Any import llm import requests @@ -198,7 +198,6 @@ def git_log(revision_range: str | None = None, last_n: int | None = None) -> lis cmd.extend(["-n", str(last_n)]) else: cmd.extend(["-n", "5"]) - try: result = subprocess.run(cmd, capture_output=True, text=True, check=True) except subprocess.CalledProcessError as exc: @@ -216,10 +215,10 @@ def git_log(revision_range: str | None = None, last_n: int | None = None) -> lis f"\n" f"Suggestion: Check if the base commit exists with:\n" f" git cat-file -t {revision_range.split('..')[0] if '..' in revision_range else 'BASE_SHA'}\n", - file=sys.stderr + file=sys.stderr, ) raise - + raw = result.stdout.strip() if not raw: return [] @@ -247,7 +246,7 @@ def _extract_flagged_word(match: dict, text: str) -> str: offset = match.get("offset", 0) length = match.get("length", 0) if offset >= 0 and length > 0 and offset + length <= len(text): - return text[offset:offset + length] + return text[offset : offset + length] return "" @@ -336,9 +335,9 @@ def get_llm_model(model_id: str, api_key: str = "") -> llm.Model: return model -def _parse_llm_json(text: str) -> dict: +def _parse_llm_json(text: str) -> dict[str, Any]: """Strip optional markdown fences and parse JSON from an LLM response. - + Handles common issues with small models producing malformed JSON. """ text = text.strip() @@ -347,7 +346,7 @@ def _parse_llm_json(text: str) -> dict: if text.endswith("```"): text = "\n".join(text.split("\n")[:-1]) text = text.strip() - + # Try to parse as-is first try: return json.loads(text) @@ -355,9 +354,10 @@ def _parse_llm_json(text: str) -> dict: # Small models sometimes produce invalid JSON with unescaped quotes # Try some basic fixes import re + # Fix common issue: "word" inside a string value (should be \"word\") # This is a heuristic - may not catch all cases - lines = text.split('\n') + lines = text.split("\n") fixed_lines = [] for line in lines: # If line contains a key-value pair with quotes in the value @@ -371,11 +371,13 @@ def _parse_llm_json(text: str) -> dict: value = value.replace('"', '\\"') line = prefix + value + suffix fixed_lines.append(line) - text = '\n'.join(fixed_lines) + text = "\n".join(fixed_lines) return json.loads(text) -def check_structure(message: str, model: llm.Model | None = None, model_id: str = "", api_key: str = "") -> dict: +def check_structure( + message: str, model: llm.Model | None = None, model_id: str = "", api_key: str = "" +) -> dict[str, Any]: """Use an LLM to evaluate whether a commit message explains *why*. Pass either a pre-loaded *model* or a *model_id* (+ optional *api_key*) @@ -391,12 +393,12 @@ def check_structure(message: str, model: llm.Model | None = None, model_id: str response = model.prompt(message, system=SYSTEM_PROMPT) text = response.text() result = _parse_llm_json(text) - + # Enforce the rule: only suggest rewrites for scores < 7 # Small models sometimes don't follow instructions perfectly if result.get("score", 0) >= 7: result["suggestion"] = None - + return result except Exception as exc: print(f"WARNING: LLM structure check failed: {exc}", file=sys.stderr) @@ -443,7 +445,7 @@ def print_report(results: list[CommitIssue]) -> None: for gi in r.grammar_issues: suggestion = "" if gi["replacements"]: - suggestion = f' -> try: {", ".join(gi["replacements"])}' + suggestion = f" -> try: {', '.join(gi['replacements'])}" print(f" - {gi['message']}{suggestion} ({gi['rule']})") if r.structure_issues: @@ -496,7 +498,11 @@ def parse_args(argv: list[str] | None = None) -> argparse.Namespace: action="store_true", help="Enable the LanguageTool grammar checker (disabled by default)", ) - p.add_argument("--grammar-only", action="store_true", help="Only run the grammar check (implies --enable-grammar)") + p.add_argument( + "--grammar-only", + action="store_true", + help="Only run the grammar check (implies --enable-grammar)", + ) p.add_argument("--structure-only", action="store_true", help="Only run the LLM structure check") # LLM (via the llm library -- model discovery handled by llm + plugins) @@ -610,17 +616,19 @@ def main(argv: list[str] | None = None) -> int: ci.score = result.get("score") ci.suggestion = result.get("suggestion") feedback = result.get("feedback", "") - + # Only treat feedback as an issue if the commit doesn't explain why # or if it scores below 7 (our threshold for "good enough") explains_why = result.get("explains_why", True) score = result.get("score", 0) - + if not explains_why or score < 7: if feedback: ci.structure_issues = [feedback] elif not explains_why: - ci.structure_issues = ["Commit message does not explain why the change was made"] + ci.structure_issues = [ + "Commit message does not explain why the change was made" + ] results.append(ci) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..fa6ad40 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,49 @@ +[tool.ruff] +target-version = "py313" +line-length = 100 + +[tool.ruff.lint] +select = [ + "E", # pycodestyle errors + "W", # pycodestyle warnings + "F", # pyflakes + "I", # isort (import sorting) + "B", # flake8-bugbear + "C4", # flake8-comprehensions + "UP", # pyupgrade + "SIM", # flake8-simplify + "TCH", # flake8-type-checking + "RUF", # Ruff-specific rules +] +ignore = [ + "E501", # line too long (let formatter handle it) +] + +[tool.ruff.lint.isort] +known-first-party = ["lint_commits", "lint_local"] + +[tool.ruff.format] +quote-style = "double" +indent-style = "space" + +[tool.mypy] +python_version = "3.13" +warn_return_any = false +warn_unused_ignores = true +disallow_untyped_defs = true +disallow_incomplete_defs = true +check_untyped_defs = true +strict_optional = true +ignore_missing_imports = false + +[[tool.mypy.overrides]] +module = "llm.*" +ignore_missing_imports = true + +[[tool.mypy.overrides]] +module = "tests.*" +ignore_errors = true + +[[tool.mypy.overrides]] +module = "conftest" +ignore_errors = true diff --git a/tests/test_integration_ollama.py b/tests/test_integration_ollama.py index bf8f9b6..7aef6ee 100644 --- a/tests/test_integration_ollama.py +++ b/tests/test_integration_ollama.py @@ -18,7 +18,6 @@ from __future__ import annotations -import json import os import sys @@ -49,6 +48,7 @@ def ollama_model_id(): def ollama_model(ollama_model_id): """Load the model once per test module via the llm library.""" from lint_local import get_llm_model + return get_llm_model(ollama_model_id) @@ -70,12 +70,12 @@ def _check(self, model, message: str) -> dict: def test_good_commit(self, ollama_model): """A well-formed commit that explains why should score high. - + Small models may occasionally produce non-JSON output, so we use check_structure which has error handling. """ from lint_local import check_structure - + result = check_structure( "Add rate limiting to the login endpoint\n\n" "Without rate limiting, the login endpoint is vulnerable to brute-force\n" @@ -91,16 +91,14 @@ def test_good_commit(self, ollama_model): def test_vague_commit(self, ollama_model): """A vague one-word commit should score low. - + Small models can be inconsistent about explains_why boolean, so we primarily check the score. """ result = self._check(ollama_model, "updates") assert "explains_why" in result # Small models may not always set explains_why=False, but should score low - assert result["score"] <= 5, ( - f"Vague commits should score low. Got {result['score']}/10" - ) + assert result["score"] <= 5, f"Vague commits should score low. Got {result['score']}/10" def test_returns_valid_json(self, ollama_model): """Even for edge cases the model should return parseable JSON.""" @@ -118,7 +116,7 @@ class TestOllamaEndToEnd: def test_check_structure_returns_dict(self, ollama_model): """check_structure should return a dict with the expected keys. - + Small models can be inconsistent, so we just verify the structure. """ from lint_local import check_structure @@ -135,7 +133,7 @@ def test_check_structure_returns_dict(self, ollama_model): def test_check_structure_clean_commit(self, ollama_model): """A good commit should explain why and score high. - + Note: Small models like qwen2.5:0.5b can be inconsistent, so we just check that the score is reasonable (>= 6) rather than strictly checking explains_why, which can vary run-to-run. @@ -160,7 +158,7 @@ def test_git_hygiene_commit_scores_high(self, ollama_model): The commit that adds git hygiene to the project should score 8+ and be considered good. This validates that the system prompt is balanced and not overly aggressive. - + The commit explains WHY (to ensure quality of git commits) and provides context about the new workflow. It should not trigger suggestions for being "more comprehensive" when it already explains the motivation. @@ -177,26 +175,26 @@ def test_git_hygiene_commit_scores_high(self, ollama_model): git commits in this code base.""" result = check_structure(commit_message, model=ollama_model) - + # Validate response structure assert isinstance(result, dict) assert "explains_why" in result assert "score" in result assert "feedback" in result assert "suggestion" in result - + # The commit clearly explains WHY - to ensure quality assert result["explains_why"] is True, ( f"Commit should explain why. Got: {result['feedback']}" ) - + # Should score 7 or higher since it explains the motivation # (Small models can vary between 7-9 for the same good commit) assert result["score"] >= 7, ( f"Expected score >= 7 for a commit that explains why (quality assurance). " f"Got {result['score']}/10. Feedback: {result['feedback']}" ) - + # Since score >= 8, should not suggest rewrite assert result["suggestion"] is None or result["suggestion"] == "", ( f"High-scoring commits (8+) should not need rewrites. " diff --git a/tests/test_lint_commits.py b/tests/test_lint_commits.py index 058b95d..bf77f53 100644 --- a/tests/test_lint_commits.py +++ b/tests/test_lint_commits.py @@ -8,8 +8,6 @@ import sys from unittest.mock import MagicMock, patch -import pytest - # Ensure the project root is on sys.path so we can import the module sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) @@ -18,8 +16,7 @@ os.environ.setdefault("REPO", "owner/repo") os.environ.setdefault("PR_NUMBER", "1") -import lint_commits # noqa: E402 - +import lint_commits # --------------------------------------------------------------------------- # Grammar check @@ -73,9 +70,7 @@ def test_custom_word_suppresses_match(self): mock_resp.raise_for_status = MagicMock() with patch("lint_commits.requests.post", return_value=mock_resp): - issues = lint_commits.check_grammar( - "Set up an Ollama server", custom_words={"ollama"} - ) + issues = lint_commits.check_grammar("Set up an Ollama server", custom_words={"ollama"}) assert issues == [] def test_custom_word_case_insensitive(self): @@ -93,9 +88,7 @@ def test_custom_word_case_insensitive(self): mock_resp.raise_for_status = MagicMock() with patch("lint_commits.requests.post", return_value=mock_resp): - issues = lint_commits.check_grammar( - "Use the NGINX proxy", custom_words={"nginx"} - ) + issues = lint_commits.check_grammar("Use the NGINX proxy", custom_words={"nginx"}) assert issues == [] def test_non_dictionary_word_still_reported(self): @@ -113,9 +106,7 @@ def test_non_dictionary_word_still_reported(self): mock_resp.raise_for_status = MagicMock() with patch("lint_commits.requests.post", return_value=mock_resp): - issues = lint_commits.check_grammar( - "Fix teh build", custom_words={"ollama", "nginx"} - ) + issues = lint_commits.check_grammar("Fix teh build", custom_words={"ollama", "nginx"}) assert len(issues) == 1 def test_builtin_words_used_by_default(self): @@ -206,12 +197,14 @@ def _mock_model(self, response_text: str) -> MagicMock: def test_good_commit(self): """LLM recognises a commit that explains why.""" - llm_response = json.dumps({ - "explains_why": True, - "score": 9, - "feedback": "Good commit message that explains the motivation.", - "suggestion": None, - }) + llm_response = json.dumps( + { + "explains_why": True, + "score": 9, + "feedback": "Good commit message that explains the motivation.", + "suggestion": None, + } + ) model = self._mock_model(llm_response) result = lint_commits.check_structure( "Add user avatar upload\n\nUsers requested the ability to upload custom avatars.", @@ -223,12 +216,14 @@ def test_good_commit(self): def test_poor_commit(self): """LLM flags a commit that does not explain why.""" - llm_response = json.dumps({ - "explains_why": False, - "score": 2, - "feedback": "This commit only states what changed, not why.", - "suggestion": "Fix typo in README\n\nThe API endpoint URL had a trailing slash.", - }) + llm_response = json.dumps( + { + "explains_why": False, + "score": 2, + "feedback": "This commit only states what changed, not why.", + "suggestion": "Fix typo in README\n\nThe API endpoint URL had a trailing slash.", + } + ) model = self._mock_model(llm_response) result = lint_commits.check_structure("updates", model=model) assert result["explains_why"] is False @@ -237,10 +232,14 @@ def test_poor_commit(self): def test_markdown_fenced_response(self): """LLM wraps response in markdown fences -- still parsed.""" - inner = json.dumps({ - "explains_why": False, "score": 3, - "feedback": "Missing context.", "suggestion": None, - }) + inner = json.dumps( + { + "explains_why": False, + "score": 3, + "feedback": "Missing context.", + "suggestion": None, + } + ) llm_response = f"```json\n{inner}\n```" model = self._mock_model(llm_response) result = lint_commits.check_structure("Fix bug", model=model) @@ -257,10 +256,14 @@ def test_llm_failure(self): def test_system_prompt_passed(self): """check_structure passes the system prompt to model.prompt.""" - llm_response = json.dumps({ - "explains_why": True, "score": 8, - "feedback": "Good.", "suggestion": None, - }) + llm_response = json.dumps( + { + "explains_why": True, + "score": 8, + "feedback": "Good.", + "suggestion": None, + } + ) model = self._mock_model(llm_response) lint_commits.check_structure("some commit", model=model) @@ -338,7 +341,7 @@ def test_normal_commit_not_ignored(self): class TestRegressions: def test_high_score_with_positive_feedback_not_treated_as_issue(self): """Regression test: positive feedback on a 10/10 commit should not fail. - + Bug: feedback was always treated as an issue, even positive feedback. Fix: only treat feedback as an issue if score < 7 or explains_why is False. """ @@ -350,17 +353,18 @@ def test_high_score_with_positive_feedback_not_treated_as_issue(self): ci.suggestion = None # This is positive feedback but was incorrectly treated as an issue ci.structure_issues = [] - + # Simulate what the fixed code should do feedback = "The commit explains the reason for the change, which is excellent." explains_why = True score = 10 - + # The bug: old code did: if feedback: ci.structure_issues = [feedback] # The fix: only add feedback as issue if score < 7 or not explains_why - if not explains_why or score < 7: - if feedback: - ci.structure_issues = [feedback] - + if (not explains_why or score < 7) and feedback: + ci.structure_issues = [feedback] + # With score=10 and explains_why=True, should have no issues - assert not ci.has_issues, "High-scoring commits with positive feedback should not be flagged as having issues" + assert not ci.has_issues, ( + "High-scoring commits with positive feedback should not be flagged as having issues" + ) diff --git a/tests/test_lint_local.py b/tests/test_lint_local.py index 90b786a..50aaf5b 100644 --- a/tests/test_lint_local.py +++ b/tests/test_lint_local.py @@ -4,8 +4,6 @@ import json import os -import re -import subprocess import sys from unittest.mock import MagicMock, patch @@ -19,8 +17,7 @@ os.environ.setdefault("REPO", "owner/repo") os.environ.setdefault("PR_NUMBER", "1") -import lint_local # noqa: E402 - +import lint_local # --------------------------------------------------------------------------- # git_log @@ -57,7 +54,7 @@ def test_revision_range(self): mock_result.returncode = 0 with patch("lint_local.subprocess.run", return_value=mock_result) as mock_run: - commits = lint_local.git_log(revision_range="main..HEAD") + lint_local.git_log(revision_range="main..HEAD") cmd = mock_run.call_args[0][0] assert "main..HEAD" in cmd @@ -147,9 +144,7 @@ def test_builtin_words_used_by_default(self): mock_resp.raise_for_status = MagicMock() with patch("lint_local.requests.post", return_value=mock_resp): - issues = lint_local.check_grammar( - text, "https://api.languagetool.org/v2", "en-US" - ) + issues = lint_local.check_grammar(text, "https://api.languagetool.org/v2", "en-US") assert issues == [] def test_non_dictionary_word_still_reported(self): @@ -214,10 +209,14 @@ def _mock_model(response_text: str) -> MagicMock: class TestCheckStructureLocal: def test_good_commit(self): """LLM response for a good commit is parsed correctly.""" - llm_response = json.dumps({ - "explains_why": True, "score": 9, - "feedback": "Clear motivation provided.", "suggestion": None, - }) + llm_response = json.dumps( + { + "explains_why": True, + "score": 9, + "feedback": "Clear motivation provided.", + "suggestion": None, + } + ) model = _mock_model(llm_response) result = lint_local.check_structure( "Fix typo\n\nThe URL had a trailing slash.", model=model @@ -227,10 +226,14 @@ def test_good_commit(self): def test_poor_commit(self): """LLM flags a vague commit.""" - llm_response = json.dumps({ - "explains_why": False, "score": 2, - "feedback": "Does not explain why.", "suggestion": "Describe the reason.", - }) + llm_response = json.dumps( + { + "explains_why": False, + "score": 2, + "feedback": "Does not explain why.", + "suggestion": "Describe the reason.", + } + ) model = _mock_model(llm_response) result = lint_local.check_structure("stuff", model=model) assert result["explains_why"] is False @@ -247,10 +250,14 @@ def test_error_returns_error_dict(self): def test_system_prompt_passed(self): """check_structure passes the system prompt to model.prompt.""" - llm_response = json.dumps({ - "explains_why": True, "score": 8, - "feedback": "Good.", "suggestion": None, - }) + llm_response = json.dumps( + { + "explains_why": True, + "score": 8, + "feedback": "Good.", + "suggestion": None, + } + ) model = _mock_model(llm_response) lint_local.check_structure("some commit", model=model) @@ -261,10 +268,14 @@ def test_system_prompt_passed(self): def test_falls_back_to_model_id(self): """When no model object given, loads by model_id.""" - llm_response = json.dumps({ - "explains_why": True, "score": 8, - "feedback": "Good.", "suggestion": None, - }) + llm_response = json.dumps( + { + "explains_why": True, + "score": 8, + "feedback": "Good.", + "suggestion": None, + } + ) model = _mock_model(llm_response) with patch("lint_local.get_llm_model", return_value=model) as mock_get: lint_local.check_structure("commit msg", model_id="tinyllama") @@ -342,17 +353,24 @@ def _mock_commits(self): ] def _good_response(self): - return json.dumps({ - "explains_why": True, "score": 9, - "feedback": "Good commit.", "suggestion": None, - }) + return json.dumps( + { + "explains_why": True, + "score": 9, + "feedback": "Good commit.", + "suggestion": None, + } + ) def _bad_response(self): - return json.dumps({ - "explains_why": False, "score": 2, - "feedback": "Does not explain why the change was made.", - "suggestion": "stuff\n\nExplain the reason here.", - }) + return json.dumps( + { + "explains_why": False, + "score": 2, + "feedback": "Does not explain why the change was made.", + "suggestion": "stuff\n\nExplain the reason here.", + } + ) def _mock_model_with(self, response_text: str) -> MagicMock: return _mock_model(response_text) @@ -408,14 +426,21 @@ def test_main_returns_1_on_issues(self): assert rc == 1 def test_main_returns_0_when_clean(self): - clean = json.dumps({ - "explains_why": True, "score": 10, - "feedback": "", "suggestion": None, - }) + clean = json.dumps( + { + "explains_why": True, + "score": 10, + "feedback": "", + "suggestion": None, + } + ) model = self._mock_model_with(clean) with ( - patch("lint_local.git_log", return_value=[{"sha": "aaa111", "message": "Fix typo in README"}]), + patch( + "lint_local.git_log", + return_value=[{"sha": "aaa111", "message": "Fix typo in README"}], + ), patch("lint_local.check_grammar", return_value=[]), patch("lint_local.get_llm_model", return_value=model), ): @@ -425,23 +450,30 @@ def test_main_returns_0_when_clean(self): def test_main_returns_0_for_high_score_with_positive_feedback(self): """Regression test: positive feedback on a 10/10 commit should not fail. - + Bug: feedback was always treated as an issue, even positive feedback. Fix: only treat feedback as an issue if score < 7 or explains_why is False. """ - high_score_with_positive_feedback = json.dumps({ - "explains_why": True, - "score": 10, - "feedback": "The commit explains the reason for the change, which is excellent.", - "suggestion": None, - }) + high_score_with_positive_feedback = json.dumps( + { + "explains_why": True, + "score": 10, + "feedback": "The commit explains the reason for the change, which is excellent.", + "suggestion": None, + } + ) model = self._mock_model_with(high_score_with_positive_feedback) with ( - patch("lint_local.git_log", return_value=[{ - "sha": "8eed9917", - "message": "Allow a looser definition of what a good git message means" - }]), + patch( + "lint_local.git_log", + return_value=[ + { + "sha": "8eed9917", + "message": "Allow a looser definition of what a good git message means", + } + ], + ), patch("lint_local.check_grammar", return_value=[]), patch("lint_local.get_llm_model", return_value=model), ):