From f618b34a5ab0ecfd2f5ab62a3e3e7a39503fdbec Mon Sep 17 00:00:00 2001 From: Bouni Date: Fri, 19 Jan 2024 10:09:09 +0100 Subject: [PATCH 01/13] Upgrade dependencies --- Pipfile | 17 +- Pipfile.lock | 682 +++++++++++++++++++++++++++++++-------------------- 2 files changed, 424 insertions(+), 275 deletions(-) diff --git a/Pipfile b/Pipfile index f4ec194..290a588 100644 --- a/Pipfile +++ b/Pipfile @@ -4,15 +4,16 @@ url = "https://pypi.org/simple" verify_ssl = true [dev-packages] -pytest = "==7.1.3" -requests = "==2.28.1" -pre-commit = "==2.20.0" -GitPython = "==3.1.9" -flake8 = "==5.0.4" +pytest = "==7.4.4" +requests = "==2.31.0" +pre-commit = "==3.6.0" +GitPython = "==3.1.41" +flake8 = "==7.0.0" +httpx = "==0.26.0" [packages] -fastapi = "==0.85.1" -uvicorn = "==0.18.3" +fastapi = "==0.109.0" +uvicorn = "==0.26.0" [requires] -python_version = "3.9" +python_version = "3.11" diff --git a/Pipfile.lock b/Pipfile.lock index 083f8b6..3e33eab 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,11 +1,11 @@ { "_meta": { "hash": { - "sha256": "bd533d34bede849ad67d149edac468ec08411f4ca1133a931d1706f33786fbc8" + "sha256": "2da1605b662d1a7b345e4db24b8f5e9b54be351429523ed9d0dbeb1c6bbdb1c6" }, "pipfile-spec": 6, "requires": { - "python_version": "3.9" + "python_version": "3.11" }, "sources": [ { @@ -16,37 +16,38 @@ ] }, "default": { - "anyio": { + "annotated-types": { "hashes": [ - "sha256:413adf95f93886e442aea925f3ee43baa5a765a64a0f52c6081894f9992fdd0b", - "sha256:cb29b9c70620506a9a8f87a309591713446953302d7d995344d0d7c6c0c9a7be" + "sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43", + "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d" ], - "markers": "python_full_version >= '3.6.2'", - "version": "==3.6.1" + "markers": "python_version >= '3.8'", + "version": "==0.6.0" }, - "click": { + "anyio": { "hashes": [ - "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e", - "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48" + "sha256:745843b39e829e108e518c489b31dc757de7d2131d53fac32bd8df268227bfee", + "sha256:e1875bb4b4e2de1669f4bc7869b6d3f54231cdced71605e6e64c9be77e3be50f" ], - "markers": "python_version >= '3.7'", - "version": "==8.1.3" + "markers": "python_version >= '3.8'", + "version": "==4.2.0" }, - "colorama": { + "click": { "hashes": [ - "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da", - "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4" + "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", + "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de" ], - "markers": "platform_system == 'Windows'", - "version": "==0.4.5" + "markers": "python_version >= '3.7'", + "version": "==8.1.7" }, "fastapi": { "hashes": [ - "sha256:1facd097189682a4ff11cbd01334a992e51b56be663b2bd50c2c09523624f144", - "sha256:de3166b6b1163dc22da4dc4ebdc3192fcbac7700dd1870a1afa44de636a636b5" + "sha256:8c77515984cd8e8cfeb58364f8cc7a28f0692088475e2614f7bf03275eba9093", + "sha256:b978095b9ee01a5cf49b19f4bc1ac9b8ca83aa076e770ef8fd9af09a2b88d191" ], "index": "pypi", - "version": "==0.85.1" + "markers": "python_version >= '3.8'", + "version": "==0.109.0" }, "h11": { "hashes": [ @@ -58,53 +59,130 @@ }, "idna": { "hashes": [ - "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4", - "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2" + "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca", + "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f" ], "markers": "python_version >= '3.5'", - "version": "==3.4" + "version": "==3.6" }, "pydantic": { "hashes": [ - "sha256:05e00dbebbe810b33c7a7362f231893183bcc4251f3f2ff991c31d5c08240c42", - "sha256:06094d18dd5e6f2bbf93efa54991c3240964bb663b87729ac340eb5014310624", - "sha256:0b959f4d8211fc964772b595ebb25f7652da3f22322c007b6fed26846a40685e", - "sha256:19b3b9ccf97af2b7519c42032441a891a5e05c68368f40865a90eb88833c2559", - "sha256:1b6ee725bd6e83ec78b1aa32c5b1fa67a3a65badddde3976bca5fe4568f27709", - "sha256:1ee433e274268a4b0c8fde7ad9d58ecba12b069a033ecc4645bb6303c062d2e9", - "sha256:216f3bcbf19c726b1cc22b099dd409aa371f55c08800bcea4c44c8f74b73478d", - "sha256:2d0567e60eb01bccda3a4df01df677adf6b437958d35c12a3ac3e0f078b0ee52", - "sha256:2e05aed07fa02231dbf03d0adb1be1d79cabb09025dd45aa094aa8b4e7b9dcda", - "sha256:352aedb1d71b8b0736c6d56ad2bd34c6982720644b0624462059ab29bd6e5912", - "sha256:355639d9afc76bcb9b0c3000ddcd08472ae75318a6eb67a15866b87e2efa168c", - "sha256:37c90345ec7dd2f1bcef82ce49b6235b40f282b94d3eec47e801baf864d15525", - "sha256:4b8795290deaae348c4eba0cebb196e1c6b98bdbe7f50b2d0d9a4a99716342fe", - "sha256:5760e164b807a48a8f25f8aa1a6d857e6ce62e7ec83ea5d5c5a802eac81bad41", - "sha256:6eb843dcc411b6a2237a694f5e1d649fc66c6064d02b204a7e9d194dff81eb4b", - "sha256:7b5ba54d026c2bd2cb769d3468885f23f43710f651688e91f5fb1edcf0ee9283", - "sha256:7c2abc4393dea97a4ccbb4ec7d8658d4e22c4765b7b9b9445588f16c71ad9965", - "sha256:81a7b66c3f499108b448f3f004801fcd7d7165fb4200acb03f1c2402da73ce4c", - "sha256:91b8e218852ef6007c2b98cd861601c6a09f1aa32bbbb74fab5b1c33d4a1e410", - "sha256:9300fcbebf85f6339a02c6994b2eb3ff1b9c8c14f502058b5bf349d42447dcf5", - "sha256:9cabf4a7f05a776e7793e72793cd92cc865ea0e83a819f9ae4ecccb1b8aa6116", - "sha256:a1f5a63a6dfe19d719b1b6e6106561869d2efaca6167f84f5ab9347887d78b98", - "sha256:a4c805731c33a8db4b6ace45ce440c4ef5336e712508b4d9e1aafa617dc9907f", - "sha256:ae544c47bec47a86bc7d350f965d8b15540e27e5aa4f55170ac6a75e5f73b644", - "sha256:b97890e56a694486f772d36efd2ba31612739bc6f3caeee50e9e7e3ebd2fdd13", - "sha256:bb6ad4489af1bac6955d38ebcb95079a836af31e4c4f74aba1ca05bb9f6027bd", - "sha256:bedf309630209e78582ffacda64a21f96f3ed2e51fbf3962d4d488e503420254", - "sha256:c1ba1afb396148bbc70e9eaa8c06c1716fdddabaf86e7027c5988bae2a829ab6", - "sha256:c33602f93bfb67779f9c507e4d69451664524389546bacfe1bee13cae6dc7488", - "sha256:c4aac8e7103bf598373208f6299fa9a5cfd1fc571f2d40bf1dd1955a63d6eeb5", - "sha256:c6f981882aea41e021f72779ce2a4e87267458cc4d39ea990729e21ef18f0f8c", - "sha256:cc78cc83110d2f275ec1970e7a831f4e371ee92405332ebfe9860a715f8336e1", - "sha256:d49f3db871575e0426b12e2f32fdb25e579dea16486a26e5a0474af87cb1ab0a", - "sha256:dd3f9a40c16daf323cf913593083698caee97df2804aa36c4b3175d5ac1b92a2", - "sha256:e0bedafe4bc165ad0a56ac0bd7695df25c50f76961da29c050712596cf092d6d", - "sha256:e9069e1b01525a96e6ff49e25876d90d5a563bc31c658289a8772ae186552236" + "sha256:b3ef57c62535b0941697cce638c08900d87fcb67e29cfa99e8a68f747f393f7a", + "sha256:d0caf5954bee831b6bfe7e338c32b9e30c85dfe080c843680783ac2b631673b4" + ], + "markers": "python_version >= '3.7'", + "version": "==2.5.3" + }, + "pydantic-core": { + "hashes": [ + "sha256:00646784f6cd993b1e1c0e7b0fdcbccc375d539db95555477771c27555e3c556", + "sha256:00b1087dabcee0b0ffd104f9f53d7d3eaddfaa314cdd6726143af6bc713aa27e", + "sha256:0348b1dc6b76041516e8a854ff95b21c55f5a411c3297d2ca52f5528e49d8411", + "sha256:036137b5ad0cb0004c75b579445a1efccd072387a36c7f217bb8efd1afbe5245", + "sha256:095b707bb287bfd534044166ab767bec70a9bba3175dcdc3371782175c14e43c", + "sha256:0c08de15d50fa190d577e8591f0329a643eeaed696d7771760295998aca6bc66", + "sha256:1302a54f87b5cd8528e4d6d1bf2133b6aa7c6122ff8e9dc5220fbc1e07bffebd", + "sha256:172de779e2a153d36ee690dbc49c6db568d7b33b18dc56b69a7514aecbcf380d", + "sha256:1b027c86c66b8627eb90e57aee1f526df77dc6d8b354ec498be9a757d513b92b", + "sha256:1ce830e480f6774608dedfd4a90c42aac4a7af0a711f1b52f807130c2e434c06", + "sha256:1fd0c1d395372843fba13a51c28e3bb9d59bd7aebfeb17358ffaaa1e4dbbe948", + "sha256:23598acb8ccaa3d1d875ef3b35cb6376535095e9405d91a3d57a8c7db5d29341", + "sha256:24368e31be2c88bd69340fbfe741b405302993242ccb476c5c3ff48aeee1afe0", + "sha256:26a92ae76f75d1915806b77cf459811e772d8f71fd1e4339c99750f0e7f6324f", + "sha256:27e524624eace5c59af499cd97dc18bb201dc6a7a2da24bfc66ef151c69a5f2a", + "sha256:2b8719037e570639e6b665a4050add43134d80b687288ba3ade18b22bbb29dd2", + "sha256:2c5bcf3414367e29f83fd66f7de64509a8fd2368b1edf4351e862910727d3e51", + "sha256:2dbe357bc4ddda078f79d2a36fc1dd0494a7f2fad83a0a684465b6f24b46fe80", + "sha256:2f5fa187bde8524b1e37ba894db13aadd64faa884657473b03a019f625cee9a8", + "sha256:2f6ffc6701a0eb28648c845f4945a194dc7ab3c651f535b81793251e1185ac3d", + "sha256:314ccc4264ce7d854941231cf71b592e30d8d368a71e50197c905874feacc8a8", + "sha256:36026d8f99c58d7044413e1b819a67ca0e0b8ebe0f25e775e6c3d1fabb3c38fb", + "sha256:36099c69f6b14fc2c49d7996cbf4f87ec4f0e66d1c74aa05228583225a07b590", + "sha256:36fa402dcdc8ea7f1b0ddcf0df4254cc6b2e08f8cd80e7010d4c4ae6e86b2a87", + "sha256:370ffecb5316ed23b667d99ce4debe53ea664b99cc37bfa2af47bc769056d534", + "sha256:3860c62057acd95cc84044e758e47b18dcd8871a328ebc8ccdefd18b0d26a21b", + "sha256:399ac0891c284fa8eb998bcfa323f2234858f5d2efca3950ae58c8f88830f145", + "sha256:3a0b5db001b98e1c649dd55afa928e75aa4087e587b9524a4992316fa23c9fba", + "sha256:3dcf1978be02153c6a31692d4fbcc2a3f1db9da36039ead23173bc256ee3b91b", + "sha256:4241204e4b36ab5ae466ecec5c4c16527a054c69f99bba20f6f75232a6a534e2", + "sha256:438027a975cc213a47c5d70672e0d29776082155cfae540c4e225716586be75e", + "sha256:43e166ad47ba900f2542a80d83f9fc65fe99eb63ceec4debec160ae729824052", + "sha256:478e9e7b360dfec451daafe286998d4a1eeaecf6d69c427b834ae771cad4b622", + "sha256:4ce8299b481bcb68e5c82002b96e411796b844d72b3e92a3fbedfe8e19813eab", + "sha256:4f86f1f318e56f5cbb282fe61eb84767aee743ebe32c7c0834690ebea50c0a6b", + "sha256:55a23dcd98c858c0db44fc5c04fc7ed81c4b4d33c653a7c45ddaebf6563a2f66", + "sha256:599c87d79cab2a6a2a9df4aefe0455e61e7d2aeede2f8577c1b7c0aec643ee8e", + "sha256:5aa90562bc079c6c290f0512b21768967f9968e4cfea84ea4ff5af5d917016e4", + "sha256:64634ccf9d671c6be242a664a33c4acf12882670b09b3f163cd00a24cffbd74e", + "sha256:667aa2eac9cd0700af1ddb38b7b1ef246d8cf94c85637cbb03d7757ca4c3fdec", + "sha256:6a31d98c0d69776c2576dda4b77b8e0c69ad08e8b539c25c7d0ca0dc19a50d6c", + "sha256:6af4b3f52cc65f8a0bc8b1cd9676f8c21ef3e9132f21fed250f6958bd7223bed", + "sha256:6c8edaea3089bf908dd27da8f5d9e395c5b4dc092dbcce9b65e7156099b4b937", + "sha256:71d72ca5eaaa8d38c8df16b7deb1a2da4f650c41b58bb142f3fb75d5ad4a611f", + "sha256:72f9a942d739f09cd42fffe5dc759928217649f070056f03c70df14f5770acf9", + "sha256:747265448cb57a9f37572a488a57d873fd96bf51e5bb7edb52cfb37124516da4", + "sha256:75ec284328b60a4e91010c1acade0c30584f28a1f345bc8f72fe8b9e46ec6a96", + "sha256:78d0768ee59baa3de0f4adac9e3748b4b1fffc52143caebddfd5ea2961595277", + "sha256:78ee52ecc088c61cce32b2d30a826f929e1708f7b9247dc3b921aec367dc1b23", + "sha256:7be719e4d2ae6c314f72844ba9d69e38dff342bc360379f7c8537c48e23034b7", + "sha256:7e1f4744eea1501404b20b0ac059ff7e3f96a97d3e3f48ce27a139e053bb370b", + "sha256:7e90d6cc4aad2cc1f5e16ed56e46cebf4877c62403a311af20459c15da76fd91", + "sha256:7ebe3416785f65c28f4f9441e916bfc8a54179c8dea73c23023f7086fa601c5d", + "sha256:7f41533d7e3cf9520065f610b41ac1c76bc2161415955fbcead4981b22c7611e", + "sha256:7f5025db12fc6de7bc1104d826d5aee1d172f9ba6ca936bf6474c2148ac336c1", + "sha256:86c963186ca5e50d5c8287b1d1c9d3f8f024cbe343d048c5bd282aec2d8641f2", + "sha256:86ce5fcfc3accf3a07a729779d0b86c5d0309a4764c897d86c11089be61da160", + "sha256:8a14c192c1d724c3acbfb3f10a958c55a2638391319ce8078cb36c02283959b9", + "sha256:8b93785eadaef932e4fe9c6e12ba67beb1b3f1e5495631419c784ab87e975670", + "sha256:8ed1af8692bd8d2a29d702f1a2e6065416d76897d726e45a1775b1444f5928a7", + "sha256:92879bce89f91f4b2416eba4429c7b5ca22c45ef4a499c39f0c5c69257522c7c", + "sha256:94fc0e6621e07d1e91c44e016cc0b189b48db053061cc22d6298a611de8071bb", + "sha256:982487f8931067a32e72d40ab6b47b1628a9c5d344be7f1a4e668fb462d2da42", + "sha256:9862bf828112e19685b76ca499b379338fd4c5c269d897e218b2ae8fcb80139d", + "sha256:99b14dbea2fdb563d8b5a57c9badfcd72083f6006caf8e126b491519c7d64ca8", + "sha256:9c6a5c79b28003543db3ba67d1df336f253a87d3112dac3a51b94f7d48e4c0e1", + "sha256:a19b794f8fe6569472ff77602437ec4430f9b2b9ec7a1105cfd2232f9ba355e6", + "sha256:a306cdd2ad3a7d795d8e617a58c3a2ed0f76c8496fb7621b6cd514eb1532cae8", + "sha256:a3dde6cac75e0b0902778978d3b1646ca9f438654395a362cb21d9ad34b24acf", + "sha256:a874f21f87c485310944b2b2734cd6d318765bcbb7515eead33af9641816506e", + "sha256:a983cca5ed1dd9a35e9e42ebf9f278d344603bfcb174ff99a5815f953925140a", + "sha256:aca48506a9c20f68ee61c87f2008f81f8ee99f8d7f0104bff3c47e2d148f89d9", + "sha256:b2602177668f89b38b9f84b7b3435d0a72511ddef45dc14446811759b82235a1", + "sha256:b3e5fe4538001bb82e2295b8d2a39356a84694c97cb73a566dc36328b9f83b40", + "sha256:b6ca36c12a5120bad343eef193cc0122928c5c7466121da7c20f41160ba00ba2", + "sha256:b89f4477d915ea43b4ceea6756f63f0288941b6443a2b28c69004fe07fde0d0d", + "sha256:b9a9d92f10772d2a181b5ca339dee066ab7d1c9a34ae2421b2a52556e719756f", + "sha256:c99462ffc538717b3e60151dfaf91125f637e801f5ab008f81c402f1dff0cd0f", + "sha256:cb92f9061657287eded380d7dc455bbf115430b3aa4741bdc662d02977e7d0af", + "sha256:cdee837710ef6b56ebd20245b83799fce40b265b3b406e51e8ccc5b85b9099b7", + "sha256:cf10b7d58ae4a1f07fccbf4a0a956d705356fea05fb4c70608bb6fa81d103cda", + "sha256:d15687d7d7f40333bd8266f3814c591c2e2cd263fa2116e314f60d82086e353a", + "sha256:d5c28525c19f5bb1e09511669bb57353d22b94cf8b65f3a8d141c389a55dec95", + "sha256:d5f916acf8afbcab6bacbb376ba7dc61f845367901ecd5e328fc4d4aef2fcab0", + "sha256:dab03ed811ed1c71d700ed08bde8431cf429bbe59e423394f0f4055f1ca0ea60", + "sha256:db453f2da3f59a348f514cfbfeb042393b68720787bbef2b4c6068ea362c8149", + "sha256:de2a0645a923ba57c5527497daf8ec5df69c6eadf869e9cd46e86349146e5975", + "sha256:dea7fcd62915fb150cdc373212141a30037e11b761fbced340e9db3379b892d4", + "sha256:dfcbebdb3c4b6f739a91769aea5ed615023f3c88cb70df812849aef634c25fbe", + "sha256:dfcebb950aa7e667ec226a442722134539e77c575f6cfaa423f24371bb8d2e94", + "sha256:e0641b506486f0b4cd1500a2a65740243e8670a2549bb02bc4556a83af84ae03", + "sha256:e33b0834f1cf779aa839975f9d8755a7c2420510c0fa1e9fa0497de77cd35d2c", + "sha256:e4ace1e220b078c8e48e82c081e35002038657e4b37d403ce940fa679e57113b", + "sha256:e4cf2d5829f6963a5483ec01578ee76d329eb5caf330ecd05b3edd697e7d768a", + "sha256:e574de99d735b3fc8364cba9912c2bec2da78775eba95cbb225ef7dda6acea24", + "sha256:e646c0e282e960345314f42f2cea5e0b5f56938c093541ea6dbf11aec2862391", + "sha256:e8a5ac97ea521d7bde7621d86c30e86b798cdecd985723c4ed737a2aa9e77d0c", + "sha256:eedf97be7bc3dbc8addcef4142f4b4164066df0c6f36397ae4aaed3eb187d8ab", + "sha256:ef633add81832f4b56d3b4c9408b43d530dfca29e68fb1b797dcb861a2c734cd", + "sha256:f27207e8ca3e5e021e2402ba942e5b4c629718e665c81b8b306f3c8b1ddbb786", + "sha256:f85f3843bdb1fe80e8c206fe6eed7a1caeae897e496542cee499c374a85c6e08", + "sha256:f8e81e4b55930e5ffab4a68db1af431629cf2e4066dbdbfef65348b8ab804ea8", + "sha256:f96ae96a060a8072ceff4cfde89d261837b4294a4f28b84a28765470d502ccc6", + "sha256:fd9e98b408384989ea4ab60206b8e100d8687da18b5c813c11e92fd8212a98e0", + "sha256:ffff855100bc066ff2cd3aa4a60bc9534661816b110f0243e59503ec2df38421" ], "markers": "python_version >= '3.7'", - "version": "==1.10.2" + "version": "==2.14.6" }, "sniffio": { "hashes": [ @@ -116,152 +194,239 @@ }, "starlette": { "hashes": [ - "sha256:42fcf3122f998fefce3e2c5ad7e5edbf0f02cf685d646a83a08d404726af5084", - "sha256:c0414d5a56297d37f3db96a84034d61ce29889b9eaccf65eb98a0b39441fcaa3" + "sha256:3e2639dac3520e4f58734ed22553f950d3f3cb1001cd2eaac4d57e8cdc5f66bc", + "sha256:50bbbda9baa098e361f398fda0928062abbaf1f54f4fadcbe17c092a01eb9a25" ], - "markers": "python_version >= '3.7'", - "version": "==0.20.4" + "markers": "python_version >= '3.8'", + "version": "==0.35.1" }, "typing-extensions": { "hashes": [ - "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa", - "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e" + "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783", + "sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd" ], - "markers": "python_version < '3.10'", - "version": "==4.4.0" + "markers": "python_version >= '3.8'", + "version": "==4.9.0" }, "uvicorn": { "hashes": [ - "sha256:0abd429ebb41e604ed8d2be6c60530de3408f250e8d2d84967d85ba9e86fe3af", - "sha256:9a66e7c42a2a95222f76ec24a4b754c158261c4696e683b9dadc72b590e0311b" + "sha256:48bfd350fce3c5c57af5fb4995fded8fb50da3b4feb543eb18ad7e0d54589602", + "sha256:cdb58ef6b8188c6c174994b2b1ba2150a9a8ae7ea5fb2f1b856b94a815d6071d" ], "index": "pypi", - "version": "==0.18.3" + "markers": "python_version >= '3.8'", + "version": "==0.26.0" } }, "develop": { - "appdirs": { - "hashes": [ - "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41", - "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128" - ], - "version": "==1.4.4" - }, - "atomicwrites": { - "hashes": [ - "sha256:81b2c9071a49367a7f770170e5eec8cb66567cfbbc8c73d20ce5ca4a8d71cf11" - ], - "markers": "sys_platform == 'win32'", - "version": "==1.4.1" - }, - "attrs": { + "anyio": { "hashes": [ - "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6", - "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c" + "sha256:745843b39e829e108e518c489b31dc757de7d2131d53fac32bd8df268227bfee", + "sha256:e1875bb4b4e2de1669f4bc7869b6d3f54231cdced71605e6e64c9be77e3be50f" ], - "markers": "python_version >= '3.5'", - "version": "==22.1.0" + "markers": "python_version >= '3.8'", + "version": "==4.2.0" }, "certifi": { "hashes": [ - "sha256:0d9c601124e5a6ba9712dbc60d9c53c21e34f5f641fe83002317394311bdce14", - "sha256:90c1a32f1d68f940488354e36370f6cca89f0f106db09518524c88d6ed83f382" + "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1", + "sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474" ], "markers": "python_version >= '3.6'", - "version": "==2022.9.24" + "version": "==2023.11.17" }, "cfgv": { "hashes": [ - "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426", - "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736" + "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9", + "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560" ], - "markers": "python_full_version >= '3.6.1'", - "version": "==3.3.1" + "markers": "python_version >= '3.8'", + "version": "==3.4.0" + }, + "charset-normalizer": { + "hashes": [ + "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027", + "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087", + "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786", + "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8", + "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09", + "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185", + "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574", + "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e", + "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519", + "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898", + "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269", + "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3", + "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f", + "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6", + "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8", + "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a", + "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73", + "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc", + "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714", + "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2", + "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc", + "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce", + "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d", + "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e", + "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6", + "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269", + "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96", + "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d", + "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a", + "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4", + "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77", + "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d", + "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0", + "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed", + "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068", + "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac", + "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25", + "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8", + "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab", + "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26", + "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2", + "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db", + "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f", + "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5", + "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99", + "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c", + "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d", + "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811", + "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa", + "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a", + "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03", + "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b", + "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04", + "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c", + "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001", + "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458", + "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389", + "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99", + "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985", + "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537", + "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238", + "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f", + "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d", + "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796", + "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a", + "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143", + "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8", + "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c", + "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5", + "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5", + "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711", + "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4", + "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6", + "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c", + "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7", + "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4", + "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b", + "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae", + "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12", + "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c", + "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae", + "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8", + "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887", + "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b", + "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4", + "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f", + "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5", + "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33", + "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519", + "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561" + ], + "markers": "python_full_version >= '3.7.0'", + "version": "==3.3.2" }, - "chardet": { + "distlib": { "hashes": [ - "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", - "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" + "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784", + "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64" ], - "version": "==3.0.4" + "version": "==0.3.8" }, - "charset-normalizer": { + "filelock": { "hashes": [ - "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845", - "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f" + "sha256:521f5f56c50f8426f5e03ad3b281b490a87ef15bc6c526f168290f0c7148d44e", + "sha256:57dbda9b35157b05fb3e58ee91448612eb674172fab98ee235ccb0b5bee19a1c" ], - "markers": "python_full_version >= '3.6.0'", - "version": "==2.1.1" + "markers": "python_version >= '3.8'", + "version": "==3.13.1" }, - "colorama": { + "flake8": { "hashes": [ - "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da", - "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4" + "sha256:33f96621059e65eec474169085dc92bf26e7b2d47366b70be2f67ab80dc25132", + "sha256:a6dfbb75e03252917f2473ea9653f7cd799c3064e54d4c8140044c5c065f53c3" ], - "markers": "platform_system == 'Windows'", - "version": "==0.4.5" + "index": "pypi", + "markers": "python_full_version >= '3.8.1'", + "version": "==7.0.0" }, - "distlib": { + "gitdb": { "hashes": [ - "sha256:14bad2d9b04d3a36127ac97f30b12a19268f211063d8f8ee4f47108896e11b46", - "sha256:f35c4b692542ca110de7ef0bea44d73981caeb34ca0b9b6b2e6d7790dda8f80e" + "sha256:81a3407ddd2ee8df444cbacea00e2d038e40150acfa3001696fe0dcf1d3adfa4", + "sha256:bf5421126136d6d0af55bc1e7c1af1c397a34f5b7bd79e776cd3e89785c2b04b" ], - "version": "==0.3.6" + "markers": "python_version >= '3.7'", + "version": "==4.0.11" }, - "filelock": { + "gitpython": { "hashes": [ - "sha256:55447caa666f2198c5b6b13a26d2084d26fa5b115c00d065664b2124680c4edc", - "sha256:617eb4e5eedc82fc5f47b6d61e4d11cb837c56cb4544e39081099fa17ad109d4" + "sha256:c36b6634d069b3f719610175020a9aed919421c87552185b085e04fbbdb10b7c", + "sha256:ed66e624884f76df22c8e16066d567aaa5a37d5b5fa19db2c6df6f7156db9048" ], "markers": "python_version >= '3.7'", - "version": "==3.8.0" + "version": "==3.1.41" }, - "flake8": { + "h11": { "hashes": [ - "sha256:6fbe320aad8d6b95cec8b8e47bc933004678dc63095be98528b7bdd2a9f510db", - "sha256:7a1cf6b73744f5806ab95e526f6f0d8c01c66d7bbe349562d22dfca20610b248" + "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d", + "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761" ], - "index": "pypi", - "version": "==5.0.4" + "markers": "python_version >= '3.7'", + "version": "==0.14.0" }, - "gitdb": { + "httpcore": { "hashes": [ - "sha256:8033ad4e853066ba6ca92050b9df2f89301b8fc8bf7e9324d412a63f8bf1a8fd", - "sha256:bac2fd45c0a1c9cf619e63a90d62bdc63892ef92387424b855792a6cabe789aa" + "sha256:096cc05bca73b8e459a1fc3dcf585148f63e534eae4339559c9b8a8d6399acc7", + "sha256:9fc092e4799b26174648e54b74ed5f683132a464e95643b226e00c2ed2fa6535" ], - "markers": "python_version >= '3.6'", - "version": "==4.0.9" + "markers": "python_version >= '3.8'", + "version": "==1.0.2" }, - "gitpython": { + "httpx": { "hashes": [ - "sha256:138016d519bf4dd55b22c682c904ed2fd0235c3612b2f8f65ce218ff358deed8", - "sha256:a03f728b49ce9597a6655793207c6ab0da55519368ff5961e4a74ae475b9fa8e" + "sha256:451b55c30d5185ea6b23c2c793abf9bb237d2a7dfb901ced6ff69ad37ec1dfaf", + "sha256:8915f5a3627c4d47b73e8202457cb28f1266982d1159bd5779d86a80c0eab1cd" ], "index": "pypi", - "version": "==3.1.9" + "markers": "python_version >= '3.8'", + "version": "==0.26.0" }, "identify": { "hashes": [ - "sha256:6c32dbd747aa4ceee1df33f25fed0b0f6e0d65721b15bd151307ff7056d50245", - "sha256:b276db7ec52d7e89f5bc4653380e33054ddc803d25875952ad90b0f012cbcdaa" + "sha256:161558f9fe4559e1557e1bff323e8631f6a0e4837f7497767c1782832f16b62d", + "sha256:d40ce5fcd762817627670da8a7d8d8e65f24342d14539c59488dc603bf662e34" ], - "markers": "python_version >= '3.7'", - "version": "==2.5.6" + "markers": "python_version >= '3.8'", + "version": "==2.5.33" }, "idna": { "hashes": [ - "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4", - "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2" + "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca", + "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f" ], "markers": "python_version >= '3.5'", - "version": "==3.4" + "version": "==3.6" }, "iniconfig": { "hashes": [ - "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3", - "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32" + "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", + "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374" ], - "version": "==1.1.1" + "markers": "python_version >= '3.7'", + "version": "==2.0.0" }, "mccabe": { "hashes": [ @@ -273,192 +438,175 @@ }, "nodeenv": { "hashes": [ - "sha256:27083a7b96a25f2f5e1d8cb4b6317ee8aeda3bdd121394e5ac54e498028a042e", - "sha256:e0e7f7dfb85fc5394c6fe1e8fa98131a2473e04311a45afb6508f7cf1836fa2b" + "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2", + "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'", - "version": "==1.7.0" + "version": "==1.8.0" }, "packaging": { "hashes": [ - "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb", - "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522" + "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5", + "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7" ], - "markers": "python_version >= '3.6'", - "version": "==21.3" + "markers": "python_version >= '3.7'", + "version": "==23.2" }, "platformdirs": { "hashes": [ - "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788", - "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19" + "sha256:11c8f37bcca40db96d8144522d925583bdb7a31f7b0e37e3ed4318400a8e2380", + "sha256:906d548203468492d432bcb294d4bc2fff751bf84971fbb2c10918cc206ee420" ], - "markers": "python_version >= '3.7'", - "version": "==2.5.2" + "markers": "python_version >= '3.8'", + "version": "==4.1.0" }, "pluggy": { "hashes": [ - "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159", - "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3" + "sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12", + "sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7" ], - "markers": "python_version >= '3.6'", - "version": "==1.0.0" + "markers": "python_version >= '3.8'", + "version": "==1.3.0" }, "pre-commit": { "hashes": [ - "sha256:51a5ba7c480ae8072ecdb6933df22d2f812dc897d5fe848778116129a681aac7", - "sha256:a978dac7bc9ec0bcee55c18a277d553b0f419d259dadb4b9418ff2d00eb43959" + "sha256:c255039ef399049a5544b6ce13d135caba8f2c28c3b4033277a788f434308376", + "sha256:d30bad9abf165f7785c15a21a1f46da7d0677cb00ee7ff4c579fd38922efe15d" ], "index": "pypi", - "version": "==2.20.0" - }, - "py": { - "hashes": [ - "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719", - "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==1.11.0" + "markers": "python_version >= '3.9'", + "version": "==3.6.0" }, "pycodestyle": { "hashes": [ - "sha256:2c9607871d58c76354b697b42f5d57e1ada7d261c261efac224b664affdc5785", - "sha256:d1735fc58b418fd7c5f658d28d943854f8a849b01a5d0a1e6f3f3fdd0166804b" + "sha256:41ba0e7afc9752dfb53ced5489e89f8186be00e599e712660695b7a75ff2663f", + "sha256:44fe31000b2d866f2e41841b18528a505fbd7fef9017b04eff4e2648a0fadc67" ], - "markers": "python_version >= '3.6'", - "version": "==2.9.1" + "markers": "python_version >= '3.8'", + "version": "==2.11.1" }, "pyflakes": { "hashes": [ - "sha256:4579f67d887f804e67edb544428f264b7b24f435b263c4614f384135cea553d2", - "sha256:491feb020dca48ccc562a8c0cbe8df07ee13078df59813b83959cbdada312ea3" - ], - "markers": "python_version >= '3.6'", - "version": "==2.5.0" - }, - "pyparsing": { - "hashes": [ - "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb", - "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc" + "sha256:1c61603ff154621fb2a9172037d84dca3500def8c8b630657d1701f026f8af3f", + "sha256:84b5be138a2dfbb40689ca07e2152deb896a65c3a3e24c251c5c62489568074a" ], - "markers": "python_full_version >= '3.6.8'", - "version": "==3.0.9" + "markers": "python_version >= '3.8'", + "version": "==3.2.0" }, "pytest": { "hashes": [ - "sha256:1377bda3466d70b55e3f5cecfa55bb7cfcf219c7964629b967c37cf0bda818b7", - "sha256:4f365fec2dff9c1162f834d9f18af1ba13062db0c708bf7b946f8a5c76180c39" + "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280", + "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8" ], "index": "pypi", - "version": "==7.1.3" + "markers": "python_version >= '3.7'", + "version": "==7.4.4" }, "pyyaml": { "hashes": [ - "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf", - "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293", - "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b", - "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57", - "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b", - "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4", - "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07", - "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba", - "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9", - "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287", - "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513", - "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0", - "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782", - "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0", - "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92", - "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f", - "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2", - "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc", - "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1", - "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c", - "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86", - "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4", - "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c", - "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34", - "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b", - "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d", - "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c", - "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb", - "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7", - "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737", - "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3", - "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d", - "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358", - "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53", - "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78", - "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803", - "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a", - "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f", - "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174", - "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5" + "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5", + "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc", + "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df", + "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741", + "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206", + "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27", + "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595", + "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62", + "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98", + "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696", + "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290", + "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9", + "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d", + "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6", + "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867", + "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47", + "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486", + "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6", + "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3", + "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007", + "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938", + "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0", + "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c", + "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735", + "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d", + "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28", + "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4", + "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba", + "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8", + "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef", + "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5", + "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd", + "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3", + "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0", + "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515", + "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c", + "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c", + "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924", + "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34", + "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43", + "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859", + "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673", + "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54", + "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a", + "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b", + "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab", + "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa", + "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c", + "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585", + "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d", + "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f" ], "markers": "python_version >= '3.6'", - "version": "==6.0" + "version": "==6.0.1" }, "requests": { "hashes": [ - "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983", - "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349" + "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f", + "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1" ], "index": "pypi", - "version": "==2.28.1" - }, - "setuptools": { - "hashes": [ - "sha256:512e5536220e38146176efb833d4a62aa726b7bbff82cfbc8ba9eaa3996e0b17", - "sha256:f62ea9da9ed6289bfe868cd6845968a2c854d1427f8548d52cae02a42b4f0356" - ], "markers": "python_version >= '3.7'", - "version": "==65.5.0" + "version": "==2.31.0" }, - "six": { + "setuptools": { "hashes": [ - "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259", - "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced" + "sha256:385eb4edd9c9d5c17540511303e39a147ce2fc04bc55289c322b9e5904fe2c05", + "sha256:be1af57fc409f93647f2e8e4573a142ed38724b8cdd389706a867bb4efcf1e78" ], - "version": "==1.15.0" + "markers": "python_version >= '3.8'", + "version": "==69.0.3" }, "smmap": { "hashes": [ - "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94", - "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936" - ], - "markers": "python_version >= '3.6'", - "version": "==5.0.0" - }, - "toml": { - "hashes": [ - "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", - "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f" + "sha256:dceeb6c0028fdb6734471eb07c0cd2aae706ccaecab45965ee83f11c8d3b1f62", + "sha256:e6d8668fa5f93e706934a62d7b4db19c8d9eb8cf2adbb75ef1b675aa332b69da" ], - "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==0.10.2" + "markers": "python_version >= '3.7'", + "version": "==5.0.1" }, - "tomli": { + "sniffio": { "hashes": [ - "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", - "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f" + "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101", + "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384" ], "markers": "python_version >= '3.7'", - "version": "==2.0.1" + "version": "==1.3.0" }, "urllib3": { "hashes": [ - "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e", - "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997" + "sha256:55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3", + "sha256:df7aa8afb0148fa78488e7899b2c59b5f4ffcfa82e6c54ccb9dd37c1d7b52d54" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5' and python_version < '4'", - "version": "==1.26.12" + "markers": "python_version >= '3.8'", + "version": "==2.1.0" }, "virtualenv": { "hashes": [ - "sha256:227ea1b9994fdc5ea31977ba3383ef296d7472ea85be9d6732e42a91c04e80da", - "sha256:d07dfc5df5e4e0dbc92862350ad87a36ed505b978f6c39609dc489eadd5b0d27" + "sha256:4238949c5ffe6876362d9c0180fc6c3a824a7b12b80604eeb8085f2ed7460de3", + "sha256:bf51c0d9c7dd63ea8e44086fa1e4fb1093a31e963b86959257378aef020e1f1b" ], - "markers": "python_version >= '3.6'", - "version": "==20.16.5" + "markers": "python_version >= '3.7'", + "version": "==20.25.0" } } } From e652869dd426bd85a04bbbdd463901d08abbf7f0 Mon Sep 17 00:00:00 2001 From: Bouni Date: Fri, 19 Jan 2024 10:10:10 +0100 Subject: [PATCH 02/13] fix deprectaed method names --- tests/test_utils.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/test_utils.py b/tests/test_utils.py index 03812c6..4fe546a 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -12,8 +12,10 @@ def load_json(json_path: Path): def generate_testjob(): - return Job.parse_raw(load_json(Path("./tests/res/in/testjob.json"))) + return Job.model_validate_json(load_json(Path("./tests/res/in/testjob.json"))) def generate_testresult(): - return Result.parse_raw(load_json(Path("./tests/res/out/testresult.json"))) + return Result.model_validate_json( + load_json(Path("./tests/res/out/testresult.json")) + ) From 0f9c60c589c63ff72bd40e8f66cdca9a72edff4e Mon Sep 17 00:00:00 2001 From: Bouni Date: Fri, 19 Jan 2024 10:11:21 +0100 Subject: [PATCH 03/13] Update test fixtures --- tests/res/in/testjob.json | 16 +++++++++--- tests/res/out/testresult.json | 48 +++++++++++++++++++++++++++-------- 2 files changed, 49 insertions(+), 15 deletions(-) diff --git a/tests/res/in/testjob.json b/tests/res/in/testjob.json index 6f8d4f6..98189c9 100644 --- a/tests/res/in/testjob.json +++ b/tests/res/in/testjob.json @@ -1,8 +1,16 @@ { "cut_width": 2, "max_length": 1500, - "target_sizes": { - "500": 2, - "200": 4 - } + "target_sizes": [ + { + "length": 500, + "quantity": 2, + "name": "Part1" + }, + { + "length": 200, + "quantity": 4, + "name": "Part2" + } + ] } diff --git a/tests/res/out/testresult.json b/tests/res/out/testresult.json index 08fcd37..4e06f1c 100644 --- a/tests/res/out/testresult.json +++ b/tests/res/out/testresult.json @@ -1,24 +1,50 @@ { "job": { - "max_length": 1500, "cut_width": 2, - "target_sizes": { - "500": 2, - "200": 4 - } + "max_length": 1500, + "target_sizes": [ + { + "length": 500, + "quantity": 2, + "name": "Part1" + }, + { + "length": 200, + "quantity": 4, + "name": "Part2" + } + ] }, "solver_type": "bruteforce", "time_us": 10000, "lengths": [ [ - 500, - 500, - 200, - 200 + [ + 500, + "Part1" + ], + [ + 500, + "Part1" + ], + [ + 200, + "Part2" + ], + [ + 200, + "Part2" + ] ], [ - 200, - 200 + [ + 200, + "Part2" + ], + [ + 200, + "Part2" + ] ] ] } From e594ac1138778f70ebb419680c3195ccf9769e6b Mon Sep 17 00:00:00 2001 From: Bouni Date: Fri, 19 Jan 2024 10:17:34 +0100 Subject: [PATCH 04/13] Refactor Job to take a length and a name as input --- app/solver/data/Job.py | 60 ++++++++++++++++++++--------------- tests/solver/data/test_Job.py | 14 ++++++-- 2 files changed, 46 insertions(+), 28 deletions(-) diff --git a/app/solver/data/Job.py b/app/solver/data/Job.py index 8a808c3..3dfe5d8 100644 --- a/app/solver/data/Job.py +++ b/app/solver/data/Job.py @@ -1,4 +1,4 @@ -from typing import Iterator, Dict, List +from typing import Iterator, List, Optional, Tuple from pydantic import BaseModel @@ -6,6 +6,7 @@ class TargetSize(BaseModel): length: int quantity: int + name: Optional[str] = "" def __lt__(self, other): """ @@ -20,38 +21,40 @@ def __str__(self): class Job(BaseModel): max_length: int cut_width: int = 0 - target_sizes: Dict[int, int] + target_sizes: List[TargetSize] # utility - def iterate_sizes(self) -> Iterator[int]: + def iterate_sizes(self) -> Iterator[Tuple[int, str | None]]: """ yields all lengths, sorted descending """ # sort descending to favor combining larger sizes first - for size, quantity in sorted(self.target_sizes.items(), reverse=True): - for _ in range(quantity): - yield size + for target in sorted(self.target_sizes, key=lambda x: x.length, reverse=True): + for _ in range(target.quantity): + yield (target.length, target.name) + # NOTE: Not used, so not really refactored at the moment def sizes_from_list(self, sizes_list: List[TargetSize]): - known_sizes = {} - - # list to dict to make them unique - for size in sizes_list: - if size.length in known_sizes: - known_sizes[size.length] += size.quantity - else: - known_sizes[size.length] = size.quantity - - self.target_sizes = known_sizes - + # known_sizes = {} + # + # # list to dict to make them unique + # for size in sizes_list: + # if size.length in known_sizes: + # known_sizes[size.length] += size.quantity + # else: + # known_sizes[size.length] = size.quantity + + self.target_sizes = sizes_list + + # NOTE: Can eventually be removed as it does nothing anymore def sizes_as_list(self) -> List[TargetSize]: """ Compatibility function """ # back to list again for compatibility - return [TargetSize(length=l, quantity=q) for (l, q) in self.target_sizes.items()] + return self.target_sizes def assert_valid(self): if self.max_length <= 0: @@ -59,20 +62,25 @@ def assert_valid(self): if self.cut_width < 0: raise ValueError(f"Job has invalid cut_width {self.cut_width}") if len(self.target_sizes) <= 0: - raise ValueError(f"Job is missing target_sizes") - if any(size > (self.max_length - self.cut_width) for size in self.target_sizes.keys()): - raise ValueError(f"Job has target sizes longer than the stock") + raise ValueError("Job is missing target_sizes") + if any( + target.length > (self.max_length - self.cut_width) + for target in self.target_sizes + ): + raise ValueError("Job has target sizes longer than the stock") def __len__(self) -> int: """ Number of target sizes in job """ - return sum(self.target_sizes.values()) + return sum([target.quantity for target in self.target_sizes]) def __eq__(self, other): - return self.max_length == other.max_length and \ - self.cut_width == other.cut_width and \ - self.target_sizes == other.target_sizes + return ( + self.max_length == other.max_length + and self.cut_width == other.cut_width + and self.target_sizes == other.target_sizes + ) def __hash__(self) -> int: - return hash((self.max_length, self.cut_width, str(sorted(self.target_sizes.items())))) + return hash((self.max_length, self.cut_width, str(sorted(self.target_sizes)))) diff --git a/tests/solver/data/test_Job.py b/tests/solver/data/test_Job.py index edf2299..9d7dae1 100644 --- a/tests/solver/data/test_Job.py +++ b/tests/solver/data/test_Job.py @@ -1,6 +1,7 @@ import pytest from app.solver.data.Job import Job +from app.solver.data.Job import TargetSize from tests.test_utils import generate_testjob @@ -11,7 +12,14 @@ def test_iterator(): for length in job.iterate_sizes(): resulting_list.append(length) - assert resulting_list == [500, 500, 200, 200, 200, 200] + assert resulting_list == [ + (500, "Part1"), + (500, "Part1"), + (200, "Part2"), + (200, "Part2"), + (200, "Part2"), + (200, "Part2"), + ] def test_job_equal(): @@ -48,6 +56,8 @@ def test_invalid(): def test_too_long(): job = generate_testjob() - job.target_sizes[job.max_length + 1] = 4 + job.target_sizes.append( + TargetSize(**{"length": job.max_length + 1, "quantity": 4, "name": "too long"}) + ) with pytest.raises(ValueError): job.assert_valid() From caf4d1f994bf25b7ceed6a720f29d449f01b625e Mon Sep 17 00:00:00 2001 From: Bouni Date: Fri, 19 Jan 2024 10:18:34 +0100 Subject: [PATCH 05/13] Refactor Result to output langth and name --- app/solver/data/Result.py | 18 ++-- tests/solver/data/test_Result.py | 144 +++++++++++++++++++++++++++++-- 2 files changed, 145 insertions(+), 17 deletions(-) diff --git a/app/solver/data/Result.py b/app/solver/data/Result.py index bad58ab..e8c5f1d 100644 --- a/app/solver/data/Result.py +++ b/app/solver/data/Result.py @@ -1,5 +1,5 @@ from enum import unique, Enum -from typing import List +from typing import List, Tuple from pydantic import BaseModel @@ -18,23 +18,23 @@ class Result(BaseModel): job: Job solver_type: SolverType time_us: int = -1 - lengths: List[List[int]] + lengths: List[List[Tuple[int, str]]] # no trimmings as they can be inferred from difference to job def __eq__(self, other): return ( - self.job == other.job - and self.solver_type == other.solver_type - and self.lengths == other.lengths + self.job == other.job + and self.solver_type == other.solver_type + and self.lengths == other.lengths ) def exactly(self, other): return ( - self.job == other.job - and self.solver_type == other.solver_type - and self.time_us == other.time_us - and self.lengths == other.lengths + self.job == other.job + and self.solver_type == other.solver_type + and self.time_us == other.time_us + and self.lengths == other.lengths ) def assert_valid(self): diff --git a/tests/solver/data/test_Result.py b/tests/solver/data/test_Result.py index 3423b04..60d8d6f 100644 --- a/tests/solver/data/test_Result.py +++ b/tests/solver/data/test_Result.py @@ -6,34 +6,162 @@ def test_constructor(): job = generate_testjob() - result = Result(job=job, solver_type=SolverType.FFD, time_us=100, lengths=[(100, 100, 100), (200, 200, 200)]) + result = Result( + job=job, + solver_type=SolverType.FFD, + time_us=100, + lengths=[ + [ + (100, "Part1"), + (100, "Part1"), + (100, "Part1"), + ], + [ + (200, "Part2"), + (200, "Part2"), + (200, "Part2"), + ], + ], + ) assert result def test_valid(): job = generate_testjob() - result = Result(job=job, solver_type=SolverType.FFD, time_us=100, lengths=[(100, 100, 100), (200, 200, 200)]) + result = Result( + job=job, + solver_type=SolverType.FFD, + time_us=100, + lengths=[ + [ + (100, "Part1"), + (100, "Part1"), + (100, "Part1"), + ], + [ + (200, "Part2"), + (200, "Part2"), + (200, "Part2"), + ], + ], + ) result.assert_valid() def test_invalid(): job = generate_testjob() - invalid_result = Result(job=job, solver_type=SolverType.FFD, time_us=-1, lengths=[(100, 100, 100), (200, 200, 200)]) + invalid_result = Result( + job=job, + solver_type=SolverType.FFD, + time_us=-1, + lengths=[ + [ + (100, "Part1"), + (100, "Part1"), + (100, "Part1"), + ], + [ + (200, "Part2"), + (200, "Part2"), + (200, "Part2"), + ], + ], + ) with pytest.raises(ValueError): invalid_result.assert_valid() def test_equal(): job = generate_testjob() - result1 = Result(job=job, solver_type=SolverType.FFD, time_us=100, lengths=[(100, 100, 100), (200, 200, 200)]) - result2 = Result(job=job, solver_type=SolverType.FFD, time_us=200, lengths=[(100, 100, 100), (200, 200, 200)]) + result1 = Result( + job=job, + solver_type=SolverType.FFD, + time_us=100, + lengths=[ + [ + (100, "Part1"), + (100, "Part1"), + (100, "Part1"), + ], + [ + (200, "Part2"), + (200, "Part2"), + (200, "Part2"), + ], + ], + ) + result2 = Result( + job=job, + solver_type=SolverType.FFD, + time_us=200, + lengths=[ + [ + (100, "Part1"), + (100, "Part1"), + (100, "Part1"), + ], + [ + (200, "Part2"), + (200, "Part2"), + (200, "Part2"), + ], + ], + ) assert result1 == result2 def test_exactly(): job = generate_testjob() - result1 = Result(job=job, solver_type=SolverType.FFD, time_us=100, lengths=[(100, 100, 100), (200, 200, 200)]) - result2 = Result(job=job, solver_type=SolverType.FFD, time_us=200, lengths=[(100, 100, 100), (200, 200, 200)]) - result3 = Result(job=job, solver_type=SolverType.FFD, time_us=200, lengths=[(100, 100, 100), (200, 200, 200)]) + result1 = Result( + job=job, + solver_type=SolverType.FFD, + time_us=100, + lengths=[ + [ + (100, "Part1"), + (100, "Part1"), + (100, "Part1"), + ], + [ + (200, "Part2"), + (200, "Part2"), + (200, "Part2"), + ], + ], + ) + result2 = Result( + job=job, + solver_type=SolverType.FFD, + time_us=200, + lengths=[ + [ + (100, "Part1"), + (100, "Part1"), + (100, "Part1"), + ], + [ + (200, "Part2"), + (200, "Part2"), + (200, "Part2"), + ], + ], + ) + result3 = Result( + job=job, + solver_type=SolverType.FFD, + time_us=200, + lengths=[ + [ + (100, "Part1"), + (100, "Part1"), + (100, "Part1"), + ], + [ + (200, "Part2"), + (200, "Part2"), + (200, "Part2"), + ], + ], + ) assert not result1.exactly(result2) assert result2.exactly(result3) From 5caf1eb01286ea243fdfcc6730c549a99df630f1 Mon Sep 17 00:00:00 2001 From: Bouni Date: Fri, 19 Jan 2024 10:18:59 +0100 Subject: [PATCH 06/13] Refactor json tests --- tests/solver/data/test_json.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/tests/solver/data/test_json.py b/tests/solver/data/test_json.py index 89e2de6..6ca5e7c 100644 --- a/tests/solver/data/test_json.py +++ b/tests/solver/data/test_json.py @@ -1,13 +1,22 @@ from pathlib import Path # import from app! Modules won't be found otherwise -from app.solver.data.Job import Job +from app.solver.data.Job import Job, TargetSize def test_to_json(): - job = Job(max_length=1200, cut_width=5, target_sizes={"300": 4, "200": 3}) - assert job.json() == '{"max_length": 1200, "cut_width": 5, ' \ - '"target_sizes": {"300": 4, "200": 3}}' + job = Job( + max_length=1200, + cut_width=5, + target_sizes=[ + TargetSize(length=300, quantity=4, name="Part1"), + TargetSize(length=200, quantity=3), + ], + ) + assert ( + job.model_dump_json() + == '{"max_length":1200,"cut_width":5,"target_sizes":[{"length":300,"quantity":4,"name":"Part1"},{"length":200,"quantity":3,"name":""}]}' + ) def test_from_json(): @@ -15,6 +24,6 @@ def test_from_json(): assert json_file.exists() with open(json_file, "r") as encoded_job: - job = Job.parse_raw(encoded_job.read()) + job = Job.model_validate_json(encoded_job.read()) assert job.__class__ == Job assert len(job) > 0 From ba939735ed7f2381679fc49839b56bf60e14856e Mon Sep 17 00:00:00 2001 From: Bouni Date: Fri, 19 Jan 2024 10:19:34 +0100 Subject: [PATCH 07/13] Refactor Solver to work with lengths and names --- app/solver/solver.py | 43 +++++++++++++++++++++---------------- tests/solver/test_solver.py | 38 ++++++++++++++++++++++---------- 2 files changed, 51 insertions(+), 30 deletions(-) diff --git a/app/solver/solver.py b/app/solver/solver.py index a2b2906..ab58ae7 100644 --- a/app/solver/solver.py +++ b/app/solver/solver.py @@ -5,14 +5,14 @@ from typing import Collection, Tuple, List from app.constants import n_max_precise, n_max -from app.solver.data.Job import Job +from app.solver.data.Job import Job, TargetSize from app.solver.data.Result import SolverType, Result def distribute(job: Job) -> Result: time: float = perf_counter() - lengths: List[List[int]] + lengths: List[List[Tuple[int, str]]] solver_type: SolverType if len(job) <= n_max_precise: @@ -31,7 +31,7 @@ def distribute(job: Job) -> Result: # CPU-bound # O(n!) -def _solve_bruteforce(job: Job) -> List[List[int]]: +def _solve_bruteforce(job: Job) -> List[List[Tuple[int, str]]]: # failsafe if len(job) > 12: raise OverflowError("Input too large") @@ -42,11 +42,13 @@ def _solve_bruteforce(job: Job) -> List[List[int]]: # "infinity" minimal_trimmings = len(job) * job.max_length - best_stock: List[List[int]] = [] + best_stock: List[List[Tuple[int, str]]] = [] # possible improvement: Distribute combinations to multiprocessing worker threads for combination in all_orderings: - stocks, trimmings = _split_combination(combination, job.max_length, job.cut_width) + stocks, trimmings = _split_combination( + combination, job.max_length, job.cut_width + ) if trimmings < minimal_trimmings: best_stock = stocks minimal_trimmings = trimmings @@ -54,7 +56,9 @@ def _solve_bruteforce(job: Job) -> List[List[int]]: return best_stock -def _split_combination(combination: Tuple[int], max_length: int, cut_width: int): +def _split_combination( + combination: Tuple[Tuple[int, str]], max_length: int, cut_width: int +): """ Collects sizes until length is reached, then starts another stock :param combination: @@ -62,21 +66,21 @@ def _split_combination(combination: Tuple[int], max_length: int, cut_width: int) :param cut_width: :return: """ - stocks: List[List[int]] = [] + stocks: List[List[Tuple[int, str]]] = [] trimmings = 0 current_size = 0 - current_stock: List[int] = [] - for size in combination: + current_stock: List[Tuple[int, str]] = [] + for size, name in combination: if (current_size + size + cut_width) > max_length: # start next stock stocks.append(current_stock) trimmings += _get_trimming(max_length, current_stock, cut_width) current_size = 0 - current_stock: List[int] = [] + current_stock: List[Tuple[int, str]] = [] current_size += size + cut_width - current_stock.append(size) + current_stock.append((size, name)) # catch leftovers if current_stock: stocks.append(current_stock) @@ -86,7 +90,7 @@ def _split_combination(combination: Tuple[int], max_length: int, cut_width: int) # this might actually be worse than FFD (both in runtime and solution), disabled for now # O(n^2) ?? -def _solve_gapfill(job: Job) -> List[List[int]]: +def _solve_gapfill(job: Job) -> List[List[Tuple[int, str]]]: # 1. Sort by magnitude (largest first) # 2. stack until limit is reached # 3. try smaller as long as possible @@ -100,11 +104,10 @@ def _solve_gapfill(job: Job) -> List[List[int]]: stocks = [] current_size = 0 - current_stock = [] + current_stock: List[Tuple[int, str]] = [] i_target = 0 while len(targets) > 0: - # nothing fit, next stock if i_target >= len(targets): # add local result @@ -115,10 +118,10 @@ def _solve_gapfill(job: Job) -> List[List[int]]: current_size = 0 i_target = 0 - current_target = targets[i_target] + current_target: TargetSize = targets[i_target] # target fits inside current stock, transfer to results if (current_size + current_target.length + job.cut_width) < job.max_length: - current_stock.append(current_target.length) + current_stock.append((current_target.length, current_target.name)) current_size += current_target.length + job.cut_width # remove empty entries @@ -140,7 +143,7 @@ def _solve_gapfill(job: Job) -> List[List[int]]: # textbook solution, guaranteed to need <= double of perfect solution # TODO this has ridiculous execution times, check why -def _solve_FFD(job: Job) -> List[List[int]]: +def _solve_FFD(job: Job) -> List[List[Tuple[int, str]]]: # iterate over list of stocks # put into first stock that it fits into @@ -180,8 +183,10 @@ def _solve_FFD(job: Job) -> List[List[int]]: return stocks -def _get_trimming(max_length: int, lengths: Collection[int], cut_width: int) -> int: - sum_lengths = sum(lengths) +def _get_trimming( + max_length: int, lengths: Collection[Tuple[int, str]], cut_width: int +) -> int: + sum_lengths = sum([length[0] for length in lengths]) sum_cuts = len(lengths) * cut_width trimmings = max_length - (sum_lengths + sum_cuts) diff --git a/tests/solver/test_solver.py b/tests/solver/test_solver.py index c394438..479bb7c 100644 --- a/tests/solver/test_solver.py +++ b/tests/solver/test_solver.py @@ -4,12 +4,22 @@ from app.solver.data.Job import Job from app.solver.data.Result import Result -from app.solver.solver import _get_trimming, _solve_bruteforce, _solve_gapfill, _solve_FFD, distribute +from app.solver.solver import ( + _get_trimming, + _solve_bruteforce, + _solve_gapfill, + _solve_FFD, + distribute, +) from tests.test_utils import generate_testjob def test_trimmings(): - trimming = _get_trimming(max_length=1500, lengths=(300, 400, 600, 100), cut_width=2) + trimming = _get_trimming( + max_length=1500, + lengths=((300, ""), (400, ""), (600, ""), (100, "")), + cut_width=2, + ) assert trimming == 92 @@ -17,33 +27,39 @@ def test_trimmings(): def test_trimmings_raise(): # raises Error if more stock was used than available with pytest.raises(OverflowError): - _get_trimming(1500, (300, 400, 600, 200), 2) + _get_trimming(1500, ((300, ""), (400, ""), (600, ""), (200, "")), 2) def test_bruteforce(): job = generate_testjob() - orig_job = job.copy(deep=True) + orig_job = job.model_copy(deep=True) solved = _solve_bruteforce(job) - assert solved == [[500, 500, 200, 200], [200, 200]] + assert solved == [ + [(500, "Part1"), (500, "Part1"), (200, "Part2"), (200, "Part2")], + [(200, "Part2"), (200, "Part2")], + ] assert orig_job == job def test_gapfill(): job = generate_testjob() - orig_job = job.copy(deep=True) + orig_job = job.model_copy(deep=True) solved = _solve_gapfill(job) - assert solved == [[500, 500, 200, 200], [200, 200]] + assert solved == [ + [(500, "Part1"), (500, "Part1"), (200, "Part2"), (200, "Part2")], + [(200, "Part2"), (200, "Part2")], + ] assert orig_job == job def test_FFD(): job = generate_testjob() - orig_job = job.copy(deep=True) + orig_job = job.model_copy(deep=True) solved = _solve_FFD(job) assert solved == [[500, 500, 200, 200], [200, 200]] @@ -57,14 +73,14 @@ def test_full_model(): json_result = Path("./tests/res/out/testresult.json") with open(json_job, "r") as encoded_job: - job = Job.parse_raw(encoded_job.read()) + job = Job.model_validate_json(encoded_job.read()) solved = distribute(job) - encoded_solved = solved.json() + encoded_solved = solved.model_dump_json() assert len(encoded_solved) > 20 with open(json_result, "r") as encoded_result: - result = Result.parse_raw(encoded_result.read()) + result = Result.model_validate_json(encoded_result.read()) assert solved == result From 3580a445761095a52b0dadd472d78ca8c41393c1 Mon Sep 17 00:00:00 2001 From: Bouni Date: Fri, 19 Jan 2024 10:26:02 +0100 Subject: [PATCH 08/13] Replace on_event with lifespan events --- app/main.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/app/main.py b/app/main.py index a8b9cb3..bc75f42 100644 --- a/app/main.py +++ b/app/main.py @@ -1,4 +1,5 @@ import platform +from contextlib import asynccontextmanager from fastapi import FastAPI from starlette.middleware.cors import CORSMiddleware @@ -6,26 +7,22 @@ from starlette.responses import HTMLResponse, PlainTextResponse from app.constants import version, n_max_precise, n_max + # don't mark /app as a sources root or pycharm will delete the "app." prefix # that's needed for pytest to work correctly from app.solver.data.Job import Job from app.solver.data.Result import Result from app.solver.solver import distribute -app = FastAPI( - title="CutSolverBackend", - version=version -) - -@app.on_event("startup") -async def on_startup(): +@asynccontextmanager +async def lifespan(app: FastAPI): print(f"Starting CutSolver {version}...") + yield + print("Shutting down CutSolver...") -@app.on_event("shutdown") -async def on_shutdown(): - print(f"Shutting down CutSolver...") +app = FastAPI(title="CutSolverBackend", version=version, lifespan=lifespan) # needs to be before CORS! From 7e5fd9fc6af54caf8be387009608468df066fe5c Mon Sep 17 00:00:00 2001 From: Bouni Date: Fri, 19 Jan 2024 10:26:21 +0100 Subject: [PATCH 09/13] Refactor tests for main --- tests/test_main.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/test_main.py b/tests/test_main.py index 2893d98..1ec3aad 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -26,8 +26,7 @@ def test_get_debug(): def test_full(): - reply = client.post("/solve", generate_testjob().json()) + reply = client.post("/solve", json=generate_testjob().model_dump()) assert reply.status_code == 200 json_result = reply.json() - - assert Result.parse_obj(json_result) == generate_testresult() + assert Result.model_validate(json_result) == generate_testresult() From 77552f278c0086d9c58610e21867c338ad6e2a7d Mon Sep 17 00:00:00 2001 From: Bouni Date: Tue, 23 Jan 2024 10:41:57 +0100 Subject: [PATCH 10/13] Update Dockefile to use Python 3.12 --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 3f4be19..0a93cbe 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # this size should be irrelevant -FROM python:3.9 as build +FROM python:3.12 as build # exporting here is a lot safer than depending on the dev environment. Pipenv is kept out of the container by design. COPY ./Pipfile /Pipfile RUN pip install pipenv @@ -9,7 +9,7 @@ RUN pipenv lock && pipenv requirements > dev-requirements.txt # certifi+httpie allows healthchecks with tiny installation size (#37) RUN pip install --user --no-cache-dir --no-warn-script-location -r dev-requirements.txt -FROM python:3.9-slim +FROM python:3.12-slim # https://github.com/opencontainers/image-spec/blob/master/annotations.md LABEL "org.opencontainers.image.title"="CutSolver" LABEL "org.opencontainers.image.vendor"="Modisch Fabrications" From db416f3b1a80ae22cdeafa7e9eeb2808545e8fad Mon Sep 17 00:00:00 2001 From: Bouni Date: Wed, 24 Jan 2024 12:52:35 +0100 Subject: [PATCH 11/13] refactored ffd solver to use size and name --- app/solver/solver.py | 35 ++++++++++++++++++----------------- tests/solver/test_solver.py | 6 +++++- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/app/solver/solver.py b/app/solver/solver.py index ab58ae7..12c649f 100644 --- a/app/solver/solver.py +++ b/app/solver/solver.py @@ -31,7 +31,7 @@ def distribute(job: Job) -> Result: # CPU-bound # O(n!) -def _solve_bruteforce(job: Job) -> List[List[Tuple[int, str]]]: +def _solve_bruteforce(job: Job) -> List[List[Tuple[int, str | None]]]: # failsafe if len(job) > 12: raise OverflowError("Input too large") @@ -42,7 +42,7 @@ def _solve_bruteforce(job: Job) -> List[List[Tuple[int, str]]]: # "infinity" minimal_trimmings = len(job) * job.max_length - best_stock: List[List[Tuple[int, str]]] = [] + best_stock: List[List[Tuple[int, str | None]]] = [] # possible improvement: Distribute combinations to multiprocessing worker threads for combination in all_orderings: @@ -57,7 +57,7 @@ def _solve_bruteforce(job: Job) -> List[List[Tuple[int, str]]]: def _split_combination( - combination: Tuple[Tuple[int, str]], max_length: int, cut_width: int + combination: Tuple[Tuple[int, str | None]], max_length: int, cut_width: int ): """ Collects sizes until length is reached, then starts another stock @@ -66,18 +66,18 @@ def _split_combination( :param cut_width: :return: """ - stocks: List[List[Tuple[int, str]]] = [] + stocks: List[List[Tuple[int, str | None]]] = [] trimmings = 0 current_size = 0 - current_stock: List[Tuple[int, str]] = [] + current_stock: List[Tuple[int, str | None]] = [] for size, name in combination: if (current_size + size + cut_width) > max_length: # start next stock stocks.append(current_stock) trimmings += _get_trimming(max_length, current_stock, cut_width) current_size = 0 - current_stock: List[Tuple[int, str]] = [] + current_stock: List[Tuple[int, str | None]] = [] current_size += size + cut_width current_stock.append((size, name)) @@ -90,7 +90,7 @@ def _split_combination( # this might actually be worse than FFD (both in runtime and solution), disabled for now # O(n^2) ?? -def _solve_gapfill(job: Job) -> List[List[Tuple[int, str]]]: +def _solve_gapfill(job: Job) -> List[List[Tuple[int, str | None]]]: # 1. Sort by magnitude (largest first) # 2. stack until limit is reached # 3. try smaller as long as possible @@ -104,7 +104,7 @@ def _solve_gapfill(job: Job) -> List[List[Tuple[int, str]]]: stocks = [] current_size = 0 - current_stock: List[Tuple[int, str]] = [] + current_stock: List[Tuple[int, str | None]] = [] i_target = 0 while len(targets) > 0: @@ -142,8 +142,8 @@ def _solve_gapfill(job: Job) -> List[List[Tuple[int, str]]]: # textbook solution, guaranteed to need <= double of perfect solution -# TODO this has ridiculous execution times, check why -def _solve_FFD(job: Job) -> List[List[Tuple[int, str]]]: +# TODO: this has ridiculous execution times, check why +def _solve_FFD(job: Job) -> List[List[Tuple[int, str | None]]]: # iterate over list of stocks # put into first stock that it fits into @@ -156,23 +156,24 @@ def _solve_FFD(job: Job) -> List[List[Tuple[int, str]]]: mutable_sizes = copy.deepcopy(job.sizes_as_list()) sizes = sorted(mutable_sizes, reverse=True) - stocks: List[List[int]] = [[]] + stocks: List[List[Tuple[int, str | None]]] = [[]] i_target = 0 while i_target < len(sizes): current_size = sizes[i_target] - - for i, stock in enumerate(stocks): + for stock in stocks: # calculate current stock length - stock_length = sum(stock) + (len(stock) - 1) * job.cut_width + stock_length = ( + sum([size[0] for size in stock]) + (len(stock) - 1) * job.cut_width + ) # step through existing stocks until current size fits if (job.max_length - stock_length) > current_size.length: # add size - stock.append(current_size.length) + stock.append((current_size.length, current_size.name)) break else: # nothing fit, opening next bin - stocks.append([current_size.length]) + stocks.append([(current_size.length, current_size.name)]) # decrease/get next if current_size.quantity <= 1: @@ -184,7 +185,7 @@ def _solve_FFD(job: Job) -> List[List[Tuple[int, str]]]: def _get_trimming( - max_length: int, lengths: Collection[Tuple[int, str]], cut_width: int + max_length: int, lengths: Collection[Tuple[int, str | None]], cut_width: int ) -> int: sum_lengths = sum([length[0] for length in lengths]) sum_cuts = len(lengths) * cut_width diff --git a/tests/solver/test_solver.py b/tests/solver/test_solver.py index 479bb7c..5c75f94 100644 --- a/tests/solver/test_solver.py +++ b/tests/solver/test_solver.py @@ -62,7 +62,11 @@ def test_FFD(): orig_job = job.model_copy(deep=True) solved = _solve_FFD(job) - assert solved == [[500, 500, 200, 200], [200, 200]] + # assert solved == [[500, 500, 200, 200], [200, 200]] + assert solved == [ + [(500, "Part1"), (500, "Part1"), (200, "Part2"), (200, "Part2")], + [(200, "Part2"), (200, "Part2")], + ] assert orig_job == job From 2247c56f905dd559a17073c0c895fb8e59d78282 Mon Sep 17 00:00:00 2001 From: Robin Modisch Date: Sun, 28 Jan 2024 15:56:51 +0100 Subject: [PATCH 12/13] homogenize py version to 3.11 --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 0a93cbe..9ea498a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # this size should be irrelevant -FROM python:3.12 as build +FROM python:3.11 as build # exporting here is a lot safer than depending on the dev environment. Pipenv is kept out of the container by design. COPY ./Pipfile /Pipfile RUN pip install pipenv @@ -9,7 +9,7 @@ RUN pipenv lock && pipenv requirements > dev-requirements.txt # certifi+httpie allows healthchecks with tiny installation size (#37) RUN pip install --user --no-cache-dir --no-warn-script-location -r dev-requirements.txt -FROM python:3.12-slim +FROM python:3.11-slim # https://github.com/opencontainers/image-spec/blob/master/annotations.md LABEL "org.opencontainers.image.title"="CutSolver" LABEL "org.opencontainers.image.vendor"="Modisch Fabrications" From ffc6a4d55036329f39e8a6655cdf4c19b9ad5aee Mon Sep 17 00:00:00 2001 From: Robin Modisch Date: Sun, 28 Jan 2024 15:59:23 +0100 Subject: [PATCH 13/13] Update ci.yml py to 3.11 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 22b5937..92d0b4e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,7 +39,7 @@ jobs: - name: Set up Python ⚙️ uses: actions/setup-python@v4 with: - python-version: "3.9" # keep in sync with pipfile + python-version: "3.11" # keep in sync with pipfile - name: Install dependencies ⚙️ run: |