diff --git a/Pipfile b/Pipfile index 6ad3649a..85357533 100644 --- a/Pipfile +++ b/Pipfile @@ -17,6 +17,7 @@ pandas = "*" plotly = "*" pillow = ">=11.3.0" # Ensure dependency is secure Pyarrow = "*" +pycountry = "*" Pygments = "*" python-dotenv = "*" PyYAML = "*" diff --git a/Pipfile.lock b/Pipfile.lock index c111bd7d..e275cbcf 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -74,11 +74,11 @@ }, "asttokens": { "hashes": [ - "sha256:0dcd8baa8d62b0c1d118b399b2ddba3c4aff271d0d7a9e0d4c1681c79035bbc7", - "sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2" + "sha256:15a3ebc0f43c2d0a50eeafea25e19046c68398e487b9f1f5b517f7c0f40f976a", + "sha256:71a4ee5de0bde6a31d64f6b13f2293ac190344478f081c3d1bccfcf5eacb0cb7" ], "markers": "python_version >= '3.8'", - "version": "==3.0.0" + "version": "==3.0.1" }, "async-lru": { "hashes": [ @@ -117,27 +117,27 @@ "css" ], "hashes": [ - "sha256:117d9c6097a7c3d22fd578fcd8d35ff1e125df6736f554da4e432fdd63f31e5e", - "sha256:123e894118b8a599fd80d3ec1a6d4cc7ce4e5882b1317a7e1ba69b56e95f991f" + "sha256:6f3b91b1c0a02bb9a78b5a454c92506aa0fdf197e1d5e114d2e00c6f64306d22", + "sha256:fe10ec77c93ddf3d13a73b035abaac7a9f5e436513864ccdad516693213c65d6" ], - "markers": "python_version >= '3.9'", - "version": "==6.2.0" + "markers": "python_version >= '3.10'", + "version": "==6.3.0" }, "cachetools": { "hashes": [ - "sha256:09868944b6dde876dfd44e1d47e18484541eaf12f26f29b7af91b26cc892d701", - "sha256:3f391e4bd8f8bf0931169baf7456cc822705f4e2a31f840d218f445b9a854201" + "sha256:6c09c98183bf58560c97b2abfcedcbaf6a896a490f534b031b661d3723b45ace", + "sha256:8e6d266b25e539df852251cfd6f990b4bc3a141db73b939058d809ebd2590fc6" ], "markers": "python_version >= '3.9'", - "version": "==6.2.1" + "version": "==6.2.2" }, "certifi": { "hashes": [ - "sha256:0f212c2744a9bb6de0c56639a6f68afe01ecd92d91f14ae897c4fe7bbeeef0de", - "sha256:47c09d31ccf2acf0be3f701ea53595ee7e0b8fa08801c6624be771df09ae7b43" + "sha256:97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b", + "sha256:d8ab5478f2ecd78af242878415affce761ca6bc54a22a27e026d7c25357c3316" ], "markers": "python_version >= '3.7'", - "version": "==2025.10.5" + "version": "==2025.11.12" }, "cffi": { "hashes": [ @@ -617,43 +617,44 @@ }, "google-api-core": { "hashes": [ - "sha256:779a380db4e21a4ee3d717cf8efbf324e53900bf37e1ffb273e5348a9916dd42", - "sha256:d32e2f5dd0517e91037169e75bf0a9783b255aff1d11730517c0b2b29e9db06a" + "sha256:2b405df02d68e68ce0fbc138559e6036559e685159d148ae5861013dc201baf8", + "sha256:4021b0f8ceb77a6fb4de6fde4502cecab45062e66ff4f2895169e0b35bc9466c" ], "markers": "python_version >= '3.7'", - "version": "==2.27.0" + "version": "==2.28.1" }, "google-api-python-client": { "hashes": [ - "sha256:00fe173a4b346d2397fbe0d37ac15368170dfbed91a0395a66ef2558e22b93fc", - "sha256:aa1b338e4bb0f141c2df26743f6b46b11f38705aacd775b61971cbc51da089c3" + "sha256:d8d0f6d85d7d1d10bdab32e642312ed572bdc98919f72f831b44b9a9cebba32f", + "sha256:e98e8e8f49e1b5048c2f8276473d6485febc76c9c47892a8b4d1afa2c9ec8278" ], "index": "pypi", "markers": "python_version >= '3.7'", - "version": "==2.185.0" + "version": "==2.187.0" }, "google-auth": { "hashes": [ - "sha256:754843be95575b9a19c604a848a41be03f7f2afd8c019f716dc1f51ee41c639d", - "sha256:b76b7b1f9e61f0cb7e88870d14f6a94aeef248959ef6992670efee37709cbfd2" + "sha256:88228eee5fc21b62a1b5fe773ca15e67778cb07dc8363adcb4a8827b52d81483", + "sha256:af628ba6fa493f75c7e9dbe9373d148ca9f4399b5ea29976519e0a3848eddd16" ], "markers": "python_version >= '3.7'", - "version": "==2.41.1" + "version": "==2.43.0" }, "google-auth-httplib2": { "hashes": [ - "sha256:38aa7badf48f974f1eb9861794e9c0cb2a0511a4ec0679b1f886d108f5640e05", - "sha256:b65a0a2123300dd71281a7bf6e64d65a0759287df52729bdd1ae2e47dc311a3d" + "sha256:1be94c611db91c01f9703e7f62b0a59bbd5587a95571c7b6fade510d648bc08b", + "sha256:5ef03be3927423c87fb69607b42df23a444e434ddb2555b73b3679793187b7de" ], - "version": "==0.2.0" + "markers": "python_version >= '3.7'", + "version": "==0.2.1" }, "googleapis-common-protos": { "hashes": [ - "sha256:1aec01e574e29da63c80ba9f7bbf1ccfaacf1da877f23609fe236ca7c72a2e2e", - "sha256:59034a1d849dc4d18971997a72ac56246570afdd17f9369a0ff68218d50ab78c" + "sha256:4299c5a82d5ae1a9702ada957347726b167f9f8d1fc352477702a1e851ff4038", + "sha256:e55a601c1b32b52d7a3e65f43563e2aa61bcd737998ee672ac9b951cd49319f5" ], "markers": "python_version >= '3.7'", - "version": "==1.71.0" + "version": "==1.72.0" }, "h11": { "hashes": [ @@ -698,28 +699,28 @@ }, "internetarchive": { "hashes": [ - "sha256:1a4de65ceada60e4a86a26ce8dff150995d70e2e19f5e9ad9fed55654c298811", - "sha256:252332d838556a156131f8102e02e07f60424da489cc5f0e97c987f0a038a412" + "sha256:f35e545c4925e1fc5f37bd83e59b8b72f79645129d0a32772a6d25fb5252d92a", + "sha256:fcfcb729f4d7ffdad42aaed22247ac42e21fe2d99c122646870844cbbd981559" ], "index": "pypi", "markers": "python_version >= '3.9'", - "version": "==5.7.0" + "version": "==5.7.1" }, "ipykernel": { "hashes": [ - "sha256:2d3fd7cdef22071c2abbad78f142b743228c5d59cd470d034871ae0ac359533c", - "sha256:87182a8305e28954b6721087dec45b171712610111d494c17bb607befa1c4000" + "sha256:58a3fc88533d5930c3546dc7eac66c6d288acde4f801e2001e65edc5dc9cf0db", + "sha256:763b5ec6c5b7776f6a8d7ce09b267693b4e5ce75cb50ae696aaefb3c85e1ea4c" ], "markers": "python_version >= '3.10'", - "version": "==7.0.1" + "version": "==7.1.0" }, "ipython": { "hashes": [ - "sha256:5603d6d5d356378be5043e69441a072b50a5b33b4503428c77b04cb8ce7bc731", - "sha256:5f77efafc886d2f023442479b8149e7d86547ad0a979e9da9f045d252f648196" + "sha256:5f6de88c905a566c6a9d6c400a8fed54a638e1f7543d17aae2551133216b1e4e", + "sha256:bce8ac85eb9521adc94e1845b4c03d88365fd6ac2f4908ec4ed1eb1b0a065f9f" ], "markers": "python_version >= '3.11'", - "version": "==9.6.0" + "version": "==9.7.0" }, "ipython-pygments-lexers": { "hashes": [ @@ -846,12 +847,12 @@ }, "jupyterlab": { "hashes": [ - "sha256:521c017508af4e1d6d9d8a9d90f47a11c61197ad63b2178342489de42540a615", - "sha256:65939ab4c8dcd0c42185c2d0d1a9d60b254dc8c46fc4fdb286b63c51e9358e07" + "sha256:88e157c75c1afff64c7dc4b801ec471450b922a4eae4305211ddd40da8201c8a", + "sha256:aec33d6d8f1225b495ee2cf20f0514f45e6df8e360bdd7ac9bace0b7ac5177ea" ], "index": "pypi", "markers": "python_version >= '3.9'", - "version": "==4.4.10" + "version": "==4.5.0" }, "jupyterlab-pygments": { "hashes": [ @@ -978,11 +979,11 @@ }, "lark": { "hashes": [ - "sha256:80661f261fb2584a9828a097a2432efd575af27d20be0fd35d17f0fe37253831", - "sha256:9a3839d0ca5e1faf7cfa3460e420e859b66bcbde05b634e73c369c8244c5fa48" + "sha256:b426a7a6d6d53189d318f2b6236ab5d6429eaf09259f1ca33eb716eed10d2905", + "sha256:c629b661023a014c37da873b4ff58a817398d12635d3bbb2c5a03be7fe5d1e12" ], "markers": "python_version >= '3.8'", - "version": "==1.3.0" + "version": "==1.3.1" }, "markupsafe": { "hashes": [ @@ -1159,11 +1160,11 @@ }, "narwhals": { "hashes": [ - "sha256:c59f7de4763004ae81691ce16df71b4e55aead0ead7ccde8c8f2ef8c9559c765", - "sha256:d8cde40a6a8a7049d8e66608b7115ab19464acc6f305d136a8dc8ba396c4acfe" + "sha256:075b6d56f3a222613793e025744b129439ecdff9292ea6615dd983af7ba6ea44", + "sha256:baeba5d448a30b04c299a696bd9ee5ff73e4742143e06c49ca316b46539a7cbb" ], "markers": "python_version >= '3.9'", - "version": "==2.9.0" + "version": "==2.12.0" }, "nbclient": { "hashes": [ @@ -1207,84 +1208,84 @@ }, "numpy": { "hashes": [ - "sha256:035796aaaddfe2f9664b9a9372f089cfc88bd795a67bd1bfe15e6e770934cf64", - "sha256:043885b4f7e6e232d7df4f51ffdef8c36320ee9d5f227b380ea636722c7ed12e", - "sha256:04a69abe45b49c5955923cf2c407843d1c85013b424ae8a560bba16c92fe44a0", - "sha256:0f2bcc76f1e05e5ab58893407c63d90b2029908fa41f9f1cc51eecce936c3365", - "sha256:13b9062e4f5c7ee5c7e5be96f29ba71bc5a37fed3d1d77c37390ae00724d296d", - "sha256:15eea9f306b98e0be91eb344a94c0e630689ef302e10c2ce5f7e11905c704f9c", - "sha256:15fb27364ed84114438fff8aaf998c9e19adbeba08c0b75409f8c452a8692c52", - "sha256:1b219560ae2c1de48ead517d085bc2d05b9433f8e49d0955c82e8cd37bd7bf36", - "sha256:22758999b256b595cf0b1d102b133bb61866ba5ceecf15f759623b64c020c9ec", - "sha256:2ec646892819370cf3558f518797f16597b4e4669894a2ba712caccc9da53f1f", - "sha256:3634093d0b428e6c32c3a69b78e554f0cd20ee420dcad5a9f3b2a63762ce4197", - "sha256:36dc13af226aeab72b7abad501d370d606326a0029b9f435eacb3b8c94b8a8b7", - "sha256:3da3491cee49cf16157e70f607c03a217ea6647b1cea4819c4f48e53d49139b9", - "sha256:40cc556d5abbc54aabe2b1ae287042d7bdb80c08edede19f0c0afb36ae586f37", - "sha256:4121c5beb58a7f9e6dfdee612cb24f4df5cd4db6e8261d7f4d7450a997a65d6a", - "sha256:4635239814149e06e2cb9db3dd584b2fa64316c96f10656983b8026a82e6e4db", - "sha256:4c01835e718bcebe80394fd0ac66c07cbb90147ebbdad3dcecd3f25de2ae7e2c", - "sha256:4ee6a571d1e4f0ea6d5f22d6e5fbd6ed1dc2b18542848e1e7301bd190500c9d7", - "sha256:56209416e81a7893036eea03abcb91c130643eb14233b2515c90dcac963fe99d", - "sha256:5e199c087e2aa71c8f9ce1cb7a8e10677dc12457e7cc1be4798632da37c3e86e", - "sha256:62b2198c438058a20b6704351b35a1d7db881812d8512d67a69c9de1f18ca05f", - "sha256:64c5825affc76942973a70acf438a8ab618dbd692b84cd5ec40a0a0509edc09a", - "sha256:65611ecbb00ac9846efe04db15cbe6186f562f6bb7e5e05f077e53a599225d16", - "sha256:6d34ed9db9e6395bb6cd33286035f73a59b058169733a9db9f85e650b88df37e", - "sha256:6d9cd732068e8288dbe2717177320723ccec4fb064123f0caf9bbd90ab5be868", - "sha256:6e274603039f924c0fe5cb73438fa9246699c78a6df1bd3decef9ae592ae1c05", - "sha256:77b84453f3adcb994ddbd0d1c5d11db2d6bda1a2b7fd5ac5bd4649d6f5dc682e", - "sha256:7c26b0b2bf58009ed1f38a641f3db4be8d960a417ca96d14e5b06df1506d41ff", - "sha256:7fd09cc5d65bda1e79432859c40978010622112e9194e581e3415a3eccc7f43f", - "sha256:817e719a868f0dacde4abdfc5c1910b301877970195db9ab6a5e2c4bd5b121f7", - "sha256:81b3a59793523e552c4a96109dde028aa4448ae06ccac5a76ff6532a85558a7f", - "sha256:81c3e6d8c97295a7360d367f9f8553973651b76907988bb6066376bc2252f24e", - "sha256:838f045478638b26c375ee96ea89464d38428c69170360b23a1a50fa4baa3562", - "sha256:84f01a4d18b2cc4ade1814a08e5f3c907b079c847051d720fad15ce37aa930b6", - "sha256:85597b2d25ddf655495e2363fe044b0ae999b75bc4d630dc0d886484b03a5eb0", - "sha256:85d9fb2d8cd998c84d13a79a09cc0c1091648e848e4e6249b0ccd7f6b487fa26", - "sha256:85e071da78d92a214212cacea81c6da557cab307f2c34b5f85b628e94803f9c0", - "sha256:863e3b5f4d9915aaf1b8ec79ae560ad21f0b8d5e3adc31e73126491bb86dee1d", - "sha256:86966db35c4040fdca64f0816a1c1dd8dbd027d90fca5a57e00e1ca4cd41b879", - "sha256:8ab1c5f5ee40d6e01cbe96de5863e39b215a4d24e7d007cad56c7184fdf4aeef", - "sha256:8b5a9a39c45d852b62693d9b3f3e0fe052541f804296ff401a72a1b60edafb29", - "sha256:8dc20bde86802df2ed8397a08d793da0ad7a5fd4ea3ac85d757bf5dd4ad7c252", - "sha256:957e92defe6c08211eb77902253b14fe5b480ebc5112bc741fd5e9cd0608f847", - "sha256:962064de37b9aef801d33bc579690f8bfe6c5e70e29b61783f60bcba838a14d6", - "sha256:985f1e46358f06c2a09921e8921e2c98168ed4ae12ccd6e5e87a4f1857923f32", - "sha256:9984bd645a8db6ca15d850ff996856d8762c51a2239225288f08f9050ca240a0", - "sha256:9cb177bc55b010b19798dc5497d540dea67fd13a8d9e882b2dae71de0cf09eb3", - "sha256:9d729d60f8d53a7361707f4b68a9663c968882dd4f09e0d58c044c8bf5faee7b", - "sha256:a13fc473b6db0be619e45f11f9e81260f7302f8d180c49a22b6e6120022596b3", - "sha256:a49d797192a8d950ca59ee2d0337a4d804f713bb5c3c50e8db26d49666e351dc", - "sha256:a700a4031bc0fd6936e78a752eefb79092cecad2599ea9c8039c548bc097f9bc", - "sha256:a7b2f9a18b5ff9824a6af80de4f37f4ec3c2aab05ef08f51c77a093f5b89adda", - "sha256:a7d018bfedb375a8d979ac758b120ba846a7fe764911a64465fd87b8729f4a6a", - "sha256:b6c231c9c2fadbae4011ca5e7e83e12dc4a5072f1a1d85a0a7b3ed754d145a40", - "sha256:bafa7d87d4c99752d07815ed7a2c0964f8ab311eb8168f41b910bd01d15b6032", - "sha256:bd0c630cf256b0a7fd9d0a11c9413b42fef5101219ce6ed5a09624f5a65392c7", - "sha256:c090d4860032b857d94144d1a9976b8e36709e40386db289aaf6672de2a81966", - "sha256:c2f91f496a87235c6aaf6d3f3d89b17dba64996abadccb289f48456cff931ca9", - "sha256:d149aee5c72176d9ddbc6803aef9c0f6d2ceeea7626574fc68518da5476fa346", - "sha256:d5e081bc082825f8b139f9e9fe42942cb4054524598aaeb177ff476cc76d09d2", - "sha256:d7315ed1dab0286adca467377c8381cd748f3dc92235f22a7dfc42745644a96a", - "sha256:dabc42f9c6577bcc13001b8810d300fe814b4cfbe8a92c873f269484594f9786", - "sha256:e1708fac43ef8b419c975926ce1eaf793b0c13b7356cfab6ab0dc34c0a02ac0f", - "sha256:e73d63fd04e3a9d6bc187f5455d81abfad05660b212c8804bf3b407e984cd2bc", - "sha256:e78aecd2800b32e8347ce49316d3eaf04aed849cd5b38e0af39f829a4e59f5eb", - "sha256:e8370eb6925bb8c1c4264fec52b0384b44f675f191df91cbe0140ec9f0955646", - "sha256:ecb63014bb7f4ce653f8be7f1df8cbc6093a5a2811211770f6606cc92b5a78fd", - "sha256:ed759bf7a70342f7817d88376eb7142fab9fef8320d6019ef87fae05a99874e1", - "sha256:ef1b5a3e808bc40827b5fa2c8196151a4c5abe110e1726949d7abddfe5c7ae11", - "sha256:f77e5b3d3da652b474cc80a14084927a5e86a5eccf54ca8ca5cbd697bf7f2667", - "sha256:faba246fb30ea2a526c2e9645f61612341de1a83fb1e0c5edf4ddda5a9c10996", - "sha256:fc8a63918b04b8571789688b2780ab2b4a33ab44bfe8ccea36d3eba51228c953", - "sha256:fdebe771ca06bb8d6abce84e51dca9f7921fe6ad34a0c914541b063e9a68928b", - "sha256:fea80f4f4cf83b54c3a051f2f727870ee51e22f0248d3114b8e755d160b38cfb" + "sha256:00dc4e846108a382c5869e77c6ed514394bdeb3403461d25a829711041217d5b", + "sha256:0472f11f6ec23a74a906a00b48a4dcf3849209696dff7c189714511268d103ae", + "sha256:04822c00b5fd0323c8166d66c701dc31b7fbd252c100acd708c48f763968d6a3", + "sha256:052e8c42e0c49d2575621c158934920524f6c5da05a1d3b9bab5d8e259e045f0", + "sha256:09a1bea522b25109bf8e6f3027bd810f7c1085c64a0c7ce050c1676ad0ba010b", + "sha256:0cd00b7b36e35398fa2d16af7b907b65304ef8bb4817a550e06e5012929830fa", + "sha256:0d8163f43acde9a73c2a33605353a4f1bc4798745a8b1d73183b28e5b435ae28", + "sha256:1062fde1dcf469571705945b0f221b73928f34a20c904ffb45db101907c3454e", + "sha256:11e06aa0af8c0f05104d56450d6093ee639e15f24ecf62d417329d06e522e017", + "sha256:17531366a2e3a9e30762c000f2c43a9aaa05728712e25c11ce1dbe700c53ad41", + "sha256:1978155dd49972084bd6ef388d66ab70f0c323ddee6f693d539376498720fb7e", + "sha256:1ed1ec893cff7040a02c8aa1c8611b94d395590d553f6b53629a4461dc7f7b63", + "sha256:2dcd0808a421a482a080f89859a18beb0b3d1e905b81e617a188bd80422d62e9", + "sha256:2e2eb32ddb9ccb817d620ac1d8dae7c3f641c1e5f55f531a33e8ab97960a75b8", + "sha256:2feae0d2c91d46e59fcd62784a3a83b3fb677fead592ce51b5a6fbb4f95965ff", + "sha256:3095bdb8dd297e5920b010e96134ed91d852d81d490e787beca7e35ae1d89cf7", + "sha256:30bc11310e8153ca664b14c5f1b73e94bd0503681fcf136a163de856f3a50139", + "sha256:3101e5177d114a593d79dd79658650fe28b5a0d8abeb8ce6f437c0e6df5be1a4", + "sha256:396084a36abdb603546b119d96528c2f6263921c50df3c8fd7cb28873a237748", + "sha256:3997b5b3c9a771e157f9aae01dd579ee35ad7109be18db0e85dbdbe1de06e952", + "sha256:414802f3b97f3c1eef41e530aaba3b3c1620649871d8cb38c6eaff034c2e16bd", + "sha256:51c1e14eb1e154ebd80e860722f9e6ed6ec89714ad2db2d3aa33c31d7c12179b", + "sha256:51c55fe3451421f3a6ef9a9c1439e82101c57a2c9eab9feb196a62b1a10b58ce", + "sha256:5ee6609ac3604fa7780e30a03e5e241a7956f8e2fcfe547d51e3afa5247ac47f", + "sha256:612a95a17655e213502f60cfb9bf9408efdc9eb1d5f50535cc6eb365d11b42b5", + "sha256:6203fdf9f3dc5bdaed7319ad8698e685c7a3be10819f41d32a0723e611733b42", + "sha256:63c0e9e7eea69588479ebf4a8a270d5ac22763cc5854e9a7eae952a3908103f7", + "sha256:66f85ce62c70b843bab1fb14a05d5737741e74e28c7b8b5a064de10142fad248", + "sha256:6cf9b429b21df6b99f4dee7a1218b8b7ffbbe7df8764dc0bd60ce8a0708fed1e", + "sha256:70b37199913c1bd300ff6e2693316c6f869c7ee16378faf10e4f5e3275b299c3", + "sha256:727fd05b57df37dc0bcf1a27767a3d9a78cbbc92822445f32cc3436ba797337b", + "sha256:74ae7b798248fe62021dbf3c914245ad45d1a6b0cb4a29ecb4b31d0bfbc4cc3e", + "sha256:784db1dcdab56bf0517743e746dfb0f885fc68d948aba86eeec2cba234bdf1c0", + "sha256:86945f2ee6d10cdfd67bcb4069c1662dd711f7e2a4343db5cecec06b87cf31aa", + "sha256:86d835afea1eaa143012a2d7a3f45a3adce2d7adc8b4961f0b362214d800846a", + "sha256:872a5cf366aec6bb1147336480fef14c9164b154aeb6542327de4970282cd2f5", + "sha256:8b973c57ff8e184109db042c842423ff4f60446239bd585a5131cc47f06f789d", + "sha256:8cba086a43d54ca804ce711b2a940b16e452807acebe7852ff327f1ecd49b0d4", + "sha256:8f7f0e05112916223d3f438f293abf0727e1181b5983f413dfa2fefc4098245c", + "sha256:900218e456384ea676e24ea6a0417f030a3b07306d29d7ad843957b40a9d8d52", + "sha256:93eebbcf1aafdf7e2ddd44c2923e2672e1010bddc014138b229e49725b4d6be5", + "sha256:9c75442b2209b8470d6d5d8b1c25714270686f14c749028d2199c54e29f20b4d", + "sha256:9ee2197ef8c4f0dfe405d835f3b6a14f5fee7782b5de51ba06fb65fc9b36e9f1", + "sha256:a414504bef8945eae5f2d7cb7be2d4af77c5d1cb5e20b296c2c25b61dff2900c", + "sha256:a4b9159734b326535f4dd01d947f919c6eefd2d9827466a696c44ced82dfbc18", + "sha256:a80afd79f45f3c4a7d341f13acbe058d1ca8ac017c165d3fa0d3de6bc1a079d7", + "sha256:aa5bc7c5d59d831d9773d1170acac7893ce3a5e130540605770ade83280e7188", + "sha256:acfd89508504a19ed06ef963ad544ec6664518c863436306153e13e94605c218", + "sha256:aeffcab3d4b43712bb7a60b65f6044d444e75e563ff6180af8f98dd4b905dfd2", + "sha256:afaffc4393205524af9dfa400fa250143a6c3bc646c08c9f5e25a9f4b4d6a903", + "sha256:b0c7088a73aef3d687c4deef8452a3ac7c1be4e29ed8bf3b366c8111128ac60c", + "sha256:b46b4ec24f7293f23adcd2d146960559aaf8020213de8ad1909dba6c013bf89c", + "sha256:b501b5fa195cc9e24fe102f21ec0a44dffc231d2af79950b451e0d99cea02234", + "sha256:bf06bc2af43fa8d32d30fae16ad965663e966b1a3202ed407b84c989c3221e82", + "sha256:c804e3a5aba5460c73955c955bdbd5c08c354954e9270a2c1565f62e866bdc39", + "sha256:c8a9958e88b65c3b27e22ca2a076311636850b612d6bbfb76e8d156aacde2aaf", + "sha256:cc0a57f895b96ec78969c34f682c602bf8da1a0270b09bc65673df2e7638ec20", + "sha256:cc8920d2ec5fa99875b670bb86ddeb21e295cb07aa331810d9e486e0b969d946", + "sha256:ccc933afd4d20aad3c00bcef049cb40049f7f196e0397f1109dba6fed63267b0", + "sha256:ce581db493ea1a96c0556360ede6607496e8bf9b3a8efa66e06477267bc831e9", + "sha256:d0f23b44f57077c1ede8c5f26b30f706498b4862d3ff0a7298b8411dd2f043ff", + "sha256:d21644de1b609825ede2f48be98dfde4656aefc713654eeee280e37cadc4e0ad", + "sha256:d6889ec4ec662a1a37eb4b4fb26b6100841804dac55bd9df579e326cdc146227", + "sha256:de5672f4a7b200c15a4127042170a694d4df43c992948f5e1af57f0174beed10", + "sha256:e6a0bc88393d65807d751a614207b7129a310ca4fe76a74e5c7da5fa5671417e", + "sha256:ed89927b86296067b4f81f108a2271d8926467a8868e554eaf370fc27fa3ccaf", + "sha256:ee3888d9ff7c14604052b2ca5535a30216aa0a58e948cdd3eeb8d3415f638769", + "sha256:f0963b55cdd70fad460fa4c1341f12f976bb26cb66021a5580329bd498988310", + "sha256:f16417ec91f12f814b10bafe79ef77e70113a2f5f7018640e7425ff979253425", + "sha256:f28620fe26bee16243be2b7b874da327312240a7cdc38b769a697578d2100013", + "sha256:f4255143f5160d0de972d28c8f9665d882b5f61309d8362fdd3e103cf7bf010c", + "sha256:ffac52f28a7849ad7576293c0cb7b9f08304e8f7d738a8cb8a90ec4c55a998eb", + "sha256:ffe22d2b05504f786c867c8395de703937f934272eb67586817b46188b4ded6d", + "sha256:fffe29a1ef00883599d1dc2c51aa2e5d80afe49523c261a74933df395c15c520" ], "index": "pypi", "markers": "python_version >= '3.11'", - "version": "==2.3.4" + "version": "==2.3.5" }, "oauthlib": { "hashes": [ @@ -1496,12 +1497,12 @@ }, "plotly": { "hashes": [ - "sha256:8b4420d1dcf2b040f5983eed433f95732ed24930e496d36eb70d211923532e64", - "sha256:dd896e3d940e653a7ce0470087e82c2bd903969a55e30d1b01bb389319461bb0" + "sha256:5ac851e100367735250206788a2b1325412aa4a4917a4fe3e6f0bc5aa6f3d90a", + "sha256:d5d38224883fd38c1409bef7d6a8dc32b74348d39313f3c52ca998b8e447f5c8" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==6.3.1" + "version": "==6.5.0" }, "prometheus-client": { "hashes": [ @@ -1529,34 +1530,44 @@ }, "protobuf": { "hashes": [ - "sha256:140303d5c8d2037730c548f8c7b93b20bb1dc301be280c378b82b8894589c954", - "sha256:25c9e1963c6734448ea2d308cfa610e692b801304ba0908d7bfa564ac5132995", - "sha256:35be49fd3f4fefa4e6e2aacc35e8b837d6703c37a2168a55ac21e9b1bc7559ef", - "sha256:905b07a65f1a4b72412314082c7dbfae91a9e8b68a0cc1577515f8df58ecf455", - "sha256:9a031d10f703f03768f2743a1c403af050b6ae1f3480e9c140f39c45f81b13ee", - "sha256:c963e86c3655af3a917962c9619e1a6b9670540351d7af9439d06064e3317cc9", - "sha256:cd33a8e38ea3e39df66e1bbc462b076d6e5ba3a4ebbde58219d777223a7873d3", - "sha256:d6101ded078042a8f17959eccd9236fb7a9ca20d3b0098bbcb91533a5680d035", - "sha256:e0697ece353e6239b90ee43a9231318302ad8353c70e6e45499fa52396debf90", - "sha256:e0a1715e4f27355afd9570f3ea369735afc853a6c3951a6afe1f80d8569ad298" + "sha256:023af8449482fa884d88b4563d85e83accab54138ae098924a985bcbb734a213", + "sha256:0f4cf01222c0d959c2b399142deb526de420be8236f22c71356e2a544e153c53", + "sha256:8fd7d5e0eb08cd5b87fd3df49bc193f5cfd778701f47e11d127d0afc6c39f1d1", + "sha256:923aa6d27a92bf44394f6abf7ea0500f38769d4b07f4be41cb52bd8b1123b9ed", + "sha256:97f65757e8d09870de6fd973aeddb92f85435607235d20b2dfed93405d00c85b", + "sha256:d595a9fd694fdeb061a62fbe10eb039cc1e444df81ec9bb70c7fc59ebcb1eafa", + "sha256:df051de4fd7e5e4371334e234c62ba43763f15ab605579e04c7008c05735cd82", + "sha256:f8adba2e44cde2d7618996b3fc02341f03f5bc3f2748be72dc7b063319276178", + "sha256:f8d3fdbc966aaab1d05046d0240dd94d40f2a8c62856d41eaa141ff64a79de6b", + "sha256:fe34575f2bdde76ac429ec7b570235bf0c788883e70aee90068e9981806f2490" ], "markers": "python_version >= '3.9'", - "version": "==6.33.0" + "version": "==6.33.1" }, "psutil": { "hashes": [ - "sha256:092b6350145007389c1cfe5716050f02030a05219d90057ea867d18fe8d372fc", - "sha256:146a704f224fb2ded2be3da5ac67fc32b9ea90c45b51676f9114a6ac45616967", - "sha256:295c4025b5cd880f7445e4379e6826f7307e3d488947bf9834e865e7847dc5f7", - "sha256:2a95104eae85d088891716db676f780c1404fc15d47fde48a46a5d61e8f5ad2c", - "sha256:5457cf741ca13da54624126cd5d333871b454ab133999a9a103fb097a7d7d21a", - "sha256:8fa59d7b1f01f0337f12cd10dbd76e4312a4d3c730a4fedcbdd4e5447a8b8460", - "sha256:92ebc58030fb054fa0f26c3206ef01c31c29d67aee1367e3483c16665c25c8d2", - "sha256:98629cd8567acefcc45afe2f4ba1e9290f579eacf490a917967decce4b74ee9b", - "sha256:9b4f17c5f65e44f69bd3a3406071a47b79df45cf2236d1f717970afcb526bcd3" + "sha256:0005da714eee687b4b8decd3d6cc7c6db36215c9e74e5ad2264b90c3df7d92dc", + "sha256:1068c303be3a72f8e18e412c5b2a8f6d31750fb152f9cb106b54090296c9d251", + "sha256:18349c5c24b06ac5612c0428ec2a0331c26443d259e2a0144a9b24b4395b58fa", + "sha256:19644c85dcb987e35eeeaefdc3915d059dac7bd1167cdcdbf27e0ce2df0c08c0", + "sha256:2bdbcd0e58ca14996a42adf3621a6244f1bb2e2e528886959c72cf1e326677ab", + "sha256:31d77fcedb7529f27bb3a0472bea9334349f9a04160e8e6e5020f22c59893264", + "sha256:3792983e23b69843aea49c8f5b8f115572c5ab64c153bada5270086a2123c7e7", + "sha256:3bb428f9f05c1225a558f53e30ccbad9930b11c3fc206836242de1091d3e7dd3", + "sha256:56d974e02ca2c8eb4812c3f76c30e28836fffc311d55d979f1465c1feeb2b68b", + "sha256:6c86281738d77335af7aec228328e944b30930899ea760ecf33a4dba66be5e74", + "sha256:8f33a3702e167783a9213db10ad29650ebf383946e91bc77f28a5eb083496bc9", + "sha256:95ef04cf2e5ba0ab9eaafc4a11eaae91b44f4ef5541acd2ee91d9108d00d59a7", + "sha256:ad81425efc5e75da3f39b3e636293360ad8d0b49bed7df824c79764fb4ba9b8b", + "sha256:b403da1df4d6d43973dc004d19cee3b848e998ae3154cc8097d139b77156c353", + "sha256:bc31fa00f1fbc3c3802141eede66f3a2d51d89716a194bf2cd6fc68310a19880", + "sha256:bd0d69cee829226a761e92f28140bec9a5ee9d5b4fb4b0cc589068dbfff559b1", + "sha256:c525ffa774fe4496282fb0b1187725793de3e7c6b29e41562733cae9ada151ee", + "sha256:f39c2c19fe824b47484b96f9692932248a54c43799a84282cfe58d05a6449efd", + "sha256:fac9cd332c67f4422504297889da5ab7e05fd11e3c4392140f7370f4208ded1f" ], "markers": "python_version >= '3.6'", - "version": "==7.1.1" + "version": "==7.1.3" }, "ptyprocess": { "hashes": [ @@ -1582,6 +1593,7 @@ "sha256:252be4a05f9d9185bb8c18e83764ebcfea7185076c07a7a662253af3a8c07941", "sha256:334f900ff08ce0423407af97e6c26ad5d4e3b0763645559ece6fbf3747d6a8f5", "sha256:35ad0f0378c9359b3f297299c3309778bb03b8612f987399a0333a560b43862d", + "sha256:3d600dc583260d845c7d8a6db540339dd883081925da2bd1c5cb808f720b3cd9", "sha256:3e294c5eadfb93d78b0763e859a0c16d4051fc1c5231ae8956d61cb0b5666f5a", "sha256:3e739edd001b04f654b166204fc7a9de896cf6007eaff33409ee9e50ceaff754", "sha256:44729980b6c50a5f2bfcc2668d36c569ce17f8b17bccaf470c4313dcbbf13c9d", @@ -1679,12 +1691,12 @@ }, "python-dotenv": { "hashes": [ - "sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc", - "sha256:a8a6399716257f45be6a007360200409fce5cda2661e3dec71d23dc15f6189ab" + "sha256:42667e897e16ab0d66954af0e60a9caa94f0fd4ecf3aaf6d2d260eec1aa36ad6", + "sha256:b81ee9561e9ca4004139c6cbba3a238c32b03e4894671e181b671e8cb8425d61" ], "index": "pypi", "markers": "python_version >= '3.9'", - "version": "==1.1.1" + "version": "==1.2.1" }, "python-json-logger": { "hashes": [ @@ -1938,124 +1950,124 @@ }, "rpds-py": { "hashes": [ - "sha256:03065002fd2e287725d95fbc69688e0c6daf6c6314ba38bdbaa3895418e09296", - "sha256:04c1b207ab8b581108801528d59ad80aa83bb170b35b0ddffb29c20e411acdc1", - "sha256:05cf1e74900e8da73fa08cc76c74a03345e5a3e37691d07cfe2092d7d8e27b04", - "sha256:0a403460c9dd91a7f23fc3188de6d8977f1d9603a351d5db6cf20aaea95b538d", - "sha256:0cb7203c7bc69d7c1585ebb33a2e6074492d2fc21ad28a7b9d40457ac2a51ab7", - "sha256:0d3259ea9ad8743a75a43eb7819324cdab393263c91be86e2d1901ee65c314e0", - "sha256:1571ae4292649100d743b26d5f9c63503bb1fedf538a8f29a98dce2d5ba6b4e6", - "sha256:1a4c6b05c685c0c03f80dabaeb73e74218c49deea965ca63f76a752807397207", - "sha256:1e8ee6413cfc677ce8898d9cde18cc3a60fc2ba756b0dec5b71eb6eb21c49fa1", - "sha256:1f0cfd1c69e2d14f8c892b893997fa9a60d890a0c8a603e88dca4955f26d1edd", - "sha256:23690b5827e643150cf7b49569679ec13fe9a610a15949ed48b85eb7f98f34ec", - "sha256:2374e16cc9131022e7d9a8f8d65d261d9ba55048c78f3b6e017971a4f5e6353c", - "sha256:24743a7b372e9a76171f6b69c01aedf927e8ac3e16c474d9fe20d552a8cb45c7", - "sha256:25dbade8fbf30bcc551cb352376c0ad64b067e4fc56f90e22ba70c3ce205988c", - "sha256:28ea02215f262b6d078daec0b45344c89e161eab9526b0d898221d96fdda5f27", - "sha256:2e42456917b6687215b3e606ab46aa6bca040c77af7df9a08a6dcfe8a4d10ca5", - "sha256:2e8456b6ee5527112ff2354dd9087b030e3429e43a74f480d4a5ca79d269fd85", - "sha256:3114f4db69ac5a1f32e7e4d1cbbe7c8f9cf8217f78e6e002cedf2d54c2a548ed", - "sha256:31eb671150b9c62409a888850aaa8e6533635704fe2b78335f9aaf7ff81eec4d", - "sha256:389c29045ee8bbb1627ea190b4976a310a295559eaf9f1464a1a6f2bf84dde78", - "sha256:3aa4dc0fdab4a7029ac63959a3ccf4ed605fee048ba67ce89ca3168da34a1342", - "sha256:3c03002f54cc855860bfdc3442928ffdca9081e73b5b382ed0b9e8efe6e5e205", - "sha256:46959ef2e64f9e4a41fc89aa20dbca2b85531f9a72c21099a3360f35d10b0d5a", - "sha256:48b55c1f64482f7d8bd39942f376bfdf2f6aec637ee8c805b5041e14eeb771db", - "sha256:4b0cb8a906b1a0196b863d460c0222fb8ad0f34041568da5620f9799b83ccf0b", - "sha256:4c6c4db5d73d179746951486df97fd25e92396be07fc29ee8ff9a8f5afbdfb27", - "sha256:4e27d3a5709cc2b3e013bf93679a849213c79ae0573f9b894b284b55e729e120", - "sha256:4fe0438ac4a29a520ea94c8c7f1754cdd8feb1bc490dfda1bfd990072363d527", - "sha256:5338742f6ba7a51012ea470bd4dc600a8c713c0c72adaa0977a1b1f4327d6592", - "sha256:5a7306c19b19005ad98468fcefeb7100b19c79fc23a5f24a12e06d91181193fa", - "sha256:5ae8ee156d6b586e4292491e885d41483136ab994e719a13458055bec14cf370", - "sha256:5b43c6a3726efd50f18d8120ec0551241c38785b68952d240c45ea553912ac41", - "sha256:5cfa9af45e7c1140af7321fa0bef25b386ee9faa8928c80dc3a5360971a29e8c", - "sha256:5d0145edba8abd3db0ab22b5300c99dc152f5c9021fab861be0f0544dc3cbc5f", - "sha256:5d3fd16b6dc89c73a4da0b4ac8b12a7ecc75b2864b95c9e5afed8003cb50a728", - "sha256:5ee514e0f0523db5d3fb171f397c54875dbbd69760a414dccf9d4d7ad628b5bd", - "sha256:5f3fa06d27fdcee47f07a39e02862da0100cb4982508f5ead53ec533cd5fe55e", - "sha256:66e6fa8e075b58946e76a78e69e1a124a21d9a48a5b4766d15ba5b06869d1fa1", - "sha256:6796079e5d24fdaba6d49bda28e2c47347e89834678f2bc2c1b4fc1489c0fb01", - "sha256:6897bebb118c44b38c9cb62a178e09f1593c949391b9a1a6fe777ccab5934ee7", - "sha256:6aa1bfce3f83baf00d9c5fcdbba93a3ab79958b4c7d7d1f55e7fe68c20e63912", - "sha256:6b4f28583a4f247ff60cd7bdda83db8c3f5b05a7a82ff20dd4b078571747708f", - "sha256:6e32dd207e2c4f8475257a3540ab8a93eff997abfa0a3fdb287cae0d6cd874b8", - "sha256:6f0c9266c26580e7243ad0d72fc3e01d6b33866cfab5084a6da7576bcf1c4f72", - "sha256:735f8495a13159ce6a0d533f01e8674cec0c57038c920495f87dcb20b3ddb48a", - "sha256:76500820c2af232435cbe215e3324c75b950a027134e044423f59f5b9a1ba515", - "sha256:7a4e59c90d9c27c561eb3160323634a9ff50b04e4f7820600a2beb0ac90db578", - "sha256:7a52a5169c664dfb495882adc75c304ae1d50df552fbd68e100fdc719dee4ff9", - "sha256:7a69df082db13c7070f7b8b1f155fa9e687f1d6aefb7b0e3f7231653b79a067b", - "sha256:7b0f9dceb221792b3ee6acb5438eb1f02b0cb2c247796a72b016dcc92c6de829", - "sha256:7b14b0c680286958817c22d76fcbca4800ddacef6f678f3a7c79a1fe7067fe37", - "sha256:7b6013db815417eeb56b2d9d7324e64fcd4fa289caeee6e7a78b2e11fc9b438a", - "sha256:7b7d9d83c942855e4fdcfa75d4f96f6b9e272d42fffcb72cd4bb2577db2e2907", - "sha256:8014045a15b4d2b3476f0a287fcc93d4f823472d7d1308d47884ecac9e612be3", - "sha256:8455933b4bcd6e83fde3fefc987a023389c4b13f9a58c8d23e4b3f6d13f78c84", - "sha256:85beb8b3f45e4e32f6802fb6cd6b17f615ef6c6a52f265371fb916fae02814aa", - "sha256:8a358a32dd3ae50e933347889b6af9a1bdf207ba5d1a3f34e1a38cd3540e6733", - "sha256:8aa23b6f0fc59b85b4c7d89ba2965af274346f738e8d9fc2455763602e62fd5f", - "sha256:8d252db6b1a78d0a3928b6190156042d54c93660ce4d98290d7b16b5296fb7cc", - "sha256:8f60c7ea34e78c199acd0d3cda37a99be2c861dd2b8cf67399784f70c9f8e57d", - "sha256:961ca621ff10d198bbe6ba4957decca61aa2a0c56695384c1d6b79bf61436df5", - "sha256:9a5690671cd672a45aa8616d7374fdf334a1b9c04a0cac3c854b1136e92374fe", - "sha256:9a7548b345f66f6695943b4ef6afe33ccd3f1b638bd9afd0f730dd255c249c9e", - "sha256:9f1d92ecea4fa12f978a367c32a5375a1982834649cdb96539dcdc12e609ab1a", - "sha256:a2036d09b363aa36695d1cc1a97b36865597f4478470b0697b5ee9403f4fe399", - "sha256:a3b695a8fa799dd2cfdb4804b37096c5f6dba1ac7f48a7fbf6d0485bcd060316", - "sha256:a410542d61fc54710f750d3764380b53bf09e8c4edbf2f9141a82aa774a04f7c", - "sha256:a6fe887c2c5c59413353b7c0caff25d0e566623501ccfff88957fa438a69377d", - "sha256:a805e9b3973f7e27f7cab63a6b4f61d90f2e5557cff73b6e97cd5b8540276d3d", - "sha256:abd4df20485a0983e2ca334a216249b6186d6e3c1627e106651943dbdb791aea", - "sha256:ac9f83e7b326a3f9ec3ef84cda98fb0a74c7159f33e692032233046e7fd15da2", - "sha256:acbe5e8b1026c0c580d0321c8aae4b0a1e1676861d48d6e8c6586625055b606a", - "sha256:ad50614a02c8c2962feebe6012b52f9802deec4263946cddea37aaf28dd25a66", - "sha256:ada7754a10faacd4f26067e62de52d6af93b6d9542f0df73c57b9771eb3ba9c4", - "sha256:adc8aa88486857d2b35d75f0640b949759f79dc105f50aa2c27816b2e0dd749f", - "sha256:b1b553dd06e875249fd43efd727785efb57a53180e0fde321468222eabbeaafa", - "sha256:b1cde22f2c30ebb049a9e74c5374994157b9b70a16147d332f89c99c5960737a", - "sha256:b3072b16904d0b5572a15eb9d31c1954e0d3227a585fc1351aa9878729099d6c", - "sha256:b670c30fd87a6aec281c3c9896d3bae4b205fd75d79d06dc87c2503717e46092", - "sha256:b8e1e9be4fa6305a16be628959188e4fd5cd6f1b0e724d63c6d8b2a8adf74ea6", - "sha256:b9699fa7990368b22032baf2b2dce1f634388e4ffc03dfefaaac79f4695edc95", - "sha256:b9b06fe1a75e05e0713f06ea0c89ecb6452210fd60e2f1b6ddc1067b990e08d9", - "sha256:bbdc5640900a7dbf9dd707fe6388972f5bbd883633eb68b76591044cfe346f7e", - "sha256:bcf1d210dfee61a6c86551d67ee1031899c0fdbae88b2d44a569995d43797712", - "sha256:bd3bbba5def70b16cd1c1d7255666aad3b290fbf8d0fe7f9f91abafb73611a91", - "sha256:beb880a9ca0a117415f241f66d56025c02037f7c4efc6fe59b5b8454f1eaa50d", - "sha256:c2a34fd26588949e1e7977cfcbb17a9a42c948c100cab890c6d8d823f0586457", - "sha256:c9a40040aa388b037eb39416710fbcce9443498d2eaab0b9b45ae988b53f5c67", - "sha256:cf128350d384b777da0e68796afdcebc2e9f63f0e9f242217754e647f6d32491", - "sha256:cf681ac76a60b667106141e11a92a3330890257e6f559ca995fbb5265160b56e", - "sha256:d15431e334fba488b081d47f30f091e5d03c18527c325386091f31718952fe08", - "sha256:d2412be8d00a1b895f8ad827cc2116455196e20ed994bb704bf138fe91a42724", - "sha256:d61b355c3275acb825f8777d6c4505f42b5007e357af500939d4a35b19177259", - "sha256:d678e91b610c29c4b3d52a2c148b641df2b4676ffe47c59f6388d58b99cdc424", - "sha256:d7366b6553cdc805abcc512b849a519167db8f5e5c3472010cd1228b224265cb", - "sha256:dcdcb890b3ada98a03f9f2bb108489cdc7580176cb73b4f2d789e9a1dac1d472", - "sha256:dd8d86b5d29d1b74100982424ba53e56033dc47720a6de9ba0259cf81d7cecaa", - "sha256:e0a0311caedc8069d68fc2bf4c9019b58a2d5ce3cd7cb656c845f1615b577e1e", - "sha256:e1460ebde1bcf6d496d80b191d854adedcc619f84ff17dc1c6d550f58c9efbba", - "sha256:e3eb248f2feba84c692579257a043a7699e28a77d86c77b032c1d9fbb3f0219c", - "sha256:e5bbc701eff140ba0e872691d573b3d5d30059ea26e5785acba9132d10c8c31d", - "sha256:e5d9b86aa501fed9862a443c5c3116f6ead8bc9296185f369277c42542bd646b", - "sha256:e5deca01b271492553fdb6c7fd974659dce736a15bae5dad7ab8b93555bceb28", - "sha256:e80848a71c78aa328fefaba9c244d588a342c8e03bda518447b624ea64d1ff56", - "sha256:e819e0e37a44a78e1383bf1970076e2ccc4dc8c2bbaa2f9bd1dc987e9afff628", - "sha256:e9e184408a0297086f880556b6168fa927d677716f83d3472ea333b42171ee3b", - "sha256:edd267266a9b0448f33dc465a97cfc5d467594b600fe28e7fa2f36450e03053a", - "sha256:efd489fec7c311dae25e94fe7eeda4b3d06be71c68f2cf2e8ef990ffcd2cd7e8", - "sha256:f0b2044fdddeea5b05df832e50d2a06fe61023acb44d76978e1b060206a8a476", - "sha256:f274f56a926ba2dc02976ca5b11c32855cbd5925534e57cfe1fda64e04d1add2", - "sha256:f296ea3054e11fc58ad42e850e8b75c62d9a93a9f981ad04b2e5ae7d2186ff9c", - "sha256:f4794c6c3fbe8f9ac87699b131a1f26e7b4abcf6d828da46a3a52648c7930eba", - "sha256:f586db2e209d54fe177e58e0bc4946bea5fb0102f150b1b2f13de03e1f0976f8", - "sha256:f5e7101145427087e493b9c9b959da68d357c28c562792300dd21a095118ed16", - "sha256:f9174471d6920cbc5e82a7822de8dfd4dcea86eb828b04fc8c6519a77b0ee51e" + "sha256:00e56b12d2199ca96068057e1ae7f9998ab6e99cda82431afafd32f3ec98cca9", + "sha256:0248b19405422573621172ab8e3a1f29141362d13d9f72bafa2e28ea0cdca5a2", + "sha256:05a2bd42768ea988294ca328206efbcc66e220d2d9b7836ee5712c07ad6340ea", + "sha256:070befbb868f257d24c3bb350dbd6e2f645e83731f31264b19d7231dd5c396c7", + "sha256:0a8896986efaa243ab713c69e6491a4138410f0fe36f2f4c71e18bd5501e8014", + "sha256:0ea962671af5cb9a260489e311fa22b2e97103e3f9f0caaea6f81390af96a9ed", + "sha256:115f48170fd4296a33938d8c11f697f5f26e0472e43d28f35624764173a60e4d", + "sha256:12597d11d97b8f7e376c88929a6e17acb980e234547c92992f9f7c058f1a7310", + "sha256:1585648d0760b88292eecab5181f5651111a69d90eff35d6b78aa32998886a61", + "sha256:16e9da2bda9eb17ea318b4c335ec9ac1818e88922cbe03a5743ea0da9ecf74fb", + "sha256:1a409b0310a566bfd1be82119891fefbdce615ccc8aa558aff7835c27988cbef", + "sha256:1c3c3e8101bb06e337c88eb0c0ede3187131f19d97d43ea0e1c5407ea74c0cbf", + "sha256:1d24564a700ef41480a984c5ebed62b74e6ce5860429b98b1fede76049e953e6", + "sha256:1de2345af363d25696969befc0c1688a6cb5e8b1d32b515ef84fc245c6cddba3", + "sha256:1ea59b23ea931d494459c8338056fe7d93458c0bf3ecc061cd03916505369d55", + "sha256:2023473f444752f0f82a58dfcbee040d0a1b3d1b3c2ec40e884bd25db6d117d2", + "sha256:20c51ae86a0bb9accc9ad4e6cdeec58d5ebb7f1b09dd4466331fc65e1766aae7", + "sha256:24a16cb7163933906c62c272de20ea3c228e4542c8c45c1d7dc2b9913e17369a", + "sha256:24a7231493e3c4a4b30138b50cca089a598e52c34cf60b2f35cebf62f274fdea", + "sha256:2549d833abdf8275c901313b9e8ff8fba57e50f6a495035a2a4e30621a2f7cc4", + "sha256:28de03cf48b8a9e6ec10318f2197b83946ed91e2891f651a109611be4106ac4b", + "sha256:28fd300326dd21198f311534bdb6d7e989dd09b3418b3a91d54a0f384c700967", + "sha256:295ce5ac7f0cf69a651ea75c8f76d02a31f98e5698e82a50a5f4d4982fbbae3b", + "sha256:2a21deb8e0d1571508c6491ce5ea5e25669b1dd4adf1c9d64b6314842f708b5d", + "sha256:2aba991e041d031c7939e1358f583ae405a7bf04804ca806b97a5c0e0af1ea5e", + "sha256:2b8e54d6e61f3ecd3abe032065ce83ea63417a24f437e4a3d73d2f85ce7b7cfe", + "sha256:2d6fb2ad1c36f91c4646989811e84b1ea5e0c3cf9690b826b6e32b7965853a63", + "sha256:33ca7bdfedd83339ca55da3a5e1527ee5870d4b8369456b5777b197756f3ca22", + "sha256:37d94eadf764d16b9a04307f2ab1d7af6dc28774bbe0535c9323101e14877b4c", + "sha256:3897924d3f9a0361472d884051f9a2460358f9a45b1d85a39a158d2f8f1ad71c", + "sha256:3919a3bbecee589300ed25000b6944174e07cd20db70552159207b3f4bbb45b8", + "sha256:394d27e4453d3b4d82bb85665dc1fcf4b0badc30fc84282defed71643b50e1a1", + "sha256:3fbd4e9aebf110473a420dea85a238b254cf8a15acb04b22a5a6b5ce8925b760", + "sha256:3fd2164d73812026ce970d44c3ebd51e019d2a26a4425a5dcbdfa93a34abc383", + "sha256:40f65470919dc189c833e86b2c4bd21bd355f98436a2cef9e0a9a92aebc8e57e", + "sha256:4448dad428f28a6a767c3e3b80cde3446a22a0efbddaa2360f4bb4dc836d0688", + "sha256:44a91e0ab77bdc0004b43261a4b8cd6d6b451e8d443754cfda830002b5745b32", + "sha256:453783477aa4f2d9104c4b59b08c871431647cb7af51b549bbf2d9eb9c827756", + "sha256:4a097b7f7f7274164566ae90a221fd725363c0e9d243e2e9ed43d195ccc5495c", + "sha256:4aa195e5804d32c682e453b34474f411ca108e4291c6a0f824ebdc30a91c973c", + "sha256:4ae4b88c6617e1b9e5038ab3fccd7bac0842fdda2b703117b2aa99bc85379113", + "sha256:521807963971a23996ddaf764c682b3e46459b3c58ccd79fefbe16718db43154", + "sha256:534dc9df211387547267ccdb42253aa30527482acb38dd9b21c5c115d66a96d2", + "sha256:539eb77eb043afcc45314d1be09ea6d6cafb3addc73e0547c171c6d636957f60", + "sha256:55d827b2ae95425d3be9bc9a5838b6c29d664924f98146557f7715e331d06df8", + "sha256:56838e1cd9174dc23c5691ee29f1d1be9eab357f27efef6bded1328b23e1ced2", + "sha256:5a572911cd053137bbff8e3a52d31c5d2dba51d3a67ad902629c70185f3f2181", + "sha256:5c9546cfdd5d45e562cc0444b6dddc191e625c62e866bf567a2c69487c7ad28a", + "sha256:5cc58aac218826d054c7da7f95821eba94125d88be673ff44267bb89d12a5866", + "sha256:6410e66f02803600edb0b1889541f4b5cc298a5ccda0ad789cc50ef23b54813e", + "sha256:66786c3fb1d8de416a7fa8e1cb1ec6ba0a745b2b0eee42f9b7daa26f1a495545", + "sha256:6e97846e9800a5d0fe7be4d008f0c93d0feeb2700da7b1f7528dabafb31dfadb", + "sha256:7033c1010b1f57bb44d8067e8c25aa6fa2e944dbf46ccc8c92b25043839c3fd2", + "sha256:715b67eac317bf1c7657508170a3e011a1ea6ccb1c9d5f296e20ba14196be6b3", + "sha256:72fdfd5ff8992e4636621826371e3ac5f3e3b8323e9d0e48378e9c13c3dac9d0", + "sha256:76054d540061eda273274f3d13a21a4abdde90e13eaefdc205db37c05230efce", + "sha256:76fe96632d53f3bf0ea31ede2f53bbe3540cc2736d4aec3b3801b0458499ef3a", + "sha256:7971bdb7bf4ee0f7e6f67fa4c7fbc6019d9850cc977d126904392d363f6f8318", + "sha256:799156ef1f3529ed82c36eb012b5d7a4cf4b6ef556dd7cc192148991d07206ae", + "sha256:7cdc0490374e31cedefefaa1520d5fe38e82fde8748cbc926e7284574c714d6b", + "sha256:7d9128ec9d8cecda6f044001fde4fb71ea7c24325336612ef8179091eb9596b9", + "sha256:7f437026dbbc3f08c99cc41a5b2570c6e1a1ddbe48ab19a9b814254128d4ea7a", + "sha256:80fdf53d36e6c72819993e35d1ebeeb8e8fc688d0c6c2b391b55e335b3afba5a", + "sha256:8238d1d310283e87376c12f658b61e1ee23a14c0e54c7c0ce953efdbdc72deed", + "sha256:89ca2e673ddd5bde9b386da9a0aac0cab0e76f40c8f0aaf0d6311b6bbf2aa311", + "sha256:8ae33ad9ce580c7a47452c3b3f7d8a9095ef6208e0a0c7e4e2384f9fc5bf8212", + "sha256:8c5a8ecaa44ce2d8d9d20a68a2483a74c07f05d72e94a4dff88906c8807e77b0", + "sha256:8e5bb73ffc029820f4348e9b66b3027493ae00bca6629129cd433fd7a76308ee", + "sha256:90f30d15f45048448b8da21c41703b31c61119c06c216a1bf8c245812a0f0c17", + "sha256:923248a56dd8d158389a28934f6f69ebf89f218ef96a6b216a9be6861804d3f4", + "sha256:9459a33f077130dbb2c7c3cea72ee9932271fb3126404ba2a2661e4fe9eb7b79", + "sha256:97c817863ffc397f1e6a6e9d2d89fe5408c0a9922dac0329672fb0f35c867ea5", + "sha256:9b9c764a11fd637e0322a488560533112837f5334ffeb48b1be20f6d98a7b437", + "sha256:9ba8028597e824854f0f1733d8b964e914ae3003b22a10c2c664cb6927e0feb9", + "sha256:9efe71687d6427737a0a2de9ca1c0a216510e6cd08925c44162be23ed7bed2d5", + "sha256:9f84c549746a5be3bc7415830747a3a0312573afc9f95785eb35228bb17742ec", + "sha256:a0891cfd8db43e085c0ab93ab7e9b0c8fee84780d436d3b266b113e51e79f954", + "sha256:a110e14508fd26fd2e472bb541f37c209409876ba601cf57e739e87d8a53cf95", + "sha256:a5d9da3ff5af1ca1249b1adb8ef0573b94c76e6ae880ba1852f033bf429d4588", + "sha256:a738f2da2f565989401bd6fd0b15990a4d1523c6d7fe83f300b7e7d17212feca", + "sha256:acd82a9e39082dc5f4492d15a6b6c8599aa21db5c35aaf7d6889aea16502c07d", + "sha256:ad7bd570be92695d89285a4b373006930715b78d96449f686af422debb4d3949", + "sha256:b016eddf00dca7944721bf0cd85b6af7f6c4efaf83ee0b37c4133bd39757a8c7", + "sha256:b1581fcde18fcdf42ea2403a16a6b646f8eb1e58d7f90a0ce693da441f76942e", + "sha256:b58f5c77f1af888b5fd1876c9a0d9858f6f88a39c9dd7c073a88e57e577da66d", + "sha256:b5f6134faf54b3cb83375db0f113506f8b7770785be1f95a631e7e2892101977", + "sha256:b9cf2359a4fca87cfb6801fae83a76aedf66ee1254a7a151f1341632acf67f1b", + "sha256:ba5e1aeaf8dd6d8f6caba1f5539cddda87d511331714b7b5fc908b6cfc3636b7", + "sha256:bb78b3a0d31ac1bde132c67015a809948db751cb4e92cdb3f0b242e430b6ed0d", + "sha256:bdb67151ea81fcf02d8f494703fb728d4d34d24556cbff5f417d74f6f5792e7c", + "sha256:c07d107b7316088f1ac0177a7661ca0c6670d443f6fe72e836069025e6266761", + "sha256:c4695dd224212f6105db7ea62197144230b808d6b2bba52238906a2762f1d1e7", + "sha256:c5523b0009e7c3c1263471b69d8da1c7d41b3ecb4cb62ef72be206b92040a950", + "sha256:c661132ab2fb4eeede2ef69670fd60da5235209874d001a98f1542f31f2a8a94", + "sha256:d37812c3da8e06f2bb35b3cf10e4a7b68e776a706c13058997238762b4e07f4f", + "sha256:d456e64724a075441e4ed648d7f154dc62e9aabff29bcdf723d0c00e9e1d352f", + "sha256:d472cf73efe5726a067dce63eebe8215b14beabea7c12606fd9994267b3cfe2b", + "sha256:d583d4403bcbf10cffc3ab5cee23d7643fcc960dff85973fd3c2d6c86e8dbb0c", + "sha256:de73e40ebc04dd5d9556f50180395322193a78ec247e637e741c1b954810f295", + "sha256:def48ff59f181130f1a2cb7c517d16328efac3ec03951cca40c1dc2049747e83", + "sha256:e6596b93c010d386ae46c9fba9bfc9fc5965fa8228edeac51576299182c2e31c", + "sha256:e71136fd0612556b35c575dc2726ae04a1669e6a6c378f2240312cf5d1a2ab10", + "sha256:e7fa2ccc312bbd91e43aa5e0869e46bc03278a3dddb8d58833150a18b0f0283a", + "sha256:ea7173df5d86f625f8dde6d5929629ad811ed8decda3b60ae603903839ac9ac0", + "sha256:f3b1b87a237cb2dba4db18bcfaaa44ba4cd5936b91121b62292ff21df577fc43", + "sha256:f475f103488312e9bd4000bc890a95955a07b2d0b6e8884aef4be56132adbbf1", + "sha256:f49196aec7c4b406495f60e6f947ad71f317a765f956d74bbd83996b9edc0352", + "sha256:f49d41559cebd608042fdcf54ba597a4a7555b49ad5c1c0c03e0af82692661cd", + "sha256:f7728653900035fb7b8d06e1e5900545d8088efc9d5d4545782da7df03ec803f", + "sha256:f9f436aee28d13b9ad2c764fc273e0457e37c2e61529a07b928346b219fcde3b", + "sha256:fc31a07ed352e5462d3ee1b22e89285f4ce97d5266f6d1169da1142e78045626", + "sha256:fc935f6b20b0c9f919a8ff024739174522abd331978f750a74bb68abd117bd19", + "sha256:fcae1770b401167f8b9e1e3f566562e6966ffa9ce63639916248a9e25fa8a244", + "sha256:fd7951c964069039acc9d67a8ff1f0a7f34845ae180ca542b17dc1456b1f1808", + "sha256:fe55fe686908f50154d1dc599232016e50c243b438c3b7432f24e2895b0e5359" ], "markers": "python_version >= '3.10'", - "version": "==0.28.0" + "version": "==0.29.0" }, "rsa": { "hashes": [ @@ -2236,11 +2248,11 @@ }, "webcolors": { "hashes": [ - "sha256:515291393b4cdf0eb19c155749a096f779f7d909f7cceea072791cb9095b92e9", - "sha256:ecb3d768f32202af770477b8b65f318fa4f566c22948673a977b00d589dd80f6" + "sha256:032c727334856fc0b968f63daa252a1ac93d33db2f5267756623c210e57a4f1d", + "sha256:62abae86504f66d0f6364c2a8520de4a0c47b80c03fc3a5f1815fedbef7c19bf" ], - "markers": "python_version >= '3.9'", - "version": "==24.11.1" + "markers": "python_version >= '3.10'", + "version": "==25.10.0" }, "webencodings": { "hashes": [ @@ -2340,43 +2352,47 @@ "develop": { "asttokens": { "hashes": [ - "sha256:0dcd8baa8d62b0c1d118b399b2ddba3c4aff271d0d7a9e0d4c1681c79035bbc7", - "sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2" + "sha256:15a3ebc0f43c2d0a50eeafea25e19046c68398e487b9f1f5b517f7c0f40f976a", + "sha256:71a4ee5de0bde6a31d64f6b13f2293ac190344478f081c3d1bccfcf5eacb0cb7" ], "markers": "python_version >= '3.8'", - "version": "==3.0.0" + "version": "==3.0.1" }, "black": { "extras": [ "jupyter" ], "hashes": [ - "sha256:0172a012f725b792c358d57fe7b6b6e8e67375dd157f64fa7a3097b3ed3e2175", - "sha256:0474bca9a0dd1b51791fcc507a4e02078a1c63f6d4e4ae5544b9848c7adfb619", - "sha256:154b06d618233fe468236ba1f0e40823d4eb08b26f5e9261526fde34916b9140", - "sha256:1b9dc70c21ef8b43248f1d86aedd2aaf75ae110b958a7909ad8463c4aa0880b0", - "sha256:2ab0ce111ef026790e9b13bd216fa7bc48edd934ffc4cbf78808b235793cbc92", - "sha256:3bec74ee60f8dfef564b573a96b8930f7b6a538e846123d5ad77ba14a8d7a64f", - "sha256:456386fe87bad41b806d53c062e2974615825c7a52159cde7ccaeb0695fa28fa", - "sha256:474b34c1342cdc157d307b56c4c65bce916480c4a8f6551fdc6bf9b486a7c4ae", - "sha256:77e7060a00c5ec4b3367c55f39cf9b06e68965a4f2e61cecacd6d0d9b7ec945a", - "sha256:846d58e3ce7879ec1ffe816bb9df6d006cd9590515ed5d17db14e17666b2b357", - "sha256:8e46eecf65a095fa62e53245ae2795c90bdecabd53b50c448d0a8bcd0d2e74c4", - "sha256:9101ee58ddc2442199a25cb648d46ba22cd580b00ca4b44234a324e3ec7a0f7e", - "sha256:a16b14a44c1af60a210d8da28e108e13e75a284bf21a9afa6b4571f96ab8bb9d", - "sha256:aaf319612536d502fdd0e88ce52d8f1352b2c0a955cc2798f79eeca9d3af0608", - "sha256:b756fc75871cb1bcac5499552d771822fd9db5a2bb8db2a7247936ca48f39831", - "sha256:c0372a93e16b3954208417bfe448e09b0de5cc721d521866cd9e0acac3c04a1f", - "sha256:ce41ed2614b706fd55fd0b4a6909d06b5bab344ffbfadc6ef34ae50adba3d4f7", - "sha256:d119957b37cc641596063cd7db2656c5be3752ac17877017b2ffcdb9dfc4d2b1", - "sha256:e3c1f4cd5e93842774d9ee4ef6cd8d17790e65f44f7cdbaab5f2cf8ccf22a823", - "sha256:e593466de7b998374ea2585a471ba90553283fb9beefcfa430d84a2651ed5933", - "sha256:ef69351df3c84485a8beb6f7b8f9721e2009e20ef80a8d619e2d1788b7816d47", - "sha256:f96b6726d690c96c60ba682955199f8c39abc1ae0c3a494a9c62c0184049a713" + "sha256:0a1d40348b6621cc20d3d7530a5b8d67e9714906dfd7346338249ad9c6cedf2b", + "sha256:0c0f7c461df55cf32929b002335883946a4893d759f2df343389c4396f3b6b37", + "sha256:1032639c90208c15711334d681de2e24821af0575573db2810b0763bcd62e0f0", + "sha256:35690a383f22dd3e468c85dc4b915217f87667ad9cce781d7b42678ce63c4170", + "sha256:43945853a31099c7c0ff8dface53b4de56c41294fa6783c0441a8b1d9bf668bc", + "sha256:51c65d7d60bb25429ea2bf0731c32b2a2442eb4bd3b2afcb47830f0b13e58bfd", + "sha256:5bd4a22a0b37401c8e492e994bce79e614f91b14d9ea911f44f36e262195fdda", + "sha256:6cb2d54a39e0ef021d6c5eef442e10fd71fcb491be6413d083a320ee768329dd", + "sha256:6cced12b747c4c76bc09b4db057c319d8545307266f41aaee665540bc0e04e96", + "sha256:7eebd4744dfe92ef1ee349dc532defbf012a88b087bb7ddd688ff59a447b080e", + "sha256:80e7486ad3535636657aa180ad32a7d67d7c273a80e12f1b4bfa0823d54e8fac", + "sha256:895571922a35434a9d8ca67ef926da6bc9ad464522a5fe0db99b394ef1c0675a", + "sha256:92285c37b93a1698dcbc34581867b480f1ba3a7b92acf1fe0467b04d7a4da0dc", + "sha256:936c4dd07669269f40b497440159a221ee435e3fddcf668e0c05244a9be71993", + "sha256:9815ccee1e55717fe9a4b924cae1646ef7f54e0f990da39a34fc7b264fcf80a2", + "sha256:9a323ac32f5dc75ce7470501b887250be5005a01602e931a15e45593f70f6e08", + "sha256:a3bb5ce32daa9ff0605d73b6f19da0b0e6c1f8f2d75594db539fdfed722f2b06", + "sha256:aa211411e94fdf86519996b7f5f05e71ba34835d8f0c0f03c00a26271da02664", + "sha256:ae263af2f496940438e5be1a0c1020e13b09154f3af4df0835ea7f9fe7bfa409", + "sha256:cb4f4b65d717062191bdec8e4a442539a8ea065e6af1c4f4d36f0cdb5f71e170", + "sha256:d81a44cbc7e4f73a9d6ae449ec2317ad81512d1e7dce7d57f6333fd6259737bc", + "sha256:dae49ef7369c6caa1a1833fd5efb7c3024bb7e4499bf64833f65ad27791b1545", + "sha256:e3f562da087791e96cefcd9dda058380a442ab322a02e222add53736451f604b", + "sha256:ec311e22458eec32a807f029b2646f661e6859c3f61bc6d9ffb67958779f392e", + "sha256:f42c0ea7f59994490f4dccd64e6b2dd49ac57c7c84f38b8faab50f8759db245c", + "sha256:f9786c24d8e9bd5f20dc7a7f0cdd742644656987f6ea6947629306f937726c03" ], "index": "pypi", "markers": "python_version >= '3.9'", - "version": "==25.9.0" + "version": "==25.11.0" }, "cfgv": { "hashes": [ @@ -2388,11 +2404,11 @@ }, "click": { "hashes": [ - "sha256:9b9f285302c6e3064f4330c05f05b81945b2a39544279343e6e7c5f27a9baddc", - "sha256:e7b8232224eba16f4ebe410c25ced9f7875cb5f3263ffc93cc3e8da705e229c4" + "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a", + "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6" ], "markers": "python_version >= '3.10'", - "version": "==8.3.0" + "version": "==8.3.1" }, "decorator": { "hashes": [ @@ -2444,11 +2460,11 @@ }, "ipython": { "hashes": [ - "sha256:5603d6d5d356378be5043e69441a072b50a5b33b4503428c77b04cb8ce7bc731", - "sha256:5f77efafc886d2f023442479b8149e7d86547ad0a979e9da9f045d252f648196" + "sha256:5f6de88c905a566c6a9d6c400a8fed54a638e1f7543d17aae2551133216b1e4e", + "sha256:bce8ac85eb9521adc94e1845b4c03d88365fd6ac2f4908ec4ed1eb1b0a065f9f" ], "markers": "python_version >= '3.11'", - "version": "==9.6.0" + "version": "==9.7.0" }, "ipython-pygments-lexers": { "hashes": [ @@ -2549,12 +2565,12 @@ }, "pre-commit": { "hashes": [ - "sha256:2b0747ad7e6e967169136edffee14c16e148a778a54e4f967921aa1ebf2308d8", - "sha256:499fe450cc9d42e9d58e606262795ecb64dd05438943c62b66f6a8673da30b16" + "sha256:b35ea52957cbf83dcc5d8ee636cbead8624e3a15fbfa61a370e42158ac8a5813", + "sha256:f0233ebab440e9f17cabbb558706eb173d19ace965c68cdce2c081042b4fab15" ], "index": "pypi", - "markers": "python_version >= '3.9'", - "version": "==4.3.0" + "markers": "python_version >= '3.10'", + "version": "==4.4.0" }, "prompt-toolkit": { "hashes": [ @@ -2605,11 +2621,11 @@ }, "pytokens": { "hashes": [ - "sha256:532d6421364e5869ea57a9523bf385f02586d4662acbcc0342afd69511b4dd43", - "sha256:74d4b318c67f4295c13782ddd9abcb7e297ec5630ad060eb90abf7ebbefe59f8" + "sha256:2f932b14ed08de5fcf0b391ace2642f858f1394c0857202959000b68ed7a458a", + "sha256:95b2b5eaf832e469d141a378872480ede3f251a5a5041b8ec6e581d3ac71bbf3" ], "markers": "python_version >= '3.8'", - "version": "==0.2.0" + "version": "==0.3.0" }, "pyyaml": { "hashes": [ @@ -2716,11 +2732,11 @@ }, "virtualenv": { "hashes": [ - "sha256:4f1a845d131133bdff10590489610c98c168ff99dc75d6c96853801f7f67af44", - "sha256:63d106565078d8c8d0b206d48080f938a8b25361e19432d2c9db40d2899c810a" + "sha256:643d3914d73d3eeb0c552cbb12d7e82adf0e504dbf86a3182f8771a153a1971c", + "sha256:c21c9cede36c9753eeade68ba7d523529f228a403463376cf821eaae2b650f1b" ], "markers": "python_version >= '3.8'", - "version": "==20.35.3" + "version": "==20.35.4" }, "wcwidth": { "hashes": [ diff --git a/scripts/1-fetch/zenodo_fetch.py b/scripts/1-fetch/zenodo_fetch.py new file mode 100755 index 00000000..6a339433 --- /dev/null +++ b/scripts/1-fetch/zenodo_fetch.py @@ -0,0 +1,616 @@ +#!/usr/bin/env python +""" +Fetch Zenodo records with license information using REST API and generate +count reports. + +This implementation uses Zenodo's REST API instead of OAI-PMH for more reliable +license detection. Benefits include: +- Structured license data (metadata.license.id) +- Clear separation of access rights +- JSON parsing +- Standardized license identifiers +""" +# Standard library +import argparse +import csv +import json +import os +import sys +import textwrap +import time +import traceback +from collections import Counter, defaultdict +from datetime import datetime + +# Third-party +import requests +from pygments import highlight +from pygments.formatters import TerminalFormatter +from pygments.lexers import PythonTracebackLexer +from requests.adapters import HTTPAdapter +from urllib3.util.retry import Retry + +# Add parent directory so shared can be imported +sys.path.append(os.path.join(os.path.dirname(__file__), "..")) + +# First-party/Local +import shared # noqa: E402 + +# Setup +LOGGER, PATHS = shared.setup(__file__) + +# Constants +# Implementation choice: set to capture comprehensive CC license data +DEFAULT_FETCH_LIMIT = ( + 100000 # Increased to capture more CC licenses from 5.5M+ records +) +# API limitation: Zenodo supports 25 records per request for unauthenticated calls +MAX_RECORDS_PER_REQUEST = 25 +ZENODO_API_BASE_URL = "https://zenodo.org/api/records" + +# CSV Headers +HEADER_COUNT = ["LICENSE_TYPE", "COUNT"] +HEADER_LANGUAGE = ["LICENSE_TYPE", "LANGUAGE", "COUNT"] +HEADER_TYPE = ["LICENSE_TYPE", "RESOURCE_TYPE", "COUNT"] +HEADER_YEAR = ["LICENSE_TYPE", "YEAR", "COUNT"] + +# CC License mapping for Zenodo API +cc_license_mapping = { + "cc-by": "CC BY 4.0", + "cc-by-sa": "CC BY-SA 4.0", + "cc-by-nc": "CC BY-NC 4.0", + "cc-by-nd": "CC BY-ND 4.0", + "cc-by-nc-sa": "CC BY-NC-SA 4.0", + "cc-by-nc-nd": "CC BY-NC-ND 4.0", +} + + +def parse_arguments(): + """Parse command-line options, returns parsed argument namespace.""" + LOGGER.info("Parsing command-line options") + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument( + "--quarter", + default=os.path.basename(PATHS["data_quarter"]), + help="Data quarter in format YYYYQx", + ) + parser.add_argument( + "--fetch-limit", + type=int, + default=DEFAULT_FETCH_LIMIT, + help=f"Total records to fetch (default: {DEFAULT_FETCH_LIMIT})", + ) + parser.add_argument( + "--dates-back", + type=int, + help="Fetch records from N years back to present " + "(e.g., --dates-back 5 for last 5 years)", + ) + parser.add_argument( + "--enable-save", + action="store_true", + help="Enable saving results (default: False)", + ) + parser.add_argument( + "--enable-git", + action="store_true", + help="Enable git actions (default: False)", + ) + return parser.parse_args() + + +def setup_session(): + """Setup requests session with retry strategy.""" + session = requests.Session() + session.headers.update({"User-Agent": shared.USER_AGENT}) + retry_strategy = Retry( + total=3, + backoff_factor=2, + status_forcelist=shared.STATUS_FORCELIST, + ) + adapter = HTTPAdapter(max_retries=retry_strategy) + session.mount("https://", adapter) + return session + + +def classify_resource_type(type_text): + """Classify resource type using Zenodo's detailed taxonomy with names.""" + if not type_text: + return "Unknown" + + text = type_text.lower() + + # Alphabetical order by return value + if ( + "publication-annotationcollection" in text + or "annotation collection" in text + ): + return "Annotation Collection" + elif "publication-book" in text or "book" in text: + return "Book" + elif "publication-section" in text or "book chapter" in text: + return "Book Chapter" + elif ( + "software-computationalnotebook" in text + or "computational notebook" in text + ): + return "Computational Notebook" + elif "publication-conferencepaper" in text or "conference paper" in text: + return "Conference Paper" + elif ( + "publication-conferenceproceeding" in text + or "conference proceeding" in text + ): + return "Conference Proceeding" + elif "publication-datapaper" in text or "data paper" in text: + return "Data Paper" + elif "dataset" in text: + return "Dataset" + elif "image-diagram" in text or "diagram" in text: + return "Diagram" + elif "publication-dissertation" in text or "dissertation" in text: + return "Dissertation" + elif "image-drawing" in text or "drawing" in text: + return "Drawing" + elif "event" in text: + return "Event" + elif "image-figure" in text or "figure" in text: + return "Figure" + elif "image" in text: + return "Image" + elif "publication-journal" in text or "journal" in text: + return "Journal" + elif "publication-article" in text or "journal article" in text: + return "Journal Article" + elif "lesson" in text: + return "Lesson" + elif "model" in text: + return "Model" + elif "other" in text: + return "Other" + elif "image-other" in text or ("image" in text and "other" in text): + return "Other Image" + elif "publication-other" in text or ( + "publication" in text and "other" in text + ): + return "Other Publication" + elif ( + "publication-datamanagementplan" in text + or "output management plan" in text + ): + return "Output Management Plan" + elif "publication-patent" in text or "patent" in text: + return "Patent" + elif "publication-peerreview" in text or "peer review" in text: + return "Peer Review" + elif "image-photo" in text or "photo" in text: + return "Photo" + elif "image-plot" in text or "plot" in text: + return "Plot" + elif "poster" in text: + return "Poster" + elif "presentation" in text or "lecture" in text: + return "Presentation" + elif "publication-preprint" in text or "preprint" in text: + return "Preprint" + elif "publication-deliverable" in text or "project deliverable" in text: + return "Project Deliverable" + elif "publication" in text or "article" in text: + return "Publication" + elif "publication-report" in text or "report" in text: + return "Report" + elif "software" in text or "code" in text: + return "Software" + elif ( + "publication-taxonomictreatment" in text + or "taxonomic treatment" in text + ): + return "Taxonomic Treatment" + elif "video" in text or "audio" in text: + return "Video/Audio" + + return "Unclassified" + + +def standardize_language(lang_text): + """Standardize language codes/names using pycountry.""" + if not lang_text: + return "Unknown" + + # First-party/Local + from shared import get_language_name + + return get_language_name(lang_text.strip()) + + +def classify_license(license_data): + """Classify license from Zenodo REST API, focusing on CC licenses.""" + if not license_data: + return "No License" + + # REST API provides structured license data + if isinstance(license_data, dict): + license_id = license_data.get("id", "") # API returns lowercase IDs + + # Focus on Creative Commons licenses - normalize most cases + if license_id.startswith("cc"): + # Special cases that need custom mapping + special_cases = { + "cc-zero": "CC0", + "cc0-1.0": "CC0", + "cc0": "CC0", + "cc-nc": "CC BY-NC 4.0", + "cc-nd": "CC BY-ND 4.0", + "cc-sa": "CC BY-SA 4.0", + "cc-publicdomain": "Public Domain Mark 1.0", + } + + if license_id in special_cases: + return special_cases[license_id] + + # Normalize standard CC licenses: cc-by-4.0 -> CC BY 4.0 + if license_id.startswith("cc-by"): + return license_id.upper().replace("-", " ") + + # Check if it's a CC license + if license_id in cc_license_mapping: + return cc_license_mapping[license_id] + + # Group all non-CC licenses as "Non-CC" for efficiency + if license_id and license_id not in ["notspecified", ""]: + return "Non-CC" + + return "Not Specified" + + return "Unknown" + + +def fetch_zenodo_records(session, page=1, size=100, query=""): + """ + Fetch Zenodo records using REST API. + + Returns JSON response containing structured record data with: + - metadata.license (structured license object) + - metadata.resource_type (structured type information) + """ + params = { + "size": min(size, MAX_RECORDS_PER_REQUEST), + "page": page, + "sort": "newest", + } + + # Only add query parameter if not empty + if query: + params["q"] = query + + try: + response = session.get(ZENODO_API_BASE_URL, params=params, timeout=15) + response.raise_for_status() + return response.json() + except requests.RequestException as e: + raise shared.QuantifyingException( + f"Error fetching Zenodo records: {e}" + ) + except json.JSONDecodeError as e: + raise shared.QuantifyingException(f"Error parsing JSON response: {e}") + + +def extract_record_info(record_json): + """ + Extract information from a Zenodo REST API record. + + Parses JSON structure: + - metadata.license (structured license object) + - metadata.resource_type (structured type information) + - metadata.publication_date (ISO date) + - metadata.language (language code) + """ + record_info = { + "identifier": None, + "title": None, + "date": None, + "type": None, + "language": None, + "license_type": None, + } + + try: + # Basic record info + record_info["identifier"] = record_json.get("id") + + metadata = record_json.get("metadata", {}) + + # Title + record_info["title"] = metadata.get("title") + + # Date - extract year from publication_date + pub_date = metadata.get("publication_date") + if pub_date: + try: + record_info["date"] = int(pub_date[:4]) + except (ValueError, TypeError) as e: + LOGGER.debug(f"Invalid date format '{pub_date}': {e}") + record_info["date"] = None + + # Resource type + resource_type = metadata.get("resource_type", {}) + if isinstance(resource_type, dict): + type_title = resource_type.get("title", "") + record_info["type"] = classify_resource_type(type_title) + + # Language + language = metadata.get("language") + if language: + record_info["language"] = standardize_language(language) + + # License - structured data from REST API + license_data = metadata.get("license") + if license_data: + license_type = classify_license(license_data) + if license_type: + record_info["license_type"] = license_type + LOGGER.debug( + f"License identified: '{license_type}' from API data: " + f"{license_data}" + ) + + except Exception as e: + LOGGER.warning( + f"Error extracting record info from record " + f"{record_json.get('id', 'unknown')}: {e}" + ) + return record_info + + return record_info + + +def save_csv(file_path, headers, data, args): + """Save data to CSV file if save is enabled.""" + LOGGER.info(f"data file: {file_path.replace(PATHS['repo'], '.')}") + if args.enable_save: + os.makedirs(os.path.dirname(file_path), exist_ok=True) + with open(file_path, "w", newline="\n", encoding="utf-8") as csvfile: + writer = csv.writer(csvfile, quoting=csv.QUOTE_ALL) + writer.writerow(headers) + writer.writerows(data) + + +def main(): + args = parse_arguments() + + shared.paths_log(LOGGER, PATHS) + shared.git_fetch_and_merge(args, PATHS["repo"]) + + session = setup_session() + all_records = [] + extraction_failures = 0 + total_processed = 0 + license_counts = Counter() + year_counts = defaultdict(Counter) + type_counts = defaultdict(Counter) + lang_counts = defaultdict(Counter) + + # Build query for all records - CC filtering happens during processing + # Note: Zenodo's search API doesn't support reliable license field queries + base_query = "" # Empty query returns all records + + if args.dates_back: + from_year = datetime.now().year - args.dates_back + query = f"publication_date:[{from_year}-01-01 TO *]" + LOGGER.info(f"Filtering records from {from_year} onwards") + else: + query = base_query + LOGGER.info( + "Fetching all records, filtering CC licenses during processing" + ) + + # Fetch Zenodo records using REST API + LOGGER.info("Fetching Zenodo records using REST API") + + page = 1 + total_fetched = 0 + records_per_page = min(MAX_RECORDS_PER_REQUEST, 100) + + while total_fetched < args.fetch_limit: + LOGGER.info(f"Fetching page {page} (total so far: {total_fetched})") + + try: + response_data = fetch_zenodo_records( + session, page=page, size=records_per_page, query=query + ) + except (requests.RequestException, json.JSONDecodeError) as e: + raise shared.QuantifyingException( + f"Failed to fetch Zenodo records: {e}" + ) + + if not response_data or "hits" not in response_data: + raise shared.QuantifyingException( + "Invalid response from Zenodo REST API - stopping execution" + ) + + hits = response_data["hits"] + records = hits.get("hits", []) + total_available = hits.get("total", 0) + + LOGGER.info(f"Total records available: {total_available}") + + if not records: + LOGGER.info("No more records available - completed fetching") + break + + batch_license_records_found = 0 + + for record in records: + if total_fetched >= args.fetch_limit: + break + + record_info = extract_record_info(record) + total_processed += 1 + + # Skip records where extraction failed + if not record_info: + extraction_failures += 1 + continue + + # Only include records with valid licenses (CC filtering at API) + if record_info.get("license_type") and record_info[ + "license_type" + ] not in ["Unknown", "No License"]: + # Apply additional date filtering if specified + if args.dates_back and record_info["date"]: + publication_year_cutoff = ( + datetime.now().year - args.dates_back + ) + if record_info["date"] < publication_year_cutoff: + continue + + all_records.append(record_info) + batch_license_records_found += 1 + total_fetched += 1 + + # Check if we've reached the end of available records + if len(records) < records_per_page: + LOGGER.info("Reached end of available records") + break + + page += 1 + + # Be respectful to the API - increased delay for rate limiting + time.sleep(2.0) + + # Check for excessive extraction failures + if total_processed > 0: + failure_rate = extraction_failures / total_processed + if failure_rate > 0.1: # More than 10% failures + raise shared.QuantifyingException( + f"Too many extraction failures: {extraction_failures}/" + f"{total_processed} ({failure_rate:.1%}) - data quality issues" + ) + elif extraction_failures > 0: + LOGGER.warning( + f"Extraction failures: {extraction_failures}/" + f"{total_processed} ({failure_rate:.1%})" + ) + + if not all_records: + LOGGER.warning("No CC-licensed records found") + else: + LOGGER.info(f"Found {len(all_records)} total CC-licensed records") + + # Generate counts and log summary + total_license_records = 0 + for record in all_records: + license_type = record["license_type"] + year = record["date"] + resource_type = record["type"] + language = record["language"] + + # Only count records with actual licenses (skip None/null license_type) + if license_type: + license_counts[license_type] += 1 + total_license_records += 1 + + if year: + year_counts[license_type][year] += 1 + + if resource_type: + type_counts[license_type][resource_type] += 1 + + if language: + lang_counts[license_type][language] += 1 + + # Log summary + LOGGER.info( + f"Processed {total_license_records} records with valid licenses" + ) + LOGGER.info("License distribution:") + for license_type, count in sorted(license_counts.items()): + LOGGER.info(f" {license_type}: {count}") + + # Save results + # 1. License totals + license_data = [ + [license_type, count] + for license_type, count in sorted(license_counts.items()) + ] + save_csv( + shared.path_join(PATHS["data_phase"], "zenodo_1_count.csv"), + HEADER_COUNT, + license_data, + args, + ) + + # 2. Year breakdown + year_data = [] + for license_type in sorted(year_counts.keys()): + for year, count in sorted(year_counts[license_type].items()): + year_data.append([license_type, year, count]) + save_csv( + shared.path_join(PATHS["data_phase"], "zenodo_2_count_by_year.csv"), + HEADER_YEAR, + year_data, + args, + ) + + # 3. Resource type breakdown + type_data = [] + for license_type in sorted(type_counts.keys()): + for resource_type, count in sorted(type_counts[license_type].items()): + type_data.append([license_type, resource_type, count]) + save_csv( + shared.path_join(PATHS["data_phase"], "zenodo_3_count_by_type.csv"), + HEADER_TYPE, + type_data, + args, + ) + + # 4. Language breakdown + lang_data = [] + for license_type in sorted(lang_counts.keys()): + for language, count in sorted(lang_counts[license_type].items()): + lang_data.append([license_type, language, count]) + save_csv( + shared.path_join( + PATHS["data_phase"], "zenodo_4_count_by_language.csv" + ), + HEADER_LANGUAGE, + lang_data, + args, + ) + + args = shared.git_add_and_commit( + args, + PATHS["repo"], + PATHS["data_quarter"], + f"Add and commit new Zenodo data for {args.quarter}", + ) + shared.git_push_changes(args, PATHS["repo"]) + + +if __name__ == "__main__": + try: + main() + except shared.QuantifyingException as e: + if e.exit_code == 0: + LOGGER.info(e.message) + else: + LOGGER.error(e.message) + sys.exit(e.exit_code) + except SystemExit as e: + if e.code != 0: + LOGGER.error(f"System exit with code: {e.code}") + sys.exit(e.code) + except KeyboardInterrupt: + LOGGER.info("(130) Halted via KeyboardInterrupt.") + sys.exit(130) + except Exception: + traceback_formatted = textwrap.indent( + highlight( + traceback.format_exc(), + PythonTracebackLexer(), + TerminalFormatter(), + ), + " ", + ) + LOGGER.critical(f"(1) Unhandled exception:\n{traceback_formatted}") + sys.exit(1) diff --git a/scripts/shared.py b/scripts/shared.py old mode 100644 new mode 100755 index 541988fc..37ba9919 --- a/scripts/shared.py +++ b/scripts/shared.py @@ -11,6 +11,7 @@ from requests import Session from requests.adapters import HTTPAdapter from urllib3.util import Retry +import pycountry # Constants STATUS_FORCELIST = [ @@ -369,3 +370,46 @@ def update_readme( logger.info( f"Updated README with new image and description for {entry_title}." ) + + +def get_language_name(lang_text): + """ + Standardize language codes/names using pycountry. + + Args: + lang_text (str): Language code or name to standardize + + Returns: + str: Standardized language name or "Unknown" if not found + """ + if not lang_text: + return "Unknown" + + lang_text = lang_text.strip().lower() + + # Try to find by alpha_2 code (e.g., 'en' -> 'English') + try: + language = pycountry.languages.get(alpha_2=lang_text) + if language: + return language.name + except (KeyError, AttributeError): + pass + + # Try to find by alpha_3 code (e.g., 'eng' -> 'English') + try: + language = pycountry.languages.get(alpha_3=lang_text) + if language: + return language.name + except (KeyError, AttributeError): + pass + + # Try to find by name (case-insensitive) + try: + for language in pycountry.languages: + if hasattr(language, 'name') and language.name.lower() == lang_text: + return language.name + except (KeyError, AttributeError): + pass + + # Return original text if no match found + return lang_text.title() if lang_text else "Unknown" diff --git a/sources.md b/sources.md index 2f559bef..a77249cd 100644 --- a/sources.md +++ b/sources.md @@ -168,3 +168,29 @@ language edition of wikipedia. It runs on the Meta-Wiki API. - No API key required - Query limit: It is rate-limited only to prevent abuse - Data available through XML or JSON format + + +## Zenodo + +**Description:** Zenodo is a general-purpose open repository developed under the +European OpenAIRE program and operated by CERN. It allows researchers to deposit +research papers, data sets, research software, reports, and any other research +related digital artifacts. All uploads are assigned a Digital Object Identifier +(DOI) and are made available under various Creative Commons licenses or in the +public domain. + +**API documentation link:** +- [Zenodo REST API Documentation](https://developers.zenodo.org/) +- [Zenodo API Reference](https://zenodo.org/api/records) +- [Base URL](https://zenodo.org/api/records) +- [Zenodo Frontend](https://zenodo.org/) + +**API information:** +- No API key required +- Query limit: Rate-limited to prevent abuse (supports up to 1000+ records per + request) +- Data available through JSON format +- Supports search by various fields including license, resource type, + publication date, and language +- Provides structured license metadata through REST API +- Maximum 300 records per request (implementation choice for reliability)