diff --git a/CHANGELOG.md b/CHANGELOG.md index b44449e..8d28461 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,9 @@ # Changelog -## 0.8.1 (unreleased) +## 0.9.0 (unreleased) +- Add `Tree.build_random_tree()` +- Add `GenericNodeData` - Fixed #7 Tree.from_dict failing to recreate an arbitrary object tree with a mapper. ## 0.8.0 (2024-03-29) diff --git a/Pipfile b/Pipfile index 8c15a74..608e3b7 100644 --- a/Pipfile +++ b/Pipfile @@ -5,10 +5,9 @@ name = "pypi" [dev-packages] black = { version = "~=24.3", extras = ["jupyter"] } +# coverage = "*" +fabulist="*" isort = "*" -# pylint = "*" -# TODO: remove this line: -# pytest-html = "!=3.2.0" # wait for https://github.com/pytest-dev/pytest-html/pull/583 pytest = "*" pytest-cov = "*" PyYAML = "*" @@ -22,9 +21,9 @@ tox = "*" twine = "*" wheel = "*" yabs = "*" -nutree = {path = ".",editable = true} ipykernel = "*" notebook = "*" +nutree = {path = ".",editable = true} [packages] @@ -32,4 +31,3 @@ notebook = "*" python_version = "3.12" [pipenv] -# allow_prereleases = true diff --git a/Pipfile.lock b/Pipfile.lock index c9de180..78c5940 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "5935bcfa3efbb2476994643f35d2c509acabbabe36499683b590fdca3a093dd2" + "sha256": "98a0bcd048aa6b4870c6737ccc39368c1df70ce8bad22db187a05d49b0855bae" }, "pipfile-spec": 6, "requires": { @@ -27,11 +27,11 @@ }, "anyio": { "hashes": [ - "sha256:048e05d0f6caeed70d731f3db756d35dcc1f35747c8c403364a8332c630441b8", - "sha256:f75253795a87df48568485fd18cdd2a3fa5c4f7c5be8e5e36637733fce06fed6" + "sha256:5aadc6a1bbb7cdb0bede386cac5e2940f5e2ff3aa20277e991cf028e0585ce94", + "sha256:c1b2d8f46a8a812513012e1107cb0e68c17159a7a594208005a57dc776e1bdc7" ], "markers": "python_version >= '3.8'", - "version": "==4.3.0" + "version": "==4.4.0" }, "appnope": { "hashes": [ @@ -84,14 +84,6 @@ "markers": "python_version >= '3.8'", "version": "==1.3.0" }, - "astroid": { - "hashes": [ - "sha256:951798f922990137ac090c53af473db7ab4e70c770e6d7fae0cec59f74411819", - "sha256:ac248253bfa4bd924a0de213707e7ebeeb3138abeb48d798784ead1e56d419d4" - ], - "markers": "python_full_version >= '3.8.0'", - "version": "==3.1.0" - }, "asttokens": { "hashes": [ "sha256:051ed49c3dcae8913ea7cd08e46a606dba30b79993209636c4875bc1d637bc24", @@ -109,19 +101,19 @@ }, "attrs": { "hashes": [ - "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30", - "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1" + "sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346", + "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2" ], "markers": "python_version >= '3.7'", - "version": "==23.2.0" + "version": "==24.2.0" }, "babel": { "hashes": [ - "sha256:6919867db036398ba21eb5c7a0f6b28ab8cbc3ae7a73a44ebe34ae74a4e7d363", - "sha256:efb1a25b7118e67ce3a259bed20545c29cb68be8ad2c784c83689981b7a57287" + "sha256:368b5b98b37c06b7daf6696391c3240c938b37767d4584413e8438c5c435fa8b", + "sha256:d1f3554ca26605fe173f3de0c65f750f5a42f924499bf134de6423582298e316" ], - "markers": "python_version >= '3.7'", - "version": "==2.14.0" + "markers": "python_version >= '3.8'", + "version": "==2.16.0" }, "beautifulsoup4": { "hashes": [ @@ -136,31 +128,31 @@ "jupyter" ], "hashes": [ - "sha256:2818cf72dfd5d289e48f37ccfa08b460bf469e67fb7c4abb07edc2e9f16fb63f", - "sha256:41622020d7120e01d377f74249e677039d20e6344ff5851de8a10f11f513bf93", - "sha256:4acf672def7eb1725f41f38bf6bf425c8237248bb0804faa3965c036f7672d11", - "sha256:4be5bb28e090456adfc1255e03967fb67ca846a03be7aadf6249096100ee32d0", - "sha256:4f1373a7808a8f135b774039f61d59e4be7eb56b2513d3d2f02a8b9365b8a8a9", - "sha256:56f52cfbd3dabe2798d76dbdd299faa046a901041faf2cf33288bc4e6dae57b5", - "sha256:65b76c275e4c1c5ce6e9870911384bff5ca31ab63d19c76811cb1fb162678213", - "sha256:65c02e4ea2ae09d16314d30912a58ada9a5c4fdfedf9512d23326128ac08ac3d", - "sha256:6905238a754ceb7788a73f02b45637d820b2f5478b20fec82ea865e4f5d4d9f7", - "sha256:79dcf34b33e38ed1b17434693763301d7ccbd1c5860674a8f871bd15139e7837", - "sha256:7bb041dca0d784697af4646d3b62ba4a6b028276ae878e53f6b4f74ddd6db99f", - "sha256:7d5e026f8da0322b5662fa7a8e752b3fa2dac1c1cbc213c3d7ff9bdd0ab12395", - "sha256:9f50ea1132e2189d8dff0115ab75b65590a3e97de1e143795adb4ce317934995", - "sha256:a0c9c4a0771afc6919578cec71ce82a3e31e054904e7197deacbc9382671c41f", - "sha256:aadf7a02d947936ee418777e0247ea114f78aff0d0959461057cae8a04f20597", - "sha256:b5991d523eee14756f3c8d5df5231550ae8993e2286b8014e2fdea7156ed0959", - "sha256:bf21b7b230718a5f08bd32d5e4f1db7fc8788345c8aea1d155fc17852b3410f5", - "sha256:c45f8dff244b3c431b36e3224b6be4a127c6aca780853574c00faf99258041eb", - "sha256:c7ed6668cbbfcd231fa0dc1b137d3e40c04c7f786e626b405c62bcd5db5857e4", - "sha256:d7de8d330763c66663661a1ffd432274a2f92f07feeddd89ffd085b5744f85e7", - "sha256:e19cb1c6365fd6dc38a6eae2dcb691d7d83935c10215aef8e6c38edee3f77abd", - "sha256:e2af80566f43c85f5797365077fb64a393861a3730bd110971ab7a0c94e873e7" - ], - "markers": "python_version >= '3.8'", - "version": "==24.3.0" + "sha256:09cdeb74d494ec023ded657f7092ba518e8cf78fa8386155e4a03fdcc44679e6", + "sha256:1f13f7f386f86f8121d76599114bb8c17b69d962137fc70efe56137727c7047e", + "sha256:2500945420b6784c38b9ee885af039f5e7471ef284ab03fa35ecdde4688cd83f", + "sha256:2b59b250fdba5f9a9cd9d0ece6e6d993d91ce877d121d161e4698af3eb9c1018", + "sha256:3c4285573d4897a7610054af5a890bde7c65cb466040c5f0c8b732812d7f0e5e", + "sha256:505289f17ceda596658ae81b61ebbe2d9b25aa78067035184ed0a9d855d18afd", + "sha256:62e8730977f0b77998029da7971fa896ceefa2c4c4933fcd593fa599ecbf97a4", + "sha256:649f6d84ccbae73ab767e206772cc2d7a393a001070a4c814a546afd0d423aed", + "sha256:6e55d30d44bed36593c3163b9bc63bf58b3b30e4611e4d88a0c3c239930ed5b2", + "sha256:707a1ca89221bc8a1a64fb5e15ef39cd755633daa672a9db7498d1c19de66a42", + "sha256:72901b4913cbac8972ad911dc4098d5753704d1f3c56e44ae8dce99eecb0e3af", + "sha256:73bbf84ed136e45d451a260c6b73ed674652f90a2b3211d6a35e78054563a9bb", + "sha256:7c046c1d1eeb7aea9335da62472481d3bbf3fd986e093cffd35f4385c94ae368", + "sha256:81c6742da39f33b08e791da38410f32e27d632260e599df7245cccee2064afeb", + "sha256:837fd281f1908d0076844bc2b801ad2d369c78c45cf800cad7b61686051041af", + "sha256:972085c618ee94f402da1af548a4f218c754ea7e5dc70acb168bfaca4c2542ed", + "sha256:9e84e33b37be070ba135176c123ae52a51f82306def9f7d063ee302ecab2cf47", + "sha256:b19c9ad992c7883ad84c9b22aaa73562a16b819c1d8db7a1a1a49fb7ec13c7d2", + "sha256:d6417535d99c37cee4091a2f24eb2b6d5ec42b144d50f1f2e436d9fe1916fe1a", + "sha256:eab4dd44ce80dea27dc69db40dab62d4ca96112f87996bca68cd75639aeb2e4c", + "sha256:f490dbd59680d809ca31efdae20e634f3fae27fba3ce0ba3208333b713bc3920", + "sha256:fb6e2c0b86bbd43dee042e48059c9ad7830abd5c94b0bc518c0eeec57c3eddc1" + ], + "markers": "python_version >= '3.8'", + "version": "==24.8.0" }, "bleach": { "hashes": [ @@ -172,77 +164,92 @@ }, "cachetools": { "hashes": [ - "sha256:0abad1021d3f8325b2fc1d2e9c8b9c9d57b04c3932657a72465447332c24d945", - "sha256:ba29e2dfa0b8b556606f097407ed1aa62080ee108ab0dc5ec9d6a723a007d105" + "sha256:02134e8439cdc2ffb62023ce1debca2944c3f289d66bb17ead3ab3dede74b292", + "sha256:2cc24fb4cbe39633fb7badd9db9ca6295d766d9c2995f245725a46715d050f2a" ], "markers": "python_version >= '3.7'", - "version": "==5.3.3" + "version": "==5.5.0" }, "certifi": { "hashes": [ - "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f", - "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1" + "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8", + "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9" ], "markers": "python_version >= '3.6'", - "version": "==2024.2.2" + "version": "==2024.8.30" }, "cffi": { "hashes": [ - "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc", - "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a", - "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417", - "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab", - "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520", - "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36", - "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743", - "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8", - "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed", - "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684", - "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56", - "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324", - "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d", - "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235", - "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e", - "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088", - "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000", - "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7", - "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e", - "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673", - "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c", - "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe", - "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2", - "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098", - "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8", - "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a", - "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0", - "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b", - "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896", - "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e", - "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9", - "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2", - "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b", - "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6", - "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404", - "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f", - "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0", - "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4", - "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc", - "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936", - "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba", - "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872", - "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb", - "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614", - "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1", - "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d", - "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969", - "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b", - "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4", - "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627", - "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956", - "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357" + "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8", + "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2", + "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1", + "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15", + "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36", + "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", + "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8", + "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36", + "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17", + "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf", + "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc", + "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3", + "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed", + "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702", + "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1", + "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8", + "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", + "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6", + "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d", + "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b", + "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e", + "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be", + "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c", + "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683", + "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9", + "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c", + "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8", + "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1", + "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4", + "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655", + "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67", + "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595", + "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0", + "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65", + "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41", + "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6", + "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401", + "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6", + "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3", + "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16", + "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93", + "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e", + "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4", + "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964", + "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c", + "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576", + "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0", + "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3", + "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662", + "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3", + "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff", + "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5", + "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd", + "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f", + "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5", + "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14", + "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d", + "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9", + "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7", + "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382", + "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a", + "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e", + "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", + "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4", + "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99", + "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87", + "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b" ], "markers": "python_version >= '3.8'", - "version": "==1.16.0" + "version": "==1.17.1" }, "chardet": { "hashes": [ @@ -384,126 +391,141 @@ "toml" ], "hashes": [ - "sha256:00838a35b882694afda09f85e469c96367daa3f3f2b097d846a7216993d37f4c", - "sha256:0513b9508b93da4e1716744ef6ebc507aff016ba115ffe8ecff744d1322a7b63", - "sha256:09c3255458533cb76ef55da8cc49ffab9e33f083739c8bd4f58e79fecfe288f7", - "sha256:09ef9199ed6653989ebbcaacc9b62b514bb63ea2f90256e71fea3ed74bd8ff6f", - "sha256:09fa497a8ab37784fbb20ab699c246053ac294d13fc7eb40ec007a5043ec91f8", - "sha256:0f9f50e7ef2a71e2fae92774c99170eb8304e3fdf9c8c3c7ae9bab3e7229c5cf", - "sha256:137eb07173141545e07403cca94ab625cc1cc6bc4c1e97b6e3846270e7e1fea0", - "sha256:1f384c3cc76aeedce208643697fb3e8437604b512255de6d18dae3f27655a384", - "sha256:201bef2eea65e0e9c56343115ba3814e896afe6d36ffd37bab783261db430f76", - "sha256:38dd60d7bf242c4ed5b38e094baf6401faa114fc09e9e6632374388a404f98e7", - "sha256:3b799445b9f7ee8bf299cfaed6f5b226c0037b74886a4e11515e569b36fe310d", - "sha256:3ea79bb50e805cd6ac058dfa3b5c8f6c040cb87fe83de10845857f5535d1db70", - "sha256:40209e141059b9370a2657c9b15607815359ab3ef9918f0196b6fccce8d3230f", - "sha256:41c9c5f3de16b903b610d09650e5e27adbfa7f500302718c9ffd1c12cf9d6818", - "sha256:54eb8d1bf7cacfbf2a3186019bcf01d11c666bd495ed18717162f7eb1e9dd00b", - "sha256:598825b51b81c808cb6f078dcb972f96af96b078faa47af7dfcdf282835baa8d", - "sha256:5fc1de20b2d4a061b3df27ab9b7c7111e9a710f10dc2b84d33a4ab25065994ec", - "sha256:623512f8ba53c422fcfb2ce68362c97945095b864cda94a92edbaf5994201083", - "sha256:690db6517f09336559dc0b5f55342df62370a48f5469fabf502db2c6d1cffcd2", - "sha256:69eb372f7e2ece89f14751fbcbe470295d73ed41ecd37ca36ed2eb47512a6ab9", - "sha256:73bfb9c09951125d06ee473bed216e2c3742f530fc5acc1383883125de76d9cd", - "sha256:742a76a12aa45b44d236815d282b03cfb1de3b4323f3e4ec933acfae08e54ade", - "sha256:7c95949560050d04d46b919301826525597f07b33beba6187d04fa64d47ac82e", - "sha256:8130a2aa2acb8788e0b56938786c33c7c98562697bf9f4c7d6e8e5e3a0501e4a", - "sha256:8a2b2b78c78293782fd3767d53e6474582f62443d0504b1554370bde86cc8227", - "sha256:8ce1415194b4a6bd0cdcc3a1dfbf58b63f910dcb7330fe15bdff542c56949f87", - "sha256:9ca28a302acb19b6af89e90f33ee3e1906961f94b54ea37de6737b7ca9d8827c", - "sha256:a4cdc86d54b5da0df6d3d3a2f0b710949286094c3a6700c21e9015932b81447e", - "sha256:aa5b1c1bfc28384f1f53b69a023d789f72b2e0ab1b3787aae16992a7ca21056c", - "sha256:aadacf9a2f407a4688d700e4ebab33a7e2e408f2ca04dbf4aef17585389eff3e", - "sha256:ae71e7ddb7a413dd60052e90528f2f65270aad4b509563af6d03d53e979feafd", - "sha256:b14706df8b2de49869ae03a5ccbc211f4041750cd4a66f698df89d44f4bd30ec", - "sha256:b1a93009cb80730c9bca5d6d4665494b725b6e8e157c1cb7f2db5b4b122ea562", - "sha256:b2991665420a803495e0b90a79233c1433d6ed77ef282e8e152a324bbbc5e0c8", - "sha256:b2c5edc4ac10a7ef6605a966c58929ec6c1bd0917fb8c15cb3363f65aa40e677", - "sha256:b4d33f418f46362995f1e9d4f3a35a1b6322cb959c31d88ae56b0298e1c22357", - "sha256:b91cbc4b195444e7e258ba27ac33769c41b94967919f10037e6355e998af255c", - "sha256:c74880fc64d4958159fbd537a091d2a585448a8f8508bf248d72112723974cbd", - "sha256:c901df83d097649e257e803be22592aedfd5182f07b3cc87d640bbb9afd50f49", - "sha256:cac99918c7bba15302a2d81f0312c08054a3359eaa1929c7e4b26ebe41e9b286", - "sha256:cc4f1358cb0c78edef3ed237ef2c86056206bb8d9140e73b6b89fbcfcbdd40e1", - "sha256:ccd341521be3d1b3daeb41960ae94a5e87abe2f46f17224ba5d6f2b8398016cf", - "sha256:ce4b94265ca988c3f8e479e741693d143026632672e3ff924f25fab50518dd51", - "sha256:cf271892d13e43bc2b51e6908ec9a6a5094a4df1d8af0bfc360088ee6c684409", - "sha256:d5ae728ff3b5401cc320d792866987e7e7e880e6ebd24433b70a33b643bb0384", - "sha256:d71eec7d83298f1af3326ce0ff1d0ea83c7cb98f72b577097f9083b20bdaf05e", - "sha256:d898fe162d26929b5960e4e138651f7427048e72c853607f2b200909794ed978", - "sha256:d89d7b2974cae412400e88f35d86af72208e1ede1a541954af5d944a8ba46c57", - "sha256:dfa8fe35a0bb90382837b238fff375de15f0dcdb9ae68ff85f7a63649c98527e", - "sha256:e0be5efd5127542ef31f165de269f77560d6cdef525fffa446de6f7e9186cfb2", - "sha256:fdfafb32984684eb03c2d83e1e51f64f0906b11e64482df3c5db936ce3839d48", - "sha256:ff7687ca3d7028d8a5f0ebae95a6e4827c5616b31a4ee1192bdfde697db110d4" - ], - "markers": "python_version >= '3.8'", - "version": "==7.4.4" + "sha256:06a737c882bd26d0d6ee7269b20b12f14a8704807a01056c80bb881a4b2ce6ca", + "sha256:07e2ca0ad381b91350c0ed49d52699b625aab2b44b65e1b4e02fa9df0e92ad2d", + "sha256:0c0420b573964c760df9e9e86d1a9a622d0d27f417e1a949a8a66dd7bcee7bc6", + "sha256:0dbde0f4aa9a16fa4d754356a8f2e36296ff4d83994b2c9d8398aa32f222f989", + "sha256:1125ca0e5fd475cbbba3bb67ae20bd2c23a98fac4e32412883f9bcbaa81c314c", + "sha256:13b0a73a0896988f053e4fbb7de6d93388e6dd292b0d87ee51d106f2c11b465b", + "sha256:166811d20dfea725e2e4baa71fffd6c968a958577848d2131f39b60043400223", + "sha256:170d444ab405852903b7d04ea9ae9b98f98ab6d7e63e1115e82620807519797f", + "sha256:1f4aa8219db826ce6be7099d559f8ec311549bfc4046f7f9fe9b5cea5c581c56", + "sha256:225667980479a17db1048cb2bf8bfb39b8e5be8f164b8f6628b64f78a72cf9d3", + "sha256:260933720fdcd75340e7dbe9060655aff3af1f0c5d20f46b57f262ab6c86a5e8", + "sha256:2bdb062ea438f22d99cba0d7829c2ef0af1d768d1e4a4f528087224c90b132cb", + "sha256:2c09f4ce52cb99dd7505cd0fc8e0e37c77b87f46bc9c1eb03fe3bc9991085388", + "sha256:3115a95daa9bdba70aea750db7b96b37259a81a709223c8448fa97727d546fe0", + "sha256:3e0cadcf6733c09154b461f1ca72d5416635e5e4ec4e536192180d34ec160f8a", + "sha256:3f1156e3e8f2872197af3840d8ad307a9dd18e615dc64d9ee41696f287c57ad8", + "sha256:4421712dbfc5562150f7554f13dde997a2e932a6b5f352edcce948a815efee6f", + "sha256:44df346d5215a8c0e360307d46ffaabe0f5d3502c8a1cefd700b34baf31d411a", + "sha256:502753043567491d3ff6d08629270127e0c31d4184c4c8d98f92c26f65019962", + "sha256:547f45fa1a93154bd82050a7f3cddbc1a7a4dd2a9bf5cb7d06f4ae29fe94eaf8", + "sha256:5621a9175cf9d0b0c84c2ef2b12e9f5f5071357c4d2ea6ca1cf01814f45d2391", + "sha256:609b06f178fe8e9f89ef676532760ec0b4deea15e9969bf754b37f7c40326dbc", + "sha256:645786266c8f18a931b65bfcefdbf6952dd0dea98feee39bd188607a9d307ed2", + "sha256:6878ef48d4227aace338d88c48738a4258213cd7b74fd9a3d4d7582bb1d8a155", + "sha256:6a89ecca80709d4076b95f89f308544ec8f7b4727e8a547913a35f16717856cb", + "sha256:6db04803b6c7291985a761004e9060b2bca08da6d04f26a7f2294b8623a0c1a0", + "sha256:6e2cd258d7d927d09493c8df1ce9174ad01b381d4729a9d8d4e38670ca24774c", + "sha256:6e81d7a3e58882450ec4186ca59a3f20a5d4440f25b1cff6f0902ad890e6748a", + "sha256:702855feff378050ae4f741045e19a32d57d19f3e0676d589df0575008ea5004", + "sha256:78b260de9790fd81e69401c2dc8b17da47c8038176a79092a89cb2b7d945d060", + "sha256:7bb65125fcbef8d989fa1dd0e8a060999497629ca5b0efbca209588a73356232", + "sha256:7dea0889685db8550f839fa202744652e87c60015029ce3f60e006f8c4462c93", + "sha256:8284cf8c0dd272a247bc154eb6c95548722dce90d098c17a883ed36e67cdb129", + "sha256:877abb17e6339d96bf08e7a622d05095e72b71f8afd8a9fefc82cf30ed944163", + "sha256:8929543a7192c13d177b770008bc4e8119f2e1f881d563fc6b6305d2d0ebe9de", + "sha256:8ae539519c4c040c5ffd0632784e21b2f03fc1340752af711f33e5be83a9d6c6", + "sha256:8f59d57baca39b32db42b83b2a7ba6f47ad9c394ec2076b084c3f029b7afca23", + "sha256:9054a0754de38d9dbd01a46621636689124d666bad1936d76c0341f7d71bf569", + "sha256:953510dfb7b12ab69d20135a0662397f077c59b1e6379a768e97c59d852ee51d", + "sha256:95cae0efeb032af8458fc27d191f85d1717b1d4e49f7cb226cf526ff28179778", + "sha256:9bc572be474cafb617672c43fe989d6e48d3c83af02ce8de73fff1c6bb3c198d", + "sha256:9c56863d44bd1c4fe2abb8a4d6f5371d197f1ac0ebdee542f07f35895fc07f36", + "sha256:9e0b2df163b8ed01d515807af24f63de04bebcecbd6c3bfeff88385789fdf75a", + "sha256:a09ece4a69cf399510c8ab25e0950d9cf2b42f7b3cb0374f95d2e2ff594478a6", + "sha256:a1ac0ae2b8bd743b88ed0502544847c3053d7171a3cff9228af618a068ed9c34", + "sha256:a318d68e92e80af8b00fa99609796fdbcdfef3629c77c6283566c6f02c6d6704", + "sha256:a4acd025ecc06185ba2b801f2de85546e0b8ac787cf9d3b06e7e2a69f925b106", + "sha256:a6d3adcf24b624a7b778533480e32434a39ad8fa30c315208f6d3e5542aeb6e9", + "sha256:a78d169acd38300060b28d600344a803628c3fd585c912cacc9ea8790fe96862", + "sha256:a95324a9de9650a729239daea117df21f4b9868ce32e63f8b650ebe6cef5595b", + "sha256:abd5fd0db5f4dc9289408aaf34908072f805ff7792632250dcb36dc591d24255", + "sha256:b06079abebbc0e89e6163b8e8f0e16270124c154dc6e4a47b413dd538859af16", + "sha256:b43c03669dc4618ec25270b06ecd3ee4fa94c7f9b3c14bae6571ca00ef98b0d3", + "sha256:b48f312cca9621272ae49008c7f613337c53fadca647d6384cc129d2996d1133", + "sha256:b5d7b556859dd85f3a541db6a4e0167b86e7273e1cdc973e5b175166bb634fdb", + "sha256:b9f222de8cded79c49bf184bdbc06630d4c58eec9459b939b4a690c82ed05657", + "sha256:c3c02d12f837d9683e5ab2f3d9844dc57655b92c74e286c262e0fc54213c216d", + "sha256:c44fee9975f04b33331cb8eb272827111efc8930cfd582e0320613263ca849ca", + "sha256:cf4b19715bccd7ee27b6b120e7e9dd56037b9c0681dcc1adc9ba9db3d417fa36", + "sha256:d0c212c49b6c10e6951362f7c6df3329f04c2b1c28499563d4035d964ab8e08c", + "sha256:d3296782ca4eab572a1a4eca686d8bfb00226300dcefdf43faa25b5242ab8a3e", + "sha256:d85f5e9a5f8b73e2350097c3756ef7e785f55bd71205defa0bfdaf96c31616ff", + "sha256:da511e6ad4f7323ee5702e6633085fb76c2f893aaf8ce4c51a0ba4fc07580ea7", + "sha256:e05882b70b87a18d937ca6768ff33cc3f72847cbc4de4491c8e73880766718e5", + "sha256:e61c0abb4c85b095a784ef23fdd4aede7a2628478e7baba7c5e3deba61070a02", + "sha256:e6a08c0be454c3b3beb105c0596ebdc2371fab6bb90c0c0297f4e58fd7e1012c", + "sha256:e9a6e0eb86070e8ccaedfbd9d38fec54864f3125ab95419970575b42af7541df", + "sha256:ed37bd3c3b063412f7620464a9ac1314d33100329f39799255fb8d3027da50d3", + "sha256:f1adfc8ac319e1a348af294106bc6a8458a0f1633cc62a1446aebc30c5fa186a", + "sha256:f5796e664fe802da4f57a168c85359a8fbf3eab5e55cd4e4569fbacecc903959", + "sha256:fc5a77d0c516700ebad189b587de289a20a78324bc54baee03dd486f0855d234", + "sha256:fd21f6ae3f08b41004dfb433fa895d858f3f5979e7762d052b12aef444e29afc" + ], + "markers": "python_version >= '3.8'", + "version": "==7.6.1" }, "cryptography": { "hashes": [ - "sha256:0270572b8bd2c833c3981724b8ee9747b3ec96f699a9665470018594301439ee", - "sha256:111a0d8553afcf8eb02a4fea6ca4f59d48ddb34497aa8706a6cf536f1a5ec576", - "sha256:16a48c23a62a2f4a285699dba2e4ff2d1cff3115b9df052cdd976a18856d8e3d", - "sha256:1b95b98b0d2af784078fa69f637135e3c317091b615cd0905f8b8a087e86fa30", - "sha256:1f71c10d1e88467126f0efd484bd44bca5e14c664ec2ede64c32f20875c0d413", - "sha256:2424ff4c4ac7f6b8177b53c17ed5d8fa74ae5955656867f5a8affaca36a27abb", - "sha256:2bce03af1ce5a5567ab89bd90d11e7bbdff56b8af3acbbec1faded8f44cb06da", - "sha256:329906dcc7b20ff3cad13c069a78124ed8247adcac44b10bea1130e36caae0b4", - "sha256:37dd623507659e08be98eec89323469e8c7b4c1407c85112634ae3dbdb926fdd", - "sha256:3eaafe47ec0d0ffcc9349e1708be2aaea4c6dd4978d76bf6eb0cb2c13636c6fc", - "sha256:5e6275c09d2badf57aea3afa80d975444f4be8d3bc58f7f80d2a484c6f9485c8", - "sha256:6fe07eec95dfd477eb9530aef5bead34fec819b3aaf6c5bd6d20565da607bfe1", - "sha256:7367d7b2eca6513681127ebad53b2582911d1736dc2ffc19f2c3ae49997496bc", - "sha256:7cde5f38e614f55e28d831754e8a3bacf9ace5d1566235e39d91b35502d6936e", - "sha256:9481ffe3cf013b71b2428b905c4f7a9a4f76ec03065b05ff499bb5682a8d9ad8", - "sha256:98d8dc6d012b82287f2c3d26ce1d2dd130ec200c8679b6213b3c73c08b2b7940", - "sha256:a011a644f6d7d03736214d38832e030d8268bcff4a41f728e6030325fea3e400", - "sha256:a2913c5375154b6ef2e91c10b5720ea6e21007412f6437504ffea2109b5a33d7", - "sha256:a30596bae9403a342c978fb47d9b0ee277699fa53bbafad14706af51fe543d16", - "sha256:b03c2ae5d2f0fc05f9a2c0c997e1bc18c8229f392234e8a0194f202169ccd278", - "sha256:b6cd2203306b63e41acdf39aa93b86fb566049aeb6dc489b70e34bcd07adca74", - "sha256:b7ffe927ee6531c78f81aa17e684e2ff617daeba7f189f911065b2ea2d526dec", - "sha256:b8cac287fafc4ad485b8a9b67d0ee80c66bf3574f655d3b97ef2e1082360faf1", - "sha256:ba334e6e4b1d92442b75ddacc615c5476d4ad55cc29b15d590cc6b86efa487e2", - "sha256:ba3e4a42397c25b7ff88cdec6e2a16c2be18720f317506ee25210f6d31925f9c", - "sha256:c41fb5e6a5fe9ebcd58ca3abfeb51dffb5d83d6775405305bfa8715b76521922", - "sha256:cd2030f6650c089aeb304cf093f3244d34745ce0cfcc39f20c6fbfe030102e2a", - "sha256:cd65d75953847815962c84a4654a84850b2bb4aed3f26fadcc1c13892e1e29f6", - "sha256:e4985a790f921508f36f81831817cbc03b102d643b5fcb81cd33df3fa291a1a1", - "sha256:e807b3188f9eb0eaa7bbb579b462c5ace579f1cedb28107ce8b48a9f7ad3679e", - "sha256:f12764b8fffc7a123f641d7d049d382b73f96a34117e0b637b80643169cec8ac", - "sha256:f8837fe1d6ac4a8052a9a8ddab256bc006242696f03368a4009be7ee3075cdb7" - ], - "version": "==42.0.5" + "sha256:014f58110f53237ace6a408b5beb6c427b64e084eb451ef25a28308270086494", + "sha256:1bbcce1a551e262dfbafb6e6252f1ae36a248e615ca44ba302df077a846a8806", + "sha256:203e92a75716d8cfb491dc47c79e17d0d9207ccffcbcb35f598fbe463ae3444d", + "sha256:27e613d7077ac613e399270253259d9d53872aaf657471473ebfc9a52935c062", + "sha256:2bd51274dcd59f09dd952afb696bf9c61a7a49dfc764c04dd33ef7a6b502a1e2", + "sha256:38926c50cff6f533f8a2dae3d7f19541432610d114a70808f0926d5aaa7121e4", + "sha256:511f4273808ab590912a93ddb4e3914dfd8a388fed883361b02dea3791f292e1", + "sha256:58d4e9129985185a06d849aa6df265bdd5a74ca6e1b736a77959b498e0505b85", + "sha256:5b43d1ea6b378b54a1dc99dd8a2b5be47658fe9a7ce0a58ff0b55f4b43ef2b84", + "sha256:61ec41068b7b74268fa86e3e9e12b9f0c21fcf65434571dbb13d954bceb08042", + "sha256:666ae11966643886c2987b3b721899d250855718d6d9ce41b521252a17985f4d", + "sha256:68aaecc4178e90719e95298515979814bda0cbada1256a4485414860bd7ab962", + "sha256:7c05650fe8023c5ed0d46793d4b7d7e6cd9c04e68eabe5b0aeea836e37bdcec2", + "sha256:80eda8b3e173f0f247f711eef62be51b599b5d425c429b5d4ca6a05e9e856baa", + "sha256:8385d98f6a3bf8bb2d65a73e17ed87a3ba84f6991c155691c51112075f9ffc5d", + "sha256:88cce104c36870d70c49c7c8fd22885875d950d9ee6ab54df2745f83ba0dc365", + "sha256:9d3cdb25fa98afdd3d0892d132b8d7139e2c087da1712041f6b762e4f807cc96", + "sha256:a575913fb06e05e6b4b814d7f7468c2c660e8bb16d8d5a1faf9b33ccc569dd47", + "sha256:ac119bb76b9faa00f48128b7f5679e1d8d437365c5d26f1c2c3f0da4ce1b553d", + "sha256:c1332724be35d23a854994ff0b66530119500b6053d0bd3363265f7e5e77288d", + "sha256:d03a475165f3134f773d1388aeb19c2d25ba88b6a9733c5c590b9ff7bbfa2e0c", + "sha256:d75601ad10b059ec832e78823b348bfa1a59f6b8d545db3a24fd44362a1564cb", + "sha256:de41fd81a41e53267cb020bb3a7212861da53a7d39f863585d13ea11049cf277", + "sha256:e710bf40870f4db63c3d7d929aa9e09e4e7ee219e703f949ec4073b4294f6172", + "sha256:ea25acb556320250756e53f9e20a4177515f012c9eaea17eb7587a8c4d8ae034", + "sha256:f98bf604c82c416bc829e490c700ca1553eafdf2912a91e23a79d97d9801372a", + "sha256:fba1007b3ef89946dbbb515aeeb41e30203b004f0b4b00e5e16078b518563289" + ], + "version": "==43.0.1" }, "debugpy": { "hashes": [ - "sha256:016a9fcfc2c6b57f939673c874310d8581d51a0fe0858e7fac4e240c5eb743cb", - "sha256:0de56aba8249c28a300bdb0672a9b94785074eb82eb672db66c8144fff673146", - "sha256:1a9fe0829c2b854757b4fd0a338d93bc17249a3bf69ecf765c61d4c522bb92a8", - "sha256:28acbe2241222b87e255260c76741e1fbf04fdc3b6d094fcf57b6c6f75ce1242", - "sha256:3a79c6f62adef994b2dbe9fc2cc9cc3864a23575b6e387339ab739873bea53d0", - "sha256:3bda0f1e943d386cc7a0e71bfa59f4137909e2ed947fb3946c506e113000f741", - "sha256:3ebb70ba1a6524d19fa7bb122f44b74170c447d5746a503e36adc244a20ac539", - "sha256:58911e8521ca0c785ac7a0539f1e77e0ce2df753f786188f382229278b4cdf23", - "sha256:6df9aa9599eb05ca179fb0b810282255202a66835c6efb1d112d21ecb830ddd3", - "sha256:7a3afa222f6fd3d9dfecd52729bc2e12c93e22a7491405a0ecbf9e1d32d45b39", - "sha256:7eb7bd2b56ea3bedb009616d9e2f64aab8fc7000d481faec3cd26c98a964bcdd", - "sha256:92116039b5500633cc8d44ecc187abe2dfa9b90f7a82bbf81d079fcdd506bae9", - "sha256:a2e658a9630f27534e63922ebf655a6ab60c370f4d2fc5c02a5b19baf4410ace", - "sha256:bfb20cb57486c8e4793d41996652e5a6a885b4d9175dd369045dad59eaacea42", - "sha256:caad2846e21188797a1f17fc09c31b84c7c3c23baf2516fed5b40b378515bbf0", - "sha256:d915a18f0597ef685e88bb35e5d7ab968964b7befefe1aaea1eb5b2640b586c7", - "sha256:dda73bf69ea479c8577a0448f8c707691152e6c4de7f0c4dec5a4bc11dee516e", - "sha256:e38beb7992b5afd9d5244e96ad5fa9135e94993b0c551ceebf3fe1a5d9beb234", - "sha256:edcc9f58ec0fd121a25bc950d4578df47428d72e1a0d66c07403b04eb93bcf98", - "sha256:efd3fdd3f67a7e576dd869c184c5dd71d9aaa36ded271939da352880c012e703", - "sha256:f696d6be15be87aef621917585f9bb94b1dc9e8aced570db1b8a6fc14e8f9b42", - "sha256:fd97ed11a4c7f6d042d320ce03d83b20c3fb40da892f994bc041bbc415d7a099" - ], - "markers": "python_version >= '3.8'", - "version": "==1.8.1" + "sha256:0a1029a2869d01cb777216af8c53cda0476875ef02a2b6ff8b2f2c9a4b04176c", + "sha256:1cd04a73eb2769eb0bfe43f5bfde1215c5923d6924b9b90f94d15f207a402226", + "sha256:28ced650c974aaf179231668a293ecd5c63c0a671ae6d56b8795ecc5d2f48d3c", + "sha256:345d6a0206e81eb68b1493ce2fbffd57c3088e2ce4b46592077a943d2b968ca3", + "sha256:3df6692351172a42af7558daa5019651f898fc67450bf091335aa8a18fbf6f3a", + "sha256:4413b7a3ede757dc33a273a17d685ea2b0c09dbd312cc03f5534a0fd4d40750a", + "sha256:4fbb3b39ae1aa3e5ad578f37a48a7a303dad9a3d018d369bc9ec629c1cfa7408", + "sha256:55919dce65b471eff25901acf82d328bbd5b833526b6c1364bd5133754777a44", + "sha256:5b5c770977c8ec6c40c60d6f58cacc7f7fe5a45960363d6974ddb9b62dbee156", + "sha256:606bccba19f7188b6ea9579c8a4f5a5364ecd0bf5a0659c8a5d0e10dcee3032a", + "sha256:7b0fe36ed9d26cb6836b0a51453653f8f2e347ba7348f2bbfe76bfeb670bfb1c", + "sha256:7e4d594367d6407a120b76bdaa03886e9eb652c05ba7f87e37418426ad2079f7", + "sha256:8f913ee8e9fcf9d38a751f56e6de12a297ae7832749d35de26d960f14280750a", + "sha256:a697beca97dad3780b89a7fb525d5e79f33821a8bc0c06faf1f1289e549743cf", + "sha256:ad84b7cde7fd96cf6eea34ff6c4a1b7887e0fe2ea46e099e53234856f9d99a34", + "sha256:b2112cfeb34b4507399d298fe7023a16656fc553ed5246536060ca7bd0e668d0", + "sha256:b78c1250441ce893cb5035dd6f5fc12db968cc07f91cc06996b2087f7cefdd8e", + "sha256:c0a65b00b7cdd2ee0c2cf4c7335fef31e15f1b7056c7fdbce9e90193e1a8c8cb", + "sha256:c9f7c15ea1da18d2fcc2709e9f3d6de98b69a5b0fff1807fb80bc55f906691f7", + "sha256:db9fb642938a7a609a6c865c32ecd0d795d56c1aaa7a7a5722d77855d5e77f2b", + "sha256:dd3811bd63632bb25eda6bd73bea8e0521794cda02be41fa3160eb26fc29e7ed", + "sha256:e84c276489e141ed0b93b0af648eef891546143d6a48f610945416453a8ad406" + ], + "markers": "python_version >= '3.8'", + "version": "==1.8.5" }, "decorator": { "hashes": [ @@ -529,14 +551,6 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.2.14" }, - "dill": { - "hashes": [ - "sha256:3ebe3c479ad625c4553aca177444d89b486b1d84982eeacded644afc0cf797ca", - "sha256:c36ca9ffb54365bdd2f8eb3eff7d2a21237f8452b57ace88b1ac615b7e815bd7" - ], - "markers": "python_version >= '3.11'", - "version": "==0.3.8" - }, "distlib": { "hashes": [ "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784", @@ -554,26 +568,34 @@ }, "executing": { "hashes": [ - "sha256:35afe2ce3affba8ee97f2d69927fa823b08b472b7b994e36a52a964b93d16147", - "sha256:eac49ca94516ccc753f9fb5ce82603156e590b27525a8bc32cce8ae302eb61bc" + "sha256:8d63781349375b5ebccc3142f4b30350c0cd9c79f921cde38be2be4637e98eaf", + "sha256:8ea27ddd260da8150fa5a708269c4a10e76161e2496ec3e587da9e3c0fe4b9ab" ], - "markers": "python_version >= '3.5'", - "version": "==2.0.1" + "markers": "python_version >= '3.8'", + "version": "==2.1.0" + }, + "fabulist": { + "hashes": [ + "sha256:6306d25164faafd2663a3c2cea4b95e73d8c51bba568fa340ce21fceb2862806", + "sha256:638f1456aa5ec97753db23abf9408fb56c6c78dbe4625a1e487013fceed1bf51" + ], + "index": "pypi", + "version": "==1.2.0" }, "fastjsonschema": { "hashes": [ - "sha256:3672b47bc94178c9f23dbb654bf47440155d4db9df5f7bc47643315f9c405cd0", - "sha256:e3126a94bdc4623d3de4485f8d468a12f02a67921315ddc87836d6e456dc789d" + "sha256:3d48fc5300ee96f5d116f10fe6f28d938e6008f59a6a025c2649475b87f76a23", + "sha256:5875f0b0fa7a0043a91e93a9b8f793bcbbba9691e7fd83dca95c28ba26d21f0a" ], - "version": "==2.19.1" + "version": "==2.20.0" }, "filelock": { "hashes": [ - "sha256:5ffa845303983e7a0b7ae17636509bc97997d58afeafa72fb141a17b152284cb", - "sha256:a79895a25bbefdf55d1a2a0a80968f7dbb28edcd6d4234a0afb3f37ecde4b546" + "sha256:81de9eb8453c769b63369f87f11131a7ab04e367f8d97ad39dc230daa07e3bec", + "sha256:f6ed4c963184f4c84dd5557ce8fece759a3724b37b80c6c4f20a2f63a4dc6609" ], "markers": "python_version >= '3.8'", - "version": "==3.13.3" + "version": "==3.16.0" }, "fqdn": { "hashes": [ @@ -592,11 +614,11 @@ }, "gitpython": { "hashes": [ - "sha256:1bf9cd7c9e7255f77778ea54359e54ac22a72a5b51288c457c881057b7bb9ecd", - "sha256:2d99869e0fef71a73cbd242528105af1d6c1b108c60dfabd994bf292f76c3ceb" + "sha256:35f314a9f878467f5453cc1fee295c3e18e52f1b99f10f6cf5b1682e968a9e7c", + "sha256:eec7ec56b92aad751f9912a73404bc02ba212a23adb2c7098ee668417051a1ff" ], "markers": "python_version >= '3.7'", - "version": "==3.1.42" + "version": "==3.1.43" }, "h11": { "hashes": [ @@ -616,19 +638,19 @@ }, "httpx": { "hashes": [ - "sha256:71d5465162c13681bff01ad59b2cc68dd838ea1f10e51574bac27103f00c91a5", - "sha256:a0cb88a46f32dc874e04ee956e4c2764aba2aa228f650b06788ba6bda2962ab5" + "sha256:7bb2708e112d8fdd7829cd4243970f0c223274051cb35ee80c03301ee29a3df0", + "sha256:f7c2be1d2f3c3c3160d441802406b206c2b76f5947b11115e6df10c6c65e66c2" ], "markers": "python_version >= '3.8'", - "version": "==0.27.0" + "version": "==0.27.2" }, "idna": { "hashes": [ - "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca", - "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f" + "sha256:050b4e5baadcd44d760cedbd2b8e639f2ff89bbc7a5730fcc662954303377aac", + "sha256:d838c2c0ed6fced7693d5e8ab8e734d5f8fda53a039c0164afb0b82e771e3603" ], - "markers": "python_version >= '3.5'", - "version": "==3.6" + "markers": "python_version >= '3.6'", + "version": "==3.8" }, "imagesize": { "hashes": [ @@ -640,11 +662,11 @@ }, "importlib-metadata": { "hashes": [ - "sha256:30962b96c0c223483ed6cc7280e7f0199feb01a0e40cfae4d4450fc6fab1f570", - "sha256:b78938b926ee8d5f020fc4772d487045805a55ddbad2ecf21c6d60938dc7fcd2" + "sha256:66f342cc6ac9818fc6ff340576acd24d65ba0b3efabb2b4ac08b598965a4a2f1", + "sha256:9a547d3bc3608b025f93d403fdd1aae741c24fbb8314df4b155675742ce303c5" ], "markers": "python_version >= '3.8'", - "version": "==7.1.0" + "version": "==8.4.0" }, "iniconfig": { "hashes": [ @@ -656,20 +678,20 @@ }, "ipykernel": { "hashes": [ - "sha256:1181e653d95c6808039c509ef8e67c4126b3b3af7781496c7cbfb5ed938a27da", - "sha256:3d44070060f9475ac2092b760123fadf105d2e2493c24848b6691a7c4f42af5c" + "sha256:afdb66ba5aa354b09b91379bac28ae4afebbb30e8b39510c9690afb7a10421b5", + "sha256:f093a22c4a40f8828f8e330a9c297cb93dcab13bd9678ded6de8e5cf81c56215" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==6.29.4" + "version": "==6.29.5" }, "ipython": { "hashes": [ - "sha256:2dcaad9049f9056f1fef63514f176c7d41f930daa78d05b82a176202818f2c14", - "sha256:3c86f284c8f3d8f2b6c662f885c4889a91df7cd52056fd02b7d8d6195d7f56e9" + "sha256:0b99a2dc9f15fd68692e898e5568725c6d49c527d36a9fb5960ffbdeaa82ff7e", + "sha256:f68b3cb8bde357a5d7adc9598d57e22a45dfbea19eb6b98286fa3b288c9cd55c" ], "markers": "python_version >= '3.10'", - "version": "==8.22.2" + "version": "==8.27.0" }, "isodate": { "hashes": [ @@ -696,27 +718,27 @@ }, "jaraco.classes": { "hashes": [ - "sha256:86b534de565381f6b3c1c830d13f931d7be1a75f0081c57dff615578676e2206", - "sha256:cb28a5ebda8bc47d8c8015307d93163464f9f2b91ab4006e09ff0ce07e8bfb30" + "sha256:47a024b51d0239c0dd8c8540c6c7f484be3b8fcf0b2d85c13825780d3b3f3acd", + "sha256:f662826b6bed8cace05e7ff873ce0f9283b5c924470fe664fff1c2f00f581790" ], "markers": "python_version >= '3.8'", - "version": "==3.3.1" + "version": "==3.4.0" }, "jaraco.context": { "hashes": [ - "sha256:4dad2404540b936a20acedec53355bdaea223acb88fd329fa6de9261c941566e", - "sha256:5d9e95ca0faa78943ed66f6bc658dd637430f16125d86988e77844c741ff2f11" + "sha256:9bae4ea555cf0b14938dc0aee7c9f32ed303aa20a3b73e7dc80111628792d1b3", + "sha256:f797fc481b490edb305122c9181830a3a5b76d84ef6d1aef2fb9b47ab956f9e4" ], - "markers": "python_version >= '3.7'", - "version": "==4.3.0" + "markers": "python_version >= '3.8'", + "version": "==6.0.1" }, "jaraco.functools": { "hashes": [ - "sha256:c279cb24c93d694ef7270f970d499cab4d3813f4e08273f95398651a634f0925", - "sha256:daf276ddf234bea897ef14f43c4e1bf9eefeac7b7a82a4dd69228ac20acff68d" + "sha256:3460c74cd0d32bf82b9576bbb3527c4364d5b27a21f5158a62aed6c4b42e23f5", + "sha256:c9d16a3ed4ccb5a889ad8e0b7a343401ee5b2a71cee6ed192d3f68bc351e94e3" ], "markers": "python_version >= '3.8'", - "version": "==4.0.0" + "version": "==4.0.2" }, "jedi": { "hashes": [ @@ -728,37 +750,37 @@ }, "jinja2": { "hashes": [ - "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa", - "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90" + "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369", + "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d" ], "markers": "python_version >= '3.7'", - "version": "==3.1.3" + "version": "==3.1.4" }, "json5": { "hashes": [ - "sha256:0c638399421da959a20952782800e5c1a78c14e08e1dc9738fa10d8ec14d58c8", - "sha256:4ca101fd5c7cb47960c055ef8f4d0e31e15a7c6c48c3b6f1473fc83b6c462a13" + "sha256:34ed7d834b1341a86987ed52f3f76cd8ee184394906b6e22a1e0deb9ab294e8f", + "sha256:548e41b9be043f9426776f05df8635a00fe06104ea51ed24b67f908856e151ae" ], "markers": "python_version >= '3.8'", - "version": "==0.9.24" + "version": "==0.9.25" }, "jsonpointer": { "hashes": [ - "sha256:15d51bba20eea3165644553647711d150376234112651b4f1811022aecad7d7a", - "sha256:585cee82b70211fa9e6043b7bb89db6e1aa49524340dde8ad6b63206ea689d88" + "sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942", + "sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef" ], - "version": "==2.4" + "version": "==3.0.0" }, "jsonschema": { "extras": [ "format-nongpl" ], "hashes": [ - "sha256:7996507afae316306f9e2290407761157c6f78002dcf7419acb99822143d1c6f", - "sha256:85727c00279f5fa6bedbe6238d2aa6403bedd8b4864ab11207d07df3cc1b2ee5" + "sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4", + "sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566" ], "markers": "python_version >= '3.8'", - "version": "==4.21.1" + "version": "==4.23.0" }, "jsonschema-specifications": { "hashes": [ @@ -770,11 +792,11 @@ }, "jupyter-client": { "hashes": [ - "sha256:3b7bd22f058434e3b9a7ea4b1500ed47de2713872288c0d511d19926f99b459f", - "sha256:e842515e2bab8e19186d89fdfea7abd15e39dd581f94e399f00e2af5a1652d3f" + "sha256:2bda14d55ee5ba58552a8c53ae43d215ad9868853489213f37da060ced54d8df", + "sha256:50cbc5c66fd1b8f65ecb66bc490ab73217993632809b6e505687de18e9dea39f" ], "markers": "python_version >= '3.8'", - "version": "==8.6.1" + "version": "==8.6.2" }, "jupyter-core": { "hashes": [ @@ -794,19 +816,19 @@ }, "jupyter-lsp": { "hashes": [ - "sha256:5e50033149344065348e688608f3c6d654ef06d9856b67655bd7b6bac9ee2d59", - "sha256:da61cb63a16b6dff5eac55c2699cc36eac975645adee02c41bdfc03bf4802e77" + "sha256:45fbddbd505f3fbfb0b6cb2f1bc5e15e83ab7c79cd6e89416b248cb3c00c11da", + "sha256:793147a05ad446f809fd53ef1cd19a9f5256fd0a2d6b7ce943a982cb4f545001" ], "markers": "python_version >= '3.8'", - "version": "==2.2.4" + "version": "==2.2.5" }, "jupyter-server": { "hashes": [ - "sha256:77b2b49c3831fbbfbdb5048cef4350d12946191f833a24e5f83e5f8f4803e97b", - "sha256:c80bfb049ea20053c3d9641c2add4848b38073bf79f1729cea1faed32fc1c78e" + "sha256:47ff506127c2f7851a17bf4713434208fc490955d0e8632e95014a9a9afbeefd", + "sha256:66095021aa9638ced276c248b1d81862e4c50f292d575920bbe960de1c56b12b" ], "markers": "python_version >= '3.8'", - "version": "==2.13.0" + "version": "==2.14.2" }, "jupyter-server-terminals": { "hashes": [ @@ -818,11 +840,11 @@ }, "jupyterlab": { "hashes": [ - "sha256:3bc843382a25e1ab7bc31d9e39295a9f0463626692b7995597709c0ab236ab2c", - "sha256:c9ad75290cb10bfaff3624bf3fbb852319b4cce4c456613f8ebbaa98d03524db" + "sha256:73b6e0775d41a9fee7ee756c80f58a6bed4040869ccc21411dc559818874d321", + "sha256:ae7f3a1b8cb88b4f55009ce79fa7c06f99d70cd63601ee4aa91815d054f46f75" ], "markers": "python_version >= '3.8'", - "version": "==4.1.5" + "version": "==4.2.5" }, "jupyterlab-pygments": { "hashes": [ @@ -834,19 +856,19 @@ }, "jupyterlab-server": { "hashes": [ - "sha256:2098198e1e82e0db982440f9b5136175d73bea2cd42a6480aa6fd502cb23c4f9", - "sha256:eb645ecc8f9b24bac5decc7803b6d5363250e16ec5af814e516bc2c54dd88081" + "sha256:e697488f66c3db49df675158a77b3b017520d772c6e1548c7d9bcc5df7944ee4", + "sha256:eb36caca59e74471988f0ae25c77945610b887f777255aa21f8065def9e51ed4" ], "markers": "python_version >= '3.8'", - "version": "==2.25.4" + "version": "==2.27.3" }, "keyring": { "hashes": [ - "sha256:9a15cd280338920388e8c1787cb8792b9755dabb3e7c61af5ac1f8cd437cefde", - "sha256:fc024ed53c7ea090e30723e6bd82f58a39dc25d9a6797d866203ecd0ee6306cb" + "sha256:8d85a1ea5d6db8515b59e1c5d1d1678b03cf7fc8b8dcfb1651e8c4a524eb42ef", + "sha256:8d963da00ccdf06e356acd9bf3b743208878751032d8599c6cc89eb51310ffae" ], "markers": "python_version >= '3.8'", - "version": "==25.0.0" + "version": "==25.3.0" }, "markdown-it-py": { "hashes": [ @@ -924,19 +946,11 @@ }, "matplotlib-inline": { "hashes": [ - "sha256:f1f41aab5328aa5aaea9b16d083b128102f8712542f819fe7e6a420ff581b311", - "sha256:f887e5f10ba98e8d2b150ddcf4702c1e5f8b3a20005eb0f74bfdbd360ee6f304" - ], - "markers": "python_version >= '3.5'", - "version": "==0.1.6" - }, - "mccabe": { - "hashes": [ - "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325", - "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e" + "sha256:8423b23ec666be3d16e16b60bdd8ac4e86e840ebd1dd11a30b9f117f2fa0ab90", + "sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca" ], - "markers": "python_version >= '3.6'", - "version": "==0.7.0" + "markers": "python_version >= '3.8'", + "version": "==0.1.7" }, "mdurl": { "hashes": [ @@ -956,11 +970,11 @@ }, "more-itertools": { "hashes": [ - "sha256:686b06abe565edfab151cb8fd385a05651e1fdf8f0a14191e4439283421f8684", - "sha256:8fccb480c43d3e99a00087634c06dd02b0d50fbf088b380de5a41a015ec239e1" + "sha256:037b0d3203ce90cca8ab1defbbdac29d5f993fc20131f3664dc8d6acfa872aef", + "sha256:5482bfef7849c25dc3c6dd53a6173ae4795da2a41a80faea6700d9f5846c5da6" ], "markers": "python_version >= '3.8'", - "version": "==10.2.0" + "version": "==10.5.0" }, "mypy-extensions": { "hashes": [ @@ -980,19 +994,19 @@ }, "nbconvert": { "hashes": [ - "sha256:a6733b78ce3d47c3f85e504998495b07e6ea9cf9bf6ec1c98dda63ec6ad19142", - "sha256:ddeff14beeeedf3dd0bc506623e41e4507e551736de59df69a91f86700292b3b" + "sha256:05873c620fe520b6322bf8a5ad562692343fe3452abda5765c7a34b7d1aa3eb3", + "sha256:86ca91ba266b0a448dc96fa6c5b9d98affabde2867b363258703536807f9f7f4" ], "markers": "python_version >= '3.8'", - "version": "==7.16.3" + "version": "==7.16.4" }, "nbformat": { "hashes": [ - "sha256:60ed5e910ef7c6264b87d644f276b1b49e24011930deef54605188ddeb211685", - "sha256:d9476ca28676799af85385f409b49d95e199951477a159a576ef2a675151e5e8" + "sha256:322168b14f937a5d11362988ecac2a4952d3d8e3a2cbeb2319584631226d5b3a", + "sha256:3b48d6c8fbca4b299bf3982ea7db1af21580e4fec269ad087b9e81588891200b" ], "markers": "python_version >= '3.8'", - "version": "==5.10.3" + "version": "==5.10.4" }, "nest-asyncio": { "hashes": [ @@ -1004,33 +1018,33 @@ }, "nh3": { "hashes": [ - "sha256:0316c25b76289cf23be6b66c77d3608a4fdf537b35426280032f432f14291b9a", - "sha256:1a814dd7bba1cb0aba5bcb9bebcc88fd801b63e21e2450ae6c52d3b3336bc911", - "sha256:1aa52a7def528297f256de0844e8dd680ee279e79583c76d6fa73a978186ddfb", - "sha256:22c26e20acbb253a5bdd33d432a326d18508a910e4dcf9a3316179860d53345a", - "sha256:40015514022af31975c0b3bca4014634fa13cb5dc4dbcbc00570acc781316dcc", - "sha256:40d0741a19c3d645e54efba71cb0d8c475b59135c1e3c580f879ad5514cbf028", - "sha256:551672fd71d06cd828e282abdb810d1be24e1abb7ae2543a8fa36a71c1006fe9", - "sha256:66f17d78826096291bd264f260213d2b3905e3c7fae6dfc5337d49429f1dc9f3", - "sha256:85cdbcca8ef10733bd31f931956f7fbb85145a4d11ab9e6742bbf44d88b7e351", - "sha256:a3f55fabe29164ba6026b5ad5c3151c314d136fd67415a17660b4aaddacf1b10", - "sha256:b4427ef0d2dfdec10b641ed0bdaf17957eb625b2ec0ea9329b3d28806c153d71", - "sha256:ba73a2f8d3a1b966e9cdba7b211779ad8a2561d2dba9674b8a19ed817923f65f", - "sha256:c21bac1a7245cbd88c0b0e4a420221b7bfa838a2814ee5bb924e9c2f10a1120b", - "sha256:c551eb2a3876e8ff2ac63dff1585236ed5dfec5ffd82216a7a174f7c5082a78a", - "sha256:c790769152308421283679a142dbdb3d1c46c79c823008ecea8e8141db1a2062", - "sha256:d7a25fd8c86657f5d9d576268e3b3767c5cd4f42867c9383618be8517f0f022a" - ], - "version": "==0.2.17" + "sha256:0411beb0589eacb6734f28d5497ca2ed379eafab8ad8c84b31bb5c34072b7164", + "sha256:14c5a72e9fe82aea5fe3072116ad4661af5cf8e8ff8fc5ad3450f123e4925e86", + "sha256:19aaba96e0f795bd0a6c56291495ff59364f4300d4a39b29a0abc9cb3774a84b", + "sha256:34c03fa78e328c691f982b7c03d4423bdfd7da69cd707fe572f544cf74ac23ad", + "sha256:36c95d4b70530b320b365659bb5034341316e6a9b30f0b25fa9c9eff4c27a204", + "sha256:3a157ab149e591bb638a55c8c6bcb8cdb559c8b12c13a8affaba6cedfe51713a", + "sha256:42c64511469005058cd17cc1537578eac40ae9f7200bedcfd1fc1a05f4f8c200", + "sha256:5f36b271dae35c465ef5e9090e1fdaba4a60a56f0bb0ba03e0932a66f28b9189", + "sha256:6955369e4d9f48f41e3f238a9e60f9410645db7e07435e62c6a9ea6135a4907f", + "sha256:7b7c2a3c9eb1a827d42539aa64091640bd275b81e097cd1d8d82ef91ffa2e811", + "sha256:8ce0f819d2f1933953fca255db2471ad58184a60508f03e6285e5114b6254844", + "sha256:94a166927e53972a9698af9542ace4e38b9de50c34352b962f4d9a7d4c927af4", + "sha256:a7f1b5b2c15866f2db413a3649a8fe4fd7b428ae58be2c0f6bca5eefd53ca2be", + "sha256:c8b3a1cebcba9b3669ed1a84cc65bf005728d2f0bc1ed2a6594a992e817f3a50", + "sha256:de3ceed6e661954871d6cd78b410213bdcb136f79aafe22aa7182e028b8c7307", + "sha256:f0eca9ca8628dbb4e916ae2491d72957fdd35f7a5d326b7032a345f111ac07fe" + ], + "version": "==0.2.18" }, "notebook": { "hashes": [ - "sha256:efc2c80043909e0faa17fce9e9b37c059c03af0ec99a4d4db84cb21d9d2e936a", - "sha256:fc6c24b9aef18d0cd57157c9c47e95833b9b0bdc599652639acf0bdb61dc7d5f" + "sha256:2ef07d4220421623ad3fe88118d687bc0450055570cdd160814a59cf3a1c516e", + "sha256:c89264081f671bc02eec0ed470a627ed791b9156cad9285226b31611d3e9fe1c" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==7.1.2" + "version": "==7.2.2" }, "notebook-shim": { "hashes": [ @@ -1054,11 +1068,11 @@ }, "packaging": { "hashes": [ - "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5", - "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9" + "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002", + "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124" ], - "markers": "python_version >= '3.7'", - "version": "==24.0" + "markers": "python_version >= '3.8'", + "version": "==24.1" }, "pandocfilters": { "hashes": [ @@ -1070,11 +1084,11 @@ }, "parso": { "hashes": [ - "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0", - "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75" + "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18", + "sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d" ], "markers": "python_version >= '3.6'", - "version": "==0.8.3" + "version": "==0.8.4" }, "pathspec": { "hashes": [ @@ -1102,19 +1116,19 @@ }, "platformdirs": { "hashes": [ - "sha256:0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068", - "sha256:ef0cc731df711022c174543cb70a9b5bd22e5a9337c8624ef2c2ceb8ddad8768" + "sha256:9e5e27a08aa095dd127b9f2e764d74254f482fef22b0970773bfba79d091ab8c", + "sha256:eb1c8582560b34ed4ba105009a4badf7f6f85768b30126f351328507b2beb617" ], "markers": "python_version >= '3.8'", - "version": "==4.2.0" + "version": "==4.3.2" }, "pluggy": { "hashes": [ - "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981", - "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be" + "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", + "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669" ], "markers": "python_version >= '3.8'", - "version": "==1.4.0" + "version": "==1.5.0" }, "prometheus-client": { "hashes": [ @@ -1126,33 +1140,34 @@ }, "prompt-toolkit": { "hashes": [ - "sha256:3527b7af26106cbc65a040bcc84839a3566ec1b051bb0bfe953631e704b0ff7d", - "sha256:a11a29cb3bf0a28a387fe5122cdb649816a957cd9261dcedf8c9f1fef33eacf6" + "sha256:0d7bfa67001d5e39d02c224b663abc33687405033a8c422d0d675a5a13361d10", + "sha256:1e1b29cb58080b1e69f207c893a1a7bf16d127a5c30c9d17a25a5d77792e5360" ], "markers": "python_full_version >= '3.7.0'", - "version": "==3.0.43" + "version": "==3.0.47" }, "psutil": { "hashes": [ - "sha256:02615ed8c5ea222323408ceba16c60e99c3f91639b07da6373fb7e6539abc56d", - "sha256:05806de88103b25903dff19bb6692bd2e714ccf9e668d050d144012055cbca73", - "sha256:26bd09967ae00920df88e0352a91cff1a78f8d69b3ecabbfe733610c0af486c8", - "sha256:27cc40c3493bb10de1be4b3f07cae4c010ce715290a5be22b98493509c6299e2", - "sha256:36f435891adb138ed3c9e58c6af3e2e6ca9ac2f365efe1f9cfef2794e6c93b4e", - "sha256:50187900d73c1381ba1454cf40308c2bf6f34268518b3f36a9b663ca87e65e36", - "sha256:611052c4bc70432ec770d5d54f64206aa7203a101ec273a0cd82418c86503bb7", - "sha256:6be126e3225486dff286a8fb9a06246a5253f4c7c53b475ea5f5ac934e64194c", - "sha256:7d79560ad97af658a0f6adfef8b834b53f64746d45b403f225b85c5c2c140eee", - "sha256:8cb6403ce6d8e047495a701dc7c5bd788add903f8986d523e3e20b98b733e421", - "sha256:8db4c1b57507eef143a15a6884ca10f7c73876cdf5d51e713151c1236a0e68cf", - "sha256:aee678c8720623dc456fa20659af736241f575d79429a0e5e9cf88ae0605cc81", - "sha256:bc56c2a1b0d15aa3eaa5a60c9f3f8e3e565303b465dbf57a1b730e7a2b9844e0", - "sha256:bd1184ceb3f87651a67b2708d4c3338e9b10c5df903f2e3776b62303b26cb631", - "sha256:d06016f7f8625a1825ba3732081d77c94589dca78b7a3fc072194851e88461a4", - "sha256:d16bbddf0693323b8c6123dd804100241da461e41d6e332fb0ba6058f630f8c8" + "sha256:02b69001f44cc73c1c5279d02b30a817e339ceb258ad75997325e0e6169d8b35", + "sha256:1287c2b95f1c0a364d23bc6f2ea2365a8d4d9b726a3be7294296ff7ba97c17f0", + "sha256:1e7c870afcb7d91fdea2b37c24aeb08f98b6d67257a5cb0a8bc3ac68d0f1a68c", + "sha256:21f1fb635deccd510f69f485b87433460a603919b45e2a324ad65b0cc74f8fb1", + "sha256:33ea5e1c975250a720b3a6609c490db40dae5d83a4eb315170c4fe0d8b1f34b3", + "sha256:34859b8d8f423b86e4385ff3665d3f4d94be3cdf48221fbe476e883514fdb71c", + "sha256:5fd9a97c8e94059b0ef54a7d4baf13b405011176c3b6ff257c247cae0d560ecd", + "sha256:6ec7588fb3ddaec7344a825afe298db83fe01bfaaab39155fa84cf1c0d6b13c3", + "sha256:6ed2440ada7ef7d0d608f20ad89a04ec47d2d3ab7190896cd62ca5fc4fe08bf0", + "sha256:8faae4f310b6d969fa26ca0545338b21f73c6b15db7c4a8d934a5482faa818f2", + "sha256:a021da3e881cd935e64a3d0a20983bda0bb4cf80e4f74fa9bfcb1bc5785360c6", + "sha256:a495580d6bae27291324fe60cea0b5a7c23fa36a7cd35035a16d93bdcf076b9d", + "sha256:a9a3dbfb4de4f18174528d87cc352d1f788b7496991cca33c6996f40c9e3c92c", + "sha256:c588a7e9b1173b6e866756dde596fd4cad94f9399daf99ad8c3258b3cb2b47a0", + "sha256:e2e8d0054fc88153ca0544f5c4d554d42e33df2e009c4ff42284ac9ebdef4132", + "sha256:fc8c9510cde0146432bbdb433322861ee8c3efbf8589865c8bf8d21cb30c4d14", + "sha256:ffe7fc9b6b36beadc8c322f84e1caff51e8703b88eee1da46d1e3a6ae11b4fd0" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", - "version": "==5.9.8" + "version": "==6.0.0" }, "ptyprocess": { "hashes": [ @@ -1163,53 +1178,45 @@ }, "pure-eval": { "hashes": [ - "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350", - "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3" + "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0", + "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42" ], - "version": "==0.2.2" + "version": "==0.2.3" }, "pycparser": { "hashes": [ - "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9", - "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206" + "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", + "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc" ], - "version": "==2.21" + "markers": "python_version >= '3.8'", + "version": "==2.22" }, "pygithub": { "hashes": [ - "sha256:0148d7347a1cdeed99af905077010aef81a4dad988b0ba51d4108bf66b443f7e", - "sha256:65b499728be3ce7b0cd2cd760da3b32f0f4d7bc55e5e0677617f90f6564e793e" + "sha256:6601e22627e87bac192f1e2e39c6e6f69a43152cfb8f307cee575879320b3051", + "sha256:81935aa4bdc939fba98fee1cb47422c09157c56a27966476ff92775602b9ee24" ], - "markers": "python_version >= '3.7'", - "version": "==2.3.0" + "markers": "python_version >= '3.8'", + "version": "==2.4.0" }, "pygments": { "hashes": [ - "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c", - "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367" + "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199", + "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a" ], - "markers": "python_version >= '3.7'", - "version": "==2.17.2" + "markers": "python_version >= '3.8'", + "version": "==2.18.0" }, "pyjwt": { "extras": [ "crypto" ], "hashes": [ - "sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de", - "sha256:59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320" - ], - "markers": "python_version >= '3.7'", - "version": "==2.8.0" - }, - "pylint": { - "hashes": [ - "sha256:507a5b60953874766d8a366e8e8c7af63e058b26345cfcb5f91f89d987fd6b74", - "sha256:6a69beb4a6f63debebaab0a3477ecd0f559aa726af4954fc948c51f7a2549e23" + "sha256:3b02fb0f44517787776cf48f2ae25d8e14f300e6d7545a4315cee571a415e850", + "sha256:7e1e5b56cc735432a7369cbfa0efe50fa113ebecdc04ae6922deba8b84582d0c" ], - "index": "pypi", - "markers": "python_full_version >= '3.8.0'", - "version": "==3.1.0" + "markers": "python_version >= '3.8'", + "version": "==2.9.0" }, "pynacl": { "hashes": [ @@ -1229,28 +1236,28 @@ }, "pyparsing": { "hashes": [ - "sha256:a1bac0ce561155ecc3ed78ca94d3c9378656ad4c94c1270de543f621420f94ad", - "sha256:f9db75911801ed778fe61bb643079ff86601aca99fcae6345aa67292038fb742" + "sha256:a6a7ee4235a3f944aa1fa2249307708f893fe5717dc603503c6c7969c070fb7c", + "sha256:f86ec8d1a83f11977c9a6ea7598e8c27fc5cddfa5b07ea2241edbbde1d7bc032" ], "markers": "python_full_version >= '3.6.8'", - "version": "==3.1.2" + "version": "==3.1.4" }, "pyproject-api": { "hashes": [ - "sha256:1817dc018adc0d1ff9ca1ed8c60e1623d5aaca40814b953af14a9cf9a5cae538", - "sha256:4c0116d60476b0786c88692cf4e325a9814965e2469c5998b830bba16b183675" + "sha256:2dc1654062c2b27733d8fd4cdda672b22fe8741ef1dde8e3a998a9547b071eeb", + "sha256:7ebc6cd10710f89f4cf2a2731710a98abce37ebff19427116ff2174c9236a827" ], "markers": "python_version >= '3.8'", - "version": "==1.6.1" + "version": "==1.7.1" }, "pytest": { "hashes": [ - "sha256:2a8386cfc11fa9d2c50ee7b2a57e7d898ef90470a7a34c4b949ff59662bb78b7", - "sha256:ac978141a75948948817d360297b7aae0fcb9d6ff6bc9ec6d514b85d5a65c044" + "sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181", + "sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==8.1.1" + "version": "==8.3.3" }, "pytest-cov": { "hashes": [ @@ -1279,159 +1286,178 @@ }, "pyyaml": { "hashes": [ - "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" + "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff", + "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", + "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086", + "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e", + "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", + "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5", + "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", + "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee", + "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", + "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68", + "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a", + "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf", + "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99", + "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8", + "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85", + "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19", + "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", + "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a", + "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", + "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317", + "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c", + "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631", + "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d", + "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", + "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", + "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e", + "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b", + "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", + "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", + "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706", + "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", + "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237", + "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", + "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083", + "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180", + "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", + "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e", + "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f", + "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725", + "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", + "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", + "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774", + "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", + "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", + "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5", + "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d", + "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290", + "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44", + "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed", + "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", + "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", + "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12", + "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4" ], - "markers": "python_version >= '3.6'", - "version": "==6.0.1" + "index": "pypi", + "markers": "python_version >= '3.8'", + "version": "==6.0.2" }, "pyzmq": { "hashes": [ - "sha256:004ff469d21e86f0ef0369717351073e0e577428e514c47c8480770d5e24a565", - "sha256:00a06faa7165634f0cac1abb27e54d7a0b3b44eb9994530b8ec73cf52e15353b", - "sha256:00c48ae2fd81e2a50c3485de1b9d5c7c57cd85dc8ec55683eac16846e57ac979", - "sha256:01171fc48542348cd1a360a4b6c3e7d8f46cdcf53a8d40f84db6707a6768acc1", - "sha256:019744b99da30330798bb37df33549d59d380c78e516e3bab9c9b84f87a9592f", - "sha256:02bbc1a87b76e04fd780b45e7f695471ae6de747769e540da909173d50ff8e2d", - "sha256:02c9087b109070c5ab0b383079fa1b5f797f8d43e9a66c07a4b8b8bdecfd88ee", - "sha256:07cd61a20a535524906595e09344505a9bd46f1da7a07e504b315d41cd42eb07", - "sha256:0806175f2ae5ad4b835ecd87f5f85583316b69f17e97786f7443baaf54b9bb98", - "sha256:09dfe949e83087da88c4a76767df04b22304a682d6154de2c572625c62ad6886", - "sha256:0dabfb10ef897f3b7e101cacba1437bd3a5032ee667b7ead32bbcdd1a8422fe7", - "sha256:0ddd6d71d4ef17ba5a87becf7ddf01b371eaba553c603477679ae817a8d84d75", - "sha256:0f513130c4c361201da9bc69df25a086487250e16b5571ead521b31ff6b02220", - "sha256:0f97bc2f1f13cb16905a5f3e1fbdf100e712d841482b2237484360f8bc4cb3d7", - "sha256:11e70516688190e9c2db14fcf93c04192b02d457b582a1f6190b154691b4c93a", - "sha256:146b9b1f29ead41255387fb07be56dc29639262c0f7344f570eecdcd8d683314", - "sha256:16b726c1f6c2e7625706549f9dbe9b06004dfbec30dbed4bf50cbdfc73e5b32a", - "sha256:1b3cbba2f47062b85fe0ef9de5b987612140a9ba3a9c6d2543c6dec9f7c2ab27", - "sha256:1b9b1f2ad6498445a941d9a4fee096d387fee436e45cc660e72e768d3d8ee611", - "sha256:1ec23bd7b3a893ae676d0e54ad47d18064e6c5ae1fadc2f195143fb27373f7f6", - "sha256:246747b88917e4867e2367b005fc8eefbb4a54b7db363d6c92f89d69abfff4b6", - "sha256:25c2dbb97d38b5ac9fd15586e048ec5eb1e38f3d47fe7d92167b0c77bb3584e9", - "sha256:2c6441e0398c2baacfe5ba30c937d274cfc2dc5b55e82e3749e333aabffde561", - "sha256:2c9a79f1d2495b167119d02be7448bfba57fad2a4207c4f68abc0bab4b92925b", - "sha256:2e2713ef44be5d52dd8b8e2023d706bf66cb22072e97fc71b168e01d25192755", - "sha256:313c3794d650d1fccaaab2df942af9f2c01d6217c846177cfcbc693c7410839e", - "sha256:3516e0b6224cf6e43e341d56da15fd33bdc37fa0c06af4f029f7d7dfceceabbc", - "sha256:359f7f74b5d3c65dae137f33eb2bcfa7ad9ebefd1cab85c935f063f1dbb245cc", - "sha256:39b1067f13aba39d794a24761e385e2eddc26295826530a8c7b6c6c341584289", - "sha256:3c00c9b7d1ca8165c610437ca0c92e7b5607b2f9076f4eb4b095c85d6e680a1d", - "sha256:3c53687dde4d9d473c587ae80cc328e5b102b517447456184b485587ebd18b62", - "sha256:3e124e6b1dd3dfbeb695435dff0e383256655bb18082e094a8dd1f6293114642", - "sha256:4345c9a27f4310afbb9c01750e9461ff33d6fb74cd2456b107525bbeebcb5be3", - "sha256:45999e7f7ed5c390f2e87ece7f6c56bf979fb213550229e711e45ecc7d42ccb8", - "sha256:49151b0efece79f6a79d41a461d78535356136ee70084a1c22532fc6383f4ad0", - "sha256:4cb8fc1f8d69b411b8ec0b5f1ffbcaf14c1db95b6bccea21d83610987435f1a4", - "sha256:4e5837af3e5aaa99a091302df5ee001149baff06ad22b722d34e30df5f0d9097", - "sha256:4e6f689880d5ad87918430957297c975203a082d9a036cc426648fcbedae769b", - "sha256:5074adeacede5f810b7ef39607ee59d94e948b4fd954495bdb072f8c54558181", - "sha256:518efd91c3d8ac9f9b4f7dd0e2b7b8bf1a4fe82a308009016b07eaa48681af82", - "sha256:55875492f820d0eb3417b51d96fea549cde77893ae3790fd25491c5754ea2f68", - "sha256:5a68d491fc20762b630e5db2191dd07ff89834086740f70e978bb2ef2668be08", - "sha256:5dde6751e857910c1339890f3524de74007958557593b9e7e8c5f01cd919f8a7", - "sha256:5e319ed7d6b8f5fad9b76daa0a68497bc6f129858ad956331a5835785761e003", - "sha256:5edac3f57c7ddaacdb4d40f6ef2f9e299471fc38d112f4bc6d60ab9365445fb0", - "sha256:6cc0020b74b2e410287e5942e1e10886ff81ac77789eb20bec13f7ae681f0fdd", - "sha256:6dd0d50bbf9dca1d0bdea219ae6b40f713a3fb477c06ca3714f208fd69e16fd8", - "sha256:7598d2ba821caa37a0f9d54c25164a4fa351ce019d64d0b44b45540950458840", - "sha256:759cfd391a0996345ba94b6a5110fca9c557ad4166d86a6e81ea526c376a01e8", - "sha256:7ae8f354b895cbd85212da245f1a5ad8159e7840e37d78b476bb4f4c3f32a9fe", - "sha256:7b6d09a8962a91151f0976008eb7b29b433a560fde056ec7a3db9ec8f1075438", - "sha256:7c61e346ac34b74028ede1c6b4bcecf649d69b707b3ff9dc0fab453821b04d1e", - "sha256:7f51a7b4ead28d3fca8dda53216314a553b0f7a91ee8fc46a72b402a78c3e43d", - "sha256:82544e0e2d0c1811482d37eef297020a040c32e0687c1f6fc23a75b75db8062c", - "sha256:8807c87fa893527ae8a524c15fc505d9950d5e856f03dae5921b5e9aa3b8783b", - "sha256:889370d5174a741a62566c003ee8ddba4b04c3f09a97b8000092b7ca83ec9c49", - "sha256:8b14c75979ce932c53b79976a395cb2a8cd3aaf14aef75e8c2cb55a330b9b49d", - "sha256:8c5f80e578427d4695adac6fdf4370c14a2feafdc8cb35549c219b90652536ae", - "sha256:8e9f3fabc445d0ce320ea2c59a75fe3ea591fdbdeebec5db6de530dd4b09412e", - "sha256:93f1aa311e8bb912e34f004cf186407a4e90eec4f0ecc0efd26056bf7eda0226", - "sha256:94504ff66f278ab4b7e03e4cba7e7e400cb73bfa9d3d71f58d8972a8dc67e7a6", - "sha256:967668420f36878a3c9ecb5ab33c9d0ff8d054f9c0233d995a6d25b0e95e1b6b", - "sha256:9880078f683466b7f567b8624bfc16cad65077be046b6e8abb53bed4eeb82dd3", - "sha256:99a6b36f95c98839ad98f8c553d8507644c880cf1e0a57fe5e3a3f3969040882", - "sha256:9a18fff090441a40ffda8a7f4f18f03dc56ae73f148f1832e109f9bffa85df15", - "sha256:9add2e5b33d2cd765ad96d5eb734a5e795a0755f7fc49aa04f76d7ddda73fd70", - "sha256:a793ac733e3d895d96f865f1806f160696422554e46d30105807fdc9841b9f7d", - "sha256:a86c2dd76ef71a773e70551a07318b8e52379f58dafa7ae1e0a4be78efd1ff16", - "sha256:a8c1d566344aee826b74e472e16edae0a02e2a044f14f7c24e123002dcff1c05", - "sha256:ac170e9e048b40c605358667aca3d94e98f604a18c44bdb4c102e67070f3ac9b", - "sha256:b264bf2cc96b5bc43ce0e852be995e400376bd87ceb363822e2cb1964fcdc737", - "sha256:b8c8a419dfb02e91b453615c69568442e897aaf77561ee0064d789705ff37a92", - "sha256:bc69c96735ab501419c432110016329bf0dea8898ce16fab97c6d9106dc0b348", - "sha256:bef02cfcbded83473bdd86dd8d3729cd82b2e569b75844fb4ea08fee3c26ae41", - "sha256:c0b5ca88a8928147b7b1e2dfa09f3b6c256bc1135a1338536cbc9ea13d3b7add", - "sha256:cc69949484171cc961e6ecd4a8911b9ce7a0d1f738fcae717177c231bf77437b", - "sha256:ced111c2e81506abd1dc142e6cd7b68dd53747b3b7ae5edbea4578c5eeff96b7", - "sha256:d1299d7e964c13607efd148ca1f07dcbf27c3ab9e125d1d0ae1d580a1682399d", - "sha256:d1b604734bec94f05f81b360a272fc824334267426ae9905ff32dc2be433ab96", - "sha256:d9a5f194cf730f2b24d6af1f833c14c10f41023da46a7f736f48b6d35061e76e", - "sha256:db36c27baed588a5a8346b971477b718fdc66cf5b80cbfbd914b4d6d355e44e2", - "sha256:df0c7a16ebb94452d2909b9a7b3337940e9a87a824c4fc1c7c36bb4404cb0cde", - "sha256:e10a4b5a4b1192d74853cc71a5e9fd022594573926c2a3a4802020360aa719d8", - "sha256:e624c789359f1a16f83f35e2c705d07663ff2b4d4479bad35621178d8f0f6ea4", - "sha256:e690145a8c0c273c28d3b89d6fb32c45e0d9605b2293c10e650265bf5c11cfec", - "sha256:ea1608dd169da230a0ad602d5b1ebd39807ac96cae1845c3ceed39af08a5c6df", - "sha256:ea253b368eb41116011add00f8d5726762320b1bda892f744c91997b65754d73", - "sha256:eb7e49a17fb8c77d3119d41a4523e432eb0c6932187c37deb6fbb00cc3028088", - "sha256:ef12e259e7bc317c7597d4f6ef59b97b913e162d83b421dd0db3d6410f17a244", - "sha256:f8429b17cbb746c3e043cb986328da023657e79d5ed258b711c06a70c2ea7537", - "sha256:fa99973d2ed20417744fca0073390ad65ce225b546febb0580358e36aa90dba6", - "sha256:faf79a302f834d9e8304fafdc11d0d042266667ac45209afa57e5efc998e3872", - "sha256:fc31baa0c32a2ca660784d5af3b9487e13b61b3032cb01a115fce6588e1bed30" + "sha256:007137c9ac9ad5ea21e6ad97d3489af654381324d5d3ba614c323f60dab8fae6", + "sha256:034da5fc55d9f8da09015d368f519478a52675e558c989bfcb5cf6d4e16a7d2a", + "sha256:05590cdbc6b902101d0e65d6a4780af14dc22914cc6ab995d99b85af45362cc9", + "sha256:070672c258581c8e4f640b5159297580a9974b026043bd4ab0470be9ed324f1f", + "sha256:0aca98bc423eb7d153214b2df397c6421ba6373d3397b26c057af3c904452e37", + "sha256:0bed0e799e6120b9c32756203fb9dfe8ca2fb8467fed830c34c877e25638c3fc", + "sha256:0d987a3ae5a71c6226b203cfd298720e0086c7fe7c74f35fa8edddfbd6597eed", + "sha256:0eaa83fc4c1e271c24eaf8fb083cbccef8fde77ec8cd45f3c35a9a123e6da097", + "sha256:160c7e0a5eb178011e72892f99f918c04a131f36056d10d9c1afb223fc952c2d", + "sha256:17bf5a931c7f6618023cdacc7081f3f266aecb68ca692adac015c383a134ca52", + "sha256:17c412bad2eb9468e876f556eb4ee910e62d721d2c7a53c7fa31e643d35352e6", + "sha256:18c8dc3b7468d8b4bdf60ce9d7141897da103c7a4690157b32b60acb45e333e6", + "sha256:1a534f43bc738181aa7cbbaf48e3eca62c76453a40a746ab95d4b27b1111a7d2", + "sha256:1c17211bc037c7d88e85ed8b7d8f7e52db6dc8eca5590d162717c654550f7282", + "sha256:1f3496d76b89d9429a656293744ceca4d2ac2a10ae59b84c1da9b5165f429ad3", + "sha256:1fcc03fa4997c447dce58264e93b5aa2d57714fbe0f06c07b7785ae131512732", + "sha256:226af7dcb51fdb0109f0016449b357e182ea0ceb6b47dfb5999d569e5db161d5", + "sha256:23f4aad749d13698f3f7b64aad34f5fc02d6f20f05999eebc96b89b01262fb18", + "sha256:25bf2374a2a8433633c65ccb9553350d5e17e60c8eb4de4d92cc6bd60f01d306", + "sha256:28ad5233e9c3b52d76196c696e362508959741e1a005fb8fa03b51aea156088f", + "sha256:28c812d9757fe8acecc910c9ac9dafd2ce968c00f9e619db09e9f8f54c3a68a3", + "sha256:29c6a4635eef69d68a00321e12a7d2559fe2dfccfa8efae3ffb8e91cd0b36a8b", + "sha256:29c7947c594e105cb9e6c466bace8532dc1ca02d498684128b339799f5248277", + "sha256:2a50625acdc7801bc6f74698c5c583a491c61d73c6b7ea4dee3901bb99adb27a", + "sha256:2ae90ff9dad33a1cfe947d2c40cb9cb5e600d759ac4f0fd22616ce6540f72797", + "sha256:2c4a71d5d6e7b28a47a394c0471b7e77a0661e2d651e7ae91e0cab0a587859ca", + "sha256:2ea4ad4e6a12e454de05f2949d4beddb52460f3de7c8b9d5c46fbb7d7222e02c", + "sha256:2eb7735ee73ca1b0d71e0e67c3739c689067f055c764f73aac4cc8ecf958ee3f", + "sha256:31507f7b47cc1ead1f6e86927f8ebb196a0bab043f6345ce070f412a59bf87b5", + "sha256:35cffef589bcdc587d06f9149f8d5e9e8859920a071df5a2671de2213bef592a", + "sha256:367b4f689786fca726ef7a6c5ba606958b145b9340a5e4808132cc65759abd44", + "sha256:39887ac397ff35b7b775db7201095fc6310a35fdbae85bac4523f7eb3b840e20", + "sha256:3a495b30fc91db2db25120df5847d9833af237546fd59170701acd816ccc01c4", + "sha256:3b55a4229ce5da9497dd0452b914556ae58e96a4381bb6f59f1305dfd7e53fc8", + "sha256:402b190912935d3db15b03e8f7485812db350d271b284ded2b80d2e5704be780", + "sha256:43a47408ac52647dfabbc66a25b05b6a61700b5165807e3fbd40063fcaf46386", + "sha256:4661c88db4a9e0f958c8abc2b97472e23061f0bc737f6f6179d7a27024e1faa5", + "sha256:46a446c212e58456b23af260f3d9fb785054f3e3653dbf7279d8f2b5546b21c2", + "sha256:470d4a4f6d48fb34e92d768b4e8a5cc3780db0d69107abf1cd7ff734b9766eb0", + "sha256:49d34ab71db5a9c292a7644ce74190b1dd5a3475612eefb1f8be1d6961441971", + "sha256:4d29ab8592b6ad12ebbf92ac2ed2bedcfd1cec192d8e559e2e099f648570e19b", + "sha256:4d80b1dd99c1942f74ed608ddb38b181b87476c6a966a88a950c7dee118fdf50", + "sha256:4da04c48873a6abdd71811c5e163bd656ee1b957971db7f35140a2d573f6949c", + "sha256:4f78c88905461a9203eac9faac157a2a0dbba84a0fd09fd29315db27be40af9f", + "sha256:4ff9dc6bc1664bb9eec25cd17506ef6672d506115095411e237d571e92a58231", + "sha256:5506f06d7dc6ecf1efacb4a013b1f05071bb24b76350832c96449f4a2d95091c", + "sha256:55cf66647e49d4621a7e20c8d13511ef1fe1efbbccf670811864452487007e08", + "sha256:5a509df7d0a83a4b178d0f937ef14286659225ef4e8812e05580776c70e155d5", + "sha256:5c2b3bfd4b9689919db068ac6c9911f3fcb231c39f7dd30e3138be94896d18e6", + "sha256:6835dd60355593de10350394242b5757fbbd88b25287314316f266e24c61d073", + "sha256:689c5d781014956a4a6de61d74ba97b23547e431e9e7d64f27d4922ba96e9d6e", + "sha256:6a96179a24b14fa6428cbfc08641c779a53f8fcec43644030328f44034c7f1f4", + "sha256:6ace4f71f1900a548f48407fc9be59c6ba9d9aaf658c2eea6cf2779e72f9f317", + "sha256:6b274e0762c33c7471f1a7471d1a2085b1a35eba5cdc48d2ae319f28b6fc4de3", + "sha256:706e794564bec25819d21a41c31d4df2d48e1cc4b061e8d345d7fb4dd3e94072", + "sha256:70fc7fcf0410d16ebdda9b26cbd8bf8d803d220a7f3522e060a69a9c87bf7bad", + "sha256:7133d0a1677aec369d67dd78520d3fa96dd7f3dcec99d66c1762870e5ea1a50a", + "sha256:7445be39143a8aa4faec43b076e06944b8f9d0701b669df4af200531b21e40bb", + "sha256:76589c020680778f06b7e0b193f4b6dd66d470234a16e1df90329f5e14a171cd", + "sha256:76589f2cd6b77b5bdea4fca5992dc1c23389d68b18ccc26a53680ba2dc80ff2f", + "sha256:77eb0968da535cba0470a5165468b2cac7772cfb569977cff92e240f57e31bef", + "sha256:794a4562dcb374f7dbbfb3f51d28fb40123b5a2abadee7b4091f93054909add5", + "sha256:7ad1bc8d1b7a18497dda9600b12dc193c577beb391beae5cd2349184db40f187", + "sha256:7f98f6dfa8b8ccaf39163ce872bddacca38f6a67289116c8937a02e30bbe9711", + "sha256:8423c1877d72c041f2c263b1ec6e34360448decfb323fa8b94e85883043ef988", + "sha256:8685fa9c25ff00f550c1fec650430c4b71e4e48e8d852f7ddcf2e48308038640", + "sha256:878206a45202247781472a2d99df12a176fef806ca175799e1c6ad263510d57c", + "sha256:89289a5ee32ef6c439086184529ae060c741334b8970a6855ec0b6ad3ff28764", + "sha256:8ab5cad923cc95c87bffee098a27856c859bd5d0af31bd346035aa816b081fe1", + "sha256:8b435f2753621cd36e7c1762156815e21c985c72b19135dac43a7f4f31d28dd1", + "sha256:8be4700cd8bb02cc454f630dcdf7cfa99de96788b80c51b60fe2fe1dac480289", + "sha256:8c997098cc65e3208eca09303630e84d42718620e83b733d0fd69543a9cab9cb", + "sha256:8ea039387c10202ce304af74def5021e9adc6297067f3441d348d2b633e8166a", + "sha256:8f7e66c7113c684c2b3f1c83cdd3376103ee0ce4c49ff80a648643e57fb22218", + "sha256:90412f2db8c02a3864cbfc67db0e3dcdbda336acf1c469526d3e869394fe001c", + "sha256:92a78853d7280bffb93df0a4a6a2498cba10ee793cc8076ef797ef2f74d107cf", + "sha256:989d842dc06dc59feea09e58c74ca3e1678c812a4a8a2a419046d711031f69c7", + "sha256:9cb3a6460cdea8fe8194a76de8895707e61ded10ad0be97188cc8463ffa7e3a8", + "sha256:9dd8cd1aeb00775f527ec60022004d030ddc51d783d056e3e23e74e623e33726", + "sha256:9ed69074a610fad1c2fda66180e7b2edd4d31c53f2d1872bc2d1211563904cd9", + "sha256:9edda2df81daa129b25a39b86cb57dfdfe16f7ec15b42b19bfac503360d27a93", + "sha256:a2224fa4a4c2ee872886ed00a571f5e967c85e078e8e8c2530a2fb01b3309b88", + "sha256:a4f96f0d88accc3dbe4a9025f785ba830f968e21e3e2c6321ccdfc9aef755115", + "sha256:aedd5dd8692635813368e558a05266b995d3d020b23e49581ddd5bbe197a8ab6", + "sha256:aee22939bb6075e7afededabad1a56a905da0b3c4e3e0c45e75810ebe3a52672", + "sha256:b1d464cb8d72bfc1a3adc53305a63a8e0cac6bc8c5a07e8ca190ab8d3faa43c2", + "sha256:b8f86dd868d41bea9a5f873ee13bf5551c94cf6bc51baebc6f85075971fe6eea", + "sha256:bc6bee759a6bddea5db78d7dcd609397449cb2d2d6587f48f3ca613b19410cfc", + "sha256:bea2acdd8ea4275e1278350ced63da0b166421928276c7c8e3f9729d7402a57b", + "sha256:bfa832bfa540e5b5c27dcf5de5d82ebc431b82c453a43d141afb1e5d2de025fa", + "sha256:c0e6091b157d48cbe37bd67233318dbb53e1e6327d6fc3bb284afd585d141003", + "sha256:c3789bd5768ab5618ebf09cef6ec2b35fed88709b104351748a63045f0ff9797", + "sha256:c530e1eecd036ecc83c3407f77bb86feb79916d4a33d11394b8234f3bd35b940", + "sha256:c811cfcd6a9bf680236c40c6f617187515269ab2912f3d7e8c0174898e2519db", + "sha256:c92d73464b886931308ccc45b2744e5968cbaade0b1d6aeb40d8ab537765f5bc", + "sha256:cccba051221b916a4f5e538997c45d7d136a5646442b1231b916d0164067ea27", + "sha256:cdeabcff45d1c219636ee2e54d852262e5c2e085d6cb476d938aee8d921356b3", + "sha256:ced65e5a985398827cc9276b93ef6dfabe0273c23de8c7931339d7e141c2818e", + "sha256:d049df610ac811dcffdc147153b414147428567fbbc8be43bb8885f04db39d98", + "sha256:dacd995031a01d16eec825bf30802fceb2c3791ef24bcce48fa98ce40918c27b", + "sha256:ddf33d97d2f52d89f6e6e7ae66ee35a4d9ca6f36eda89c24591b0c40205a3629", + "sha256:ded0fc7d90fe93ae0b18059930086c51e640cdd3baebdc783a695c77f123dcd9", + "sha256:e3e0210287329272539eea617830a6a28161fbbd8a3271bf4150ae3e58c5d0e6", + "sha256:e6fa2e3e683f34aea77de8112f6483803c96a44fd726d7358b9888ae5bb394ec", + "sha256:ea0eb6af8a17fa272f7b98d7bebfab7836a0d62738e16ba380f440fceca2d951", + "sha256:ea7f69de383cb47522c9c208aec6dd17697db7875a4674c4af3f8cfdac0bdeae", + "sha256:eac5174677da084abf378739dbf4ad245661635f1600edd1221f150b165343f4", + "sha256:fc4f7a173a5609631bb0c42c23d12c49df3966f89f496a51d3eb0ec81f4519d6", + "sha256:fdb5b3e311d4d4b0eb8b3e8b4d1b0a512713ad7e6a68791d0923d1aec433d919" ], - "markers": "python_version >= '3.6'", - "version": "==25.1.2" + "markers": "python_version >= '3.7'", + "version": "==26.2.0" }, "rdflib": { "hashes": [ @@ -1460,19 +1486,19 @@ }, "referencing": { "hashes": [ - "sha256:5773bd84ef41799a5a8ca72dc34590c041eb01bf9aa02632b4a973fb0181a844", - "sha256:d53ae300ceddd3169f1ffa9caf2cb7b769e92657e4fafb23d34b93679116dfd4" + "sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c", + "sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de" ], "markers": "python_version >= '3.8'", - "version": "==0.34.0" + "version": "==0.35.1" }, "requests": { "hashes": [ - "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f", - "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1" + "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", + "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6" ], - "markers": "python_version >= '3.7'", - "version": "==2.31.0" + "markers": "python_version >= '3.8'", + "version": "==2.32.3" }, "requests-toolbelt": { "hashes": [ @@ -1508,140 +1534,145 @@ }, "rich": { "hashes": [ - "sha256:4edbae314f59eb482f54e9e30bf00d33350aaa94f4bfcd4e9e3110e64d0d7222", - "sha256:9be308cb1fe2f1f57d67ce99e95af38a1e2bc71ad9813b0e247cf7ffbcc3a432" + "sha256:1760a3c0848469b97b558fc61c85233e3dafb69c7a071b4d60c38099d3cd4c06", + "sha256:8260cda28e3db6bf04d2d1ef4dbc03ba80a824c88b0e7668a0f23126a424844a" ], "markers": "python_full_version >= '3.7.0'", - "version": "==13.7.1" + "version": "==13.8.1" }, "rpds-py": { "hashes": [ - "sha256:01e36a39af54a30f28b73096dd39b6802eddd04c90dbe161c1b8dbe22353189f", - "sha256:044a3e61a7c2dafacae99d1e722cc2d4c05280790ec5a05031b3876809d89a5c", - "sha256:08231ac30a842bd04daabc4d71fddd7e6d26189406d5a69535638e4dcb88fe76", - "sha256:08f9ad53c3f31dfb4baa00da22f1e862900f45908383c062c27628754af2e88e", - "sha256:0ab39c1ba9023914297dd88ec3b3b3c3f33671baeb6acf82ad7ce883f6e8e157", - "sha256:0af039631b6de0397ab2ba16eaf2872e9f8fca391b44d3d8cac317860a700a3f", - "sha256:0b8612cd233543a3781bc659c731b9d607de65890085098986dfd573fc2befe5", - "sha256:11a8c85ef4a07a7638180bf04fe189d12757c696eb41f310d2426895356dcf05", - "sha256:1374f4129f9bcca53a1bba0bb86bf78325a0374577cf7e9e4cd046b1e6f20e24", - "sha256:1d4acf42190d449d5e89654d5c1ed3a4f17925eec71f05e2a41414689cda02d1", - "sha256:1d9a5be316c15ffb2b3c405c4ff14448c36b4435be062a7f578ccd8b01f0c4d8", - "sha256:1df3659d26f539ac74fb3b0c481cdf9d725386e3552c6fa2974f4d33d78e544b", - "sha256:22806714311a69fd0af9b35b7be97c18a0fc2826e6827dbb3a8c94eac6cf7eeb", - "sha256:2644e47de560eb7bd55c20fc59f6daa04682655c58d08185a9b95c1970fa1e07", - "sha256:2e6d75ab12b0bbab7215e5d40f1e5b738aa539598db27ef83b2ec46747df90e1", - "sha256:30f43887bbae0d49113cbaab729a112251a940e9b274536613097ab8b4899cf6", - "sha256:34b18ba135c687f4dac449aa5157d36e2cbb7c03cbea4ddbd88604e076aa836e", - "sha256:36b3ee798c58ace201289024b52788161e1ea133e4ac93fba7d49da5fec0ef9e", - "sha256:39514da80f971362f9267c600b6d459bfbbc549cffc2cef8e47474fddc9b45b1", - "sha256:39f5441553f1c2aed4de4377178ad8ff8f9d733723d6c66d983d75341de265ab", - "sha256:3a96e0c6a41dcdba3a0a581bbf6c44bb863f27c541547fb4b9711fd8cf0ffad4", - "sha256:3f26b5bd1079acdb0c7a5645e350fe54d16b17bfc5e71f371c449383d3342e17", - "sha256:41ef53e7c58aa4ef281da975f62c258950f54b76ec8e45941e93a3d1d8580594", - "sha256:42821446ee7a76f5d9f71f9e33a4fb2ffd724bb3e7f93386150b61a43115788d", - "sha256:43fbac5f22e25bee1d482c97474f930a353542855f05c1161fd804c9dc74a09d", - "sha256:4457a94da0d5c53dc4b3e4de1158bdab077db23c53232f37a3cb7afdb053a4e3", - "sha256:465a3eb5659338cf2a9243e50ad9b2296fa15061736d6e26240e713522b6235c", - "sha256:482103aed1dfe2f3b71a58eff35ba105289b8d862551ea576bd15479aba01f66", - "sha256:4832d7d380477521a8c1644bbab6588dfedea5e30a7d967b5fb75977c45fd77f", - "sha256:4901165d170a5fde6f589acb90a6b33629ad1ec976d4529e769c6f3d885e3e80", - "sha256:5307def11a35f5ae4581a0b658b0af8178c65c530e94893345bebf41cc139d33", - "sha256:5417558f6887e9b6b65b4527232553c139b57ec42c64570569b155262ac0754f", - "sha256:56a737287efecafc16f6d067c2ea0117abadcd078d58721f967952db329a3e5c", - "sha256:586f8204935b9ec884500498ccc91aa869fc652c40c093bd9e1471fbcc25c022", - "sha256:5b4e7d8d6c9b2e8ee2d55c90b59c707ca59bc30058269b3db7b1f8df5763557e", - "sha256:5ddcba87675b6d509139d1b521e0c8250e967e63b5909a7e8f8944d0f90ff36f", - "sha256:618a3d6cae6ef8ec88bb76dd80b83cfe415ad4f1d942ca2a903bf6b6ff97a2da", - "sha256:635dc434ff724b178cb192c70016cc0ad25a275228f749ee0daf0eddbc8183b1", - "sha256:661d25cbffaf8cc42e971dd570d87cb29a665f49f4abe1f9e76be9a5182c4688", - "sha256:66e6a3af5a75363d2c9a48b07cb27c4ea542938b1a2e93b15a503cdfa8490795", - "sha256:67071a6171e92b6da534b8ae326505f7c18022c6f19072a81dcf40db2638767c", - "sha256:685537e07897f173abcf67258bee3c05c374fa6fff89d4c7e42fb391b0605e98", - "sha256:69e64831e22a6b377772e7fb337533c365085b31619005802a79242fee620bc1", - "sha256:6b0817e34942b2ca527b0e9298373e7cc75f429e8da2055607f4931fded23e20", - "sha256:6c81e5f372cd0dc5dc4809553d34f832f60a46034a5f187756d9b90586c2c307", - "sha256:6d7faa6f14017c0b1e69f5e2c357b998731ea75a442ab3841c0dbbbfe902d2c4", - "sha256:6ef0befbb5d79cf32d0266f5cff01545602344eda89480e1dd88aca964260b18", - "sha256:6ef687afab047554a2d366e112dd187b62d261d49eb79b77e386f94644363294", - "sha256:7223a2a5fe0d217e60a60cdae28d6949140dde9c3bcc714063c5b463065e3d66", - "sha256:77f195baa60a54ef9d2de16fbbfd3ff8b04edc0c0140a761b56c267ac11aa467", - "sha256:793968759cd0d96cac1e367afd70c235867831983f876a53389ad869b043c948", - "sha256:7bd339195d84439cbe5771546fe8a4e8a7a045417d8f9de9a368c434e42a721e", - "sha256:7cd863afe7336c62ec78d7d1349a2f34c007a3cc6c2369d667c65aeec412a5b1", - "sha256:7f2facbd386dd60cbbf1a794181e6aa0bd429bd78bfdf775436020172e2a23f0", - "sha256:84ffab12db93b5f6bad84c712c92060a2d321b35c3c9960b43d08d0f639d60d7", - "sha256:8c8370641f1a7f0e0669ddccca22f1da893cef7628396431eb445d46d893e5cd", - "sha256:8db715ebe3bb7d86d77ac1826f7d67ec11a70dbd2376b7cc214199360517b641", - "sha256:8e8916ae4c720529e18afa0b879473049e95949bf97042e938530e072fde061d", - "sha256:8f03bccbd8586e9dd37219bce4d4e0d3ab492e6b3b533e973fa08a112cb2ffc9", - "sha256:8f2fc11e8fe034ee3c34d316d0ad8808f45bc3b9ce5857ff29d513f3ff2923a1", - "sha256:923d39efa3cfb7279a0327e337a7958bff00cc447fd07a25cddb0a1cc9a6d2da", - "sha256:93df1de2f7f7239dc9cc5a4a12408ee1598725036bd2dedadc14d94525192fc3", - "sha256:998e33ad22dc7ec7e030b3df701c43630b5bc0d8fbc2267653577e3fec279afa", - "sha256:99f70b740dc04d09e6b2699b675874367885217a2e9f782bdf5395632ac663b7", - "sha256:9a00312dea9310d4cb7dbd7787e722d2e86a95c2db92fbd7d0155f97127bcb40", - "sha256:9d54553c1136b50fd12cc17e5b11ad07374c316df307e4cfd6441bea5fb68496", - "sha256:9dbbeb27f4e70bfd9eec1be5477517365afe05a9b2c441a0b21929ee61048124", - "sha256:a1ce3ba137ed54f83e56fb983a5859a27d43a40188ba798993812fed73c70836", - "sha256:a34d557a42aa28bd5c48a023c570219ba2593bcbbb8dc1b98d8cf5d529ab1434", - "sha256:a5f446dd5055667aabaee78487f2b5ab72e244f9bc0b2ffebfeec79051679984", - "sha256:ad36cfb355e24f1bd37cac88c112cd7730873f20fb0bdaf8ba59eedf8216079f", - "sha256:aec493917dd45e3c69d00a8874e7cbed844efd935595ef78a0f25f14312e33c6", - "sha256:b316144e85316da2723f9d8dc75bada12fa58489a527091fa1d5a612643d1a0e", - "sha256:b34ae4636dfc4e76a438ab826a0d1eed2589ca7d9a1b2d5bb546978ac6485461", - "sha256:b34b7aa8b261c1dbf7720b5d6f01f38243e9b9daf7e6b8bc1fd4657000062f2c", - "sha256:bc362ee4e314870a70f4ae88772d72d877246537d9f8cb8f7eacf10884862432", - "sha256:bed88b9a458e354014d662d47e7a5baafd7ff81c780fd91584a10d6ec842cb73", - "sha256:c0013fe6b46aa496a6749c77e00a3eb07952832ad6166bd481c74bda0dcb6d58", - "sha256:c0b5dcf9193625afd8ecc92312d6ed78781c46ecbf39af9ad4681fc9f464af88", - "sha256:c4325ff0442a12113a6379af66978c3fe562f846763287ef66bdc1d57925d337", - "sha256:c463ed05f9dfb9baebef68048aed8dcdc94411e4bf3d33a39ba97e271624f8f7", - "sha256:c8362467a0fdeccd47935f22c256bec5e6abe543bf0d66e3d3d57a8fb5731863", - "sha256:cd5bf1af8efe569654bbef5a3e0a56eca45f87cfcffab31dd8dde70da5982475", - "sha256:cf1ea2e34868f6fbf070e1af291c8180480310173de0b0c43fc38a02929fc0e3", - "sha256:d62dec4976954a23d7f91f2f4530852b0c7608116c257833922a896101336c51", - "sha256:d68c93e381010662ab873fea609bf6c0f428b6d0bb00f2c6939782e0818d37bf", - "sha256:d7c36232a90d4755b720fbd76739d8891732b18cf240a9c645d75f00639a9024", - "sha256:dd18772815d5f008fa03d2b9a681ae38d5ae9f0e599f7dda233c439fcaa00d40", - "sha256:ddc2f4dfd396c7bfa18e6ce371cba60e4cf9d2e5cdb71376aa2da264605b60b9", - "sha256:e003b002ec72c8d5a3e3da2989c7d6065b47d9eaa70cd8808b5384fbb970f4ec", - "sha256:e32a92116d4f2a80b629778280103d2a510a5b3f6314ceccd6e38006b5e92dcb", - "sha256:e4461d0f003a0aa9be2bdd1b798a041f177189c1a0f7619fe8c95ad08d9a45d7", - "sha256:e541ec6f2ec456934fd279a3120f856cd0aedd209fc3852eca563f81738f6861", - "sha256:e546e768d08ad55b20b11dbb78a745151acbd938f8f00d0cfbabe8b0199b9880", - "sha256:ea7d4a99f3b38c37eac212dbd6ec42b7a5ec51e2c74b5d3223e43c811609e65f", - "sha256:ed4eb745efbff0a8e9587d22a84be94a5eb7d2d99c02dacf7bd0911713ed14dd", - "sha256:f8a2f084546cc59ea99fda8e070be2fd140c3092dc11524a71aa8f0f3d5a55ca", - "sha256:fcb25daa9219b4cf3a0ab24b0eb9a5cc8949ed4dc72acb8fa16b7e1681aa3c58", - "sha256:fdea4952db2793c4ad0bdccd27c1d8fdd1423a92f04598bc39425bcc2b8ee46e" - ], - "markers": "python_version >= '3.8'", - "version": "==0.18.0" + "sha256:06db23d43f26478303e954c34c75182356ca9aa7797d22c5345b16871ab9c45c", + "sha256:0e13e6952ef264c40587d510ad676a988df19adea20444c2b295e536457bc585", + "sha256:11ef6ce74616342888b69878d45e9f779b95d4bd48b382a229fe624a409b72c5", + "sha256:1259c7b3705ac0a0bd38197565a5d603218591d3f6cee6e614e380b6ba61c6f6", + "sha256:18d7585c463087bddcfa74c2ba267339f14f2515158ac4db30b1f9cbdb62c8ef", + "sha256:1e0f80b739e5a8f54837be5d5c924483996b603d5502bfff79bf33da06164ee2", + "sha256:1e5f3cd7397c8f86c8cc72d5a791071431c108edd79872cdd96e00abd8497d29", + "sha256:220002c1b846db9afd83371d08d239fdc865e8f8c5795bbaec20916a76db3318", + "sha256:22e6c9976e38f4d8c4a63bd8a8edac5307dffd3ee7e6026d97f3cc3a2dc02a0b", + "sha256:238a2d5b1cad28cdc6ed15faf93a998336eb041c4e440dd7f902528b8891b399", + "sha256:2580b0c34583b85efec8c5c5ec9edf2dfe817330cc882ee972ae650e7b5ef739", + "sha256:28527c685f237c05445efec62426d285e47a58fb05ba0090a4340b73ecda6dee", + "sha256:2cf126d33a91ee6eedc7f3197b53e87a2acdac63602c0f03a02dd69e4b138174", + "sha256:338ca4539aad4ce70a656e5187a3a31c5204f261aef9f6ab50e50bcdffaf050a", + "sha256:39ed0d010457a78f54090fafb5d108501b5aa5604cc22408fc1c0c77eac14344", + "sha256:3ad0fda1635f8439cde85c700f964b23ed5fc2d28016b32b9ee5fe30da5c84e2", + "sha256:3d2b1ad682a3dfda2a4e8ad8572f3100f95fad98cb99faf37ff0ddfe9cbf9d03", + "sha256:3d61339e9f84a3f0767b1995adfb171a0d00a1185192718a17af6e124728e0f5", + "sha256:3fde368e9140312b6e8b6c09fb9f8c8c2f00999d1823403ae90cc00480221b22", + "sha256:40ce74fc86ee4645d0a225498d091d8bc61f39b709ebef8204cb8b5a464d3c0e", + "sha256:49a8063ea4296b3a7e81a5dfb8f7b2d73f0b1c20c2af401fb0cdf22e14711a96", + "sha256:4a1f1d51eccb7e6c32ae89243cb352389228ea62f89cd80823ea7dd1b98e0b91", + "sha256:4b16aa0107ecb512b568244ef461f27697164d9a68d8b35090e9b0c1c8b27752", + "sha256:4f1ed4749a08379555cebf4650453f14452eaa9c43d0a95c49db50c18b7da075", + "sha256:4fe84294c7019456e56d93e8ababdad5a329cd25975be749c3f5f558abb48253", + "sha256:50eccbf054e62a7b2209b28dc7a22d6254860209d6753e6b78cfaeb0075d7bee", + "sha256:514b3293b64187172bc77c8fb0cdae26981618021053b30d8371c3a902d4d5ad", + "sha256:54b43a2b07db18314669092bb2de584524d1ef414588780261e31e85846c26a5", + "sha256:55fea87029cded5df854ca7e192ec7bdb7ecd1d9a3f63d5c4eb09148acf4a7ce", + "sha256:569b3ea770c2717b730b61998b6c54996adee3cef69fc28d444f3e7920313cf7", + "sha256:56e27147a5a4c2c21633ff8475d185734c0e4befd1c989b5b95a5d0db699b21b", + "sha256:57eb94a8c16ab08fef6404301c38318e2c5a32216bf5de453e2714c964c125c8", + "sha256:5a35df9f5548fd79cb2f52d27182108c3e6641a4feb0f39067911bf2adaa3e57", + "sha256:5a8c94dad2e45324fc74dce25e1645d4d14df9a4e54a30fa0ae8bad9a63928e3", + "sha256:5b4f105deeffa28bbcdff6c49b34e74903139afa690e35d2d9e3c2c2fba18cec", + "sha256:5c1dc0f53856b9cc9a0ccca0a7cc61d3d20a7088201c0937f3f4048c1718a209", + "sha256:614fdafe9f5f19c63ea02817fa4861c606a59a604a77c8cdef5aa01d28b97921", + "sha256:617c7357272c67696fd052811e352ac54ed1d9b49ab370261a80d3b6ce385045", + "sha256:65794e4048ee837494aea3c21a28ad5fc080994dfba5b036cf84de37f7ad5074", + "sha256:6632f2d04f15d1bd6fe0eedd3b86d9061b836ddca4c03d5cf5c7e9e6b7c14580", + "sha256:6c8ef2ebf76df43f5750b46851ed1cdf8f109d7787ca40035fe19fbdc1acc5a7", + "sha256:758406267907b3781beee0f0edfe4a179fbd97c0be2e9b1154d7f0a1279cf8e5", + "sha256:7e60cb630f674a31f0368ed32b2a6b4331b8350d67de53c0359992444b116dd3", + "sha256:89c19a494bf3ad08c1da49445cc5d13d8fefc265f48ee7e7556839acdacf69d0", + "sha256:8a86a9b96070674fc88b6f9f71a97d2c1d3e5165574615d1f9168ecba4cecb24", + "sha256:8bc7690f7caee50b04a79bf017a8d020c1f48c2a1077ffe172abec59870f1139", + "sha256:8d7919548df3f25374a1f5d01fbcd38dacab338ef5f33e044744b5c36729c8db", + "sha256:9426133526f69fcaba6e42146b4e12d6bc6c839b8b555097020e2b78ce908dcc", + "sha256:9824fb430c9cf9af743cf7aaf6707bf14323fb51ee74425c380f4c846ea70789", + "sha256:9bb4a0d90fdb03437c109a17eade42dfbf6190408f29b2744114d11586611d6f", + "sha256:9bc2d153989e3216b0559251b0c260cfd168ec78b1fac33dd485750a228db5a2", + "sha256:9d35cef91e59ebbeaa45214861874bc6f19eb35de96db73e467a8358d701a96c", + "sha256:a1862d2d7ce1674cffa6d186d53ca95c6e17ed2b06b3f4c476173565c862d232", + "sha256:a84ab91cbe7aab97f7446652d0ed37d35b68a465aeef8fc41932a9d7eee2c1a6", + "sha256:aa7f429242aae2947246587d2964fad750b79e8c233a2367f71b554e9447949c", + "sha256:aa9a0521aeca7d4941499a73ad7d4f8ffa3d1affc50b9ea11d992cd7eff18a29", + "sha256:ac2f4f7a98934c2ed6505aead07b979e6f999389f16b714448fb39bbaa86a489", + "sha256:ae94bd0b2f02c28e199e9bc51485d0c5601f58780636185660f86bf80c89af94", + "sha256:af0fc424a5842a11e28956e69395fbbeab2c97c42253169d87e90aac2886d751", + "sha256:b2a5db5397d82fa847e4c624b0c98fe59d2d9b7cf0ce6de09e4d2e80f8f5b3f2", + "sha256:b4c29cbbba378759ac5786730d1c3cb4ec6f8ababf5c42a9ce303dc4b3d08cda", + "sha256:b74b25f024b421d5859d156750ea9a65651793d51b76a2e9238c05c9d5f203a9", + "sha256:b7f19250ceef892adf27f0399b9e5afad019288e9be756d6919cb58892129f51", + "sha256:b80d4a7900cf6b66bb9cee5c352b2d708e29e5a37fe9bf784fa97fc11504bf6c", + "sha256:b8c00a3b1e70c1d3891f0db1b05292747f0dbcfb49c43f9244d04c70fbc40eb8", + "sha256:bb273176be34a746bdac0b0d7e4e2c467323d13640b736c4c477881a3220a989", + "sha256:c3c20f0ddeb6e29126d45f89206b8291352b8c5b44384e78a6499d68b52ae511", + "sha256:c3e130fd0ec56cb76eb49ef52faead8ff09d13f4527e9b0c400307ff72b408e1", + "sha256:c52d3f2f82b763a24ef52f5d24358553e8403ce05f893b5347098014f2d9eff2", + "sha256:c6377e647bbfd0a0b159fe557f2c6c602c159fc752fa316572f012fc0bf67150", + "sha256:c638144ce971df84650d3ed0096e2ae7af8e62ecbbb7b201c8935c370df00a2c", + "sha256:ce9845054c13696f7af7f2b353e6b4f676dab1b4b215d7fe5e05c6f8bb06f965", + "sha256:cf258ede5bc22a45c8e726b29835b9303c285ab46fc7c3a4cc770736b5304c9f", + "sha256:d0a26ffe9d4dd35e4dfdd1e71f46401cff0181c75ac174711ccff0459135fa58", + "sha256:d0b67d87bb45ed1cd020e8fbf2307d449b68abc45402fe1a4ac9e46c3c8b192b", + "sha256:d20277fd62e1b992a50c43f13fbe13277a31f8c9f70d59759c88f644d66c619f", + "sha256:d454b8749b4bd70dd0a79f428731ee263fa6995f83ccb8bada706e8d1d3ff89d", + "sha256:d4c7d1a051eeb39f5c9547e82ea27cbcc28338482242e3e0b7768033cb083821", + "sha256:d72278a30111e5b5525c1dd96120d9e958464316f55adb030433ea905866f4de", + "sha256:d72a210824facfdaf8768cf2d7ca25a042c30320b3020de2fa04640920d4e121", + "sha256:d807dc2051abe041b6649681dce568f8e10668e3c1c6543ebae58f2d7e617855", + "sha256:dbe982f38565bb50cb7fb061ebf762c2f254ca3d8c20d4006878766e84266272", + "sha256:dcedf0b42bcb4cfff4101d7771a10532415a6106062f005ab97d1d0ab5681c60", + "sha256:deb62214c42a261cb3eb04d474f7155279c1a8a8c30ac89b7dcb1721d92c3c02", + "sha256:def7400461c3a3f26e49078302e1c1b38f6752342c77e3cf72ce91ca69fb1bc1", + "sha256:df3de6b7726b52966edf29663e57306b23ef775faf0ac01a3e9f4012a24a4140", + "sha256:e1940dae14e715e2e02dfd5b0f64a52e8374a517a1e531ad9412319dc3ac7879", + "sha256:e4df1e3b3bec320790f699890d41c59d250f6beda159ea3c44c3f5bac1976940", + "sha256:e6900ecdd50ce0facf703f7a00df12374b74bbc8ad9fe0f6559947fb20f82364", + "sha256:ea438162a9fcbee3ecf36c23e6c68237479f89f962f82dae83dc15feeceb37e4", + "sha256:eb851b7df9dda52dc1415ebee12362047ce771fc36914586b2e9fcbd7d293b3e", + "sha256:ec31a99ca63bf3cd7f1a5ac9fe95c5e2d060d3c768a09bc1d16e235840861420", + "sha256:f0475242f447cc6cb8a9dd486d68b2ef7fbee84427124c232bff5f63b1fe11e5", + "sha256:f2fbf7db2012d4876fb0d66b5b9ba6591197b0f165db8d99371d976546472a24", + "sha256:f60012a73aa396be721558caa3a6fd49b3dd0033d1675c6d59c4502e870fcf0c", + "sha256:f8e604fe73ba048c06085beaf51147eaec7df856824bfe7b98657cf436623daf", + "sha256:f90a4cd061914a60bd51c68bcb4357086991bd0bb93d8aa66a6da7701370708f", + "sha256:f918a1a130a6dfe1d7fe0f105064141342e7dd1611f2e6a21cd2f5c8cb1cfb3e", + "sha256:fa518bcd7600c584bf42e6617ee8132869e877db2f76bcdc281ec6a4113a53ab", + "sha256:faefcc78f53a88f3076b7f8be0a8f8d35133a3ecf7f3770895c25f8813460f08", + "sha256:fcaeb7b57f1a1e071ebd748984359fef83ecb026325b9d4ca847c95bc7311c92", + "sha256:fd2d84f40633bc475ef2d5490b9c19543fbf18596dcb1b291e3a12ea5d722f7a", + "sha256:fdfc3a892927458d98f3d55428ae46b921d1f7543b89382fdb483f5640daaec8" + ], + "markers": "python_version >= '3.8'", + "version": "==0.20.0" }, "ruff": { "hashes": [ - "sha256:3f3860057590e810c7ffea75669bdc6927bfd91e29b4baa9258fd48b540a4365", - "sha256:519cf6a0ebed244dce1dc8aecd3dc99add7a2ee15bb68cf19588bb5bf58e0488", - "sha256:60c870a7d46efcbc8385d27ec07fe534ac32f3b251e4fc44b3cbfd9e09609ef4", - "sha256:64abeed785dad51801b423fa51840b1764b35d6c461ea8caef9cf9e5e5ab34d9", - "sha256:6810563cc08ad0096b57c717bd78aeac888a1bfd38654d9113cb3dc4d3f74232", - "sha256:6fc14fa742e1d8f24910e1fff0bd5e26d395b0e0e04cc1b15c7c5e5fe5b4af91", - "sha256:986f2377f7cf12efac1f515fc1a5b753c000ed1e0a6de96747cdf2da20a1b369", - "sha256:98e98300056445ba2cc27d0b325fd044dc17fcc38e4e4d2c7711585bd0a958ed", - "sha256:af27ac187c0a331e8ef91d84bf1c3c6a5dea97e912a7560ac0cef25c526a4102", - "sha256:bb0acfb921030d00070539c038cd24bb1df73a2981e9f55942514af8b17be94e", - "sha256:c4fd98e85869603e65f554fdc5cddf0712e352fe6e61d29d5a6fe087ec82b76c", - "sha256:cf133dd744f2470b347f602452a88e70dadfbe0fcfb5fd46e093d55da65f82f7", - "sha256:cf187a7e7098233d0d0c71175375c5162f880126c4c716fa28a8ac418dcf3378", - "sha256:d3ee7880f653cc03749a3bfea720cf2a192e4f884925b0cf7eecce82f0ce5854", - "sha256:de0d5069b165e5a32b3c6ffbb81c350b1e3d3483347196ffdf86dc0ef9e37dd6", - "sha256:df52972138318bc7546d92348a1ee58449bc3f9eaf0db278906eb511889c4b50", - "sha256:f0f4484c6541a99862b693e13a151435a279b271cff20e37101116a21e2a1ad1" + "sha256:0308610470fcc82969082fc83c76c0d362f562e2f0cdab0586516f03a4e06ec6", + "sha256:0b52387d3289ccd227b62102c24714ed75fbba0b16ecc69a923a37e3b5e0aaaa", + "sha256:0ea086601b22dc5e7693a78f3fcfc460cceabfdf3bdc36dc898792aba48fbad6", + "sha256:34d5efad480193c046c86608dbba2bccdc1c5fd11950fb271f8086e0c763a5d1", + "sha256:50e30b437cebef547bd5c3edf9ce81343e5dd7c737cb36ccb4fe83573f3d392e", + "sha256:549daccee5227282289390b0222d0fbee0275d1db6d514550d65420053021a58", + "sha256:66dbfea86b663baab8fcae56c59f190caba9398df1488164e2df53e216248baa", + "sha256:7862f42fc1a4aca1ea3ffe8a11f67819d183a5693b228f0bb3a531f5e40336fc", + "sha256:803b96dea21795a6c9d5bfa9e96127cc9c31a1987802ca68f35e5c95aed3fc0d", + "sha256:932063a03bac394866683e15710c25b8690ccdca1cf192b9a98260332ca93408", + "sha256:ac3b5bfbee99973f80aa1b7cbd1c9cbce200883bdd067300c22a6cc1c7fba212", + "sha256:ac4b75e898ed189b3708c9ab3fc70b79a433219e1e87193b4f2b77251d058d14", + "sha256:bedff9e4f004dad5f7f76a9d39c4ca98af526c9b1695068198b3bda8c085ef60", + "sha256:c44536df7b93a587de690e124b89bd47306fddd59398a0fb12afd6133c7b3818", + "sha256:c4b153fc152af51855458e79e835fb6b933032921756cec9af7d0ba2aa01a258", + "sha256:d02a4127a86de23002e694d7ff19f905c51e338c72d8e09b56bfb60e1681724f", + "sha256:eebe4ff1967c838a1a9618a5a59a3b0a00406f8d7eefee97c70411fefc353617", + "sha256:f0f8968feea5ce3777c0d8365653d5e91c40c31a81d95824ba61d871a11b8523" ], "index": "pypi", "markers": "python_version >= '3.7'", - "version": "==0.3.4" + "version": "==0.6.4" }, "semantic-version": { "hashes": [ @@ -1653,20 +1684,20 @@ }, "send2trash": { "hashes": [ - "sha256:a384719d99c07ce1eefd6905d2decb6f8b7ed054025bb0e618919f945de4f679", - "sha256:c132d59fa44b9ca2b1699af5c86f57ce9f4c5eb56629d5d55fbb7a35f84e2312" + "sha256:0c31227e0bd08961c7665474a3d1ef7193929fedda4233843689baa056be46c9", + "sha256:b18e7a3966d99871aefeb00cfbcfdced55ce4871194810fc71f4aa484b953abf" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==1.8.2" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", + "version": "==1.8.3" }, "setuptools": { "hashes": [ - "sha256:0ff4183f8f42cd8fa3acea16c45205521a4ef28f73c6391d8a25e92893134f2e", - "sha256:c21c49fb1042386df081cb5d86759792ab89efca84cf114889191cd09aacc80c" + "sha256:5f4c08aa4d3ebcb57a50c33b1b07e94315d7fc7230f7115e47fc99776c8ce308", + "sha256:95b40ed940a1c67eb70fc099094bd6e99c6ee7c23aa2306f4d2697ba7916f9c6" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==69.2.0" + "version": "==74.1.2" }, "six": { "hashes": [ @@ -1708,51 +1739,53 @@ }, "soupsieve": { "hashes": [ - "sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690", - "sha256:eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7" + "sha256:e2e68417777af359ec65daac1057404a3c8a5455bb8abc36f1a9866ab1a51abb", + "sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9" ], "markers": "python_version >= '3.8'", - "version": "==2.5" + "version": "==2.6" }, "sphinx": { "hashes": [ - "sha256:1e09160a40b956dc623c910118fa636da93bd3ca0b9876a7b3df90f07d691560", - "sha256:9a5160e1ea90688d5963ba09a2dcd8bdd526620edbb65c328728f1b2228d5ab5" + "sha256:242f92a7ea7e6c5b406fdc2615413890ba9f699114a9c09192d7dfead2ee9cfe", + "sha256:c2419e2135d11f1951cd994d6eb18a1835bd8fdd8429f9ca375dc1f3281bd239" ], + "index": "pypi", "markers": "python_version >= '3.9'", - "version": "==7.2.6" + "version": "==7.4.7" }, "sphinx-rtd-theme": { "hashes": [ "sha256:bd5d7b80622406762073a04ef8fadc5f9151261563d47027de09910ce03afe6b", "sha256:ec93d0856dc280cf3aee9a4c9807c60e027c7f7b461b77aeffed682e68f0e586" ], + "index": "pypi", "markers": "python_version >= '3.6'", "version": "==2.0.0" }, "sphinxcontrib-applehelp": { "hashes": [ - "sha256:c40a4f96f3776c4393d933412053962fac2b84f4c99a7982ba42e09576a70619", - "sha256:cb61eb0ec1b61f349e5cc36b2028e9e7ca765be05e49641c97241274753067b4" + "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1", + "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5" ], "markers": "python_version >= '3.9'", - "version": "==1.0.8" + "version": "==2.0.0" }, "sphinxcontrib-devhelp": { "hashes": [ - "sha256:6485d09629944511c893fa11355bda18b742b83a2b181f9a009f7e500595c90f", - "sha256:9893fd3f90506bc4b97bdb977ceb8fbd823989f4316b28c3841ec128544372d3" + "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad", + "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2" ], "markers": "python_version >= '3.9'", - "version": "==1.0.6" + "version": "==2.0.0" }, "sphinxcontrib-htmlhelp": { "hashes": [ - "sha256:0dc87637d5de53dd5eec3a6a01753b1ccf99494bd756aafecd74b4fa9e729015", - "sha256:393f04f112b4d2f53d93448d4bce35842f62b307ccdc549ec1585e950bc35e04" + "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8", + "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9" ], "markers": "python_version >= '3.9'", - "version": "==2.0.5" + "version": "==2.1.0" }, "sphinxcontrib-jquery": { "hashes": [ @@ -1772,19 +1805,19 @@ }, "sphinxcontrib-qthelp": { "hashes": [ - "sha256:053dedc38823a80a7209a80860b16b722e9e0209e32fea98c90e4e6624588ed6", - "sha256:e2ae3b5c492d58fcbd73281fbd27e34b8393ec34a073c792642cd8e529288182" + "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab", + "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb" ], "markers": "python_version >= '3.9'", - "version": "==1.0.7" + "version": "==2.0.0" }, "sphinxcontrib-serializinghtml": { "hashes": [ - "sha256:326369b8df80a7d2d8d7f99aa5ac577f51ea51556ed974e7716cfd4fca3f6cb7", - "sha256:93f3f5dc458b91b192fe10c397e324f262cf163d79f3282c158e8436a2c4511f" + "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331", + "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d" ], "markers": "python_version >= '3.9'", - "version": "==1.1.10" + "version": "==2.0.0" }, "stack-data": { "hashes": [ @@ -1803,18 +1836,18 @@ }, "tinycss2": { "hashes": [ - "sha256:2b80a96d41e7c3914b8cda8bc7f705a4d9c49275616e886103dd839dfc847847", - "sha256:8cff3a8f066c2ec677c06dbc7b45619804a6938478d9d73c284b29d14ecb0627" + "sha256:152f9acabd296a8375fbca5b84c961ff95971fcfc32e79550c8df8e29118c54d", + "sha256:54a8dbdffb334d536851be0226030e9505965bb2f30f21a4a82c55fb2a80fae7" ], - "markers": "python_version >= '3.7'", - "version": "==1.2.1" + "markers": "python_version >= '3.8'", + "version": "==1.3.0" }, "tokenize-rt": { "hashes": [ - "sha256:9fe80f8a5c1edad2d3ede0f37481cc0cc1538a2f442c9c2f9e4feacd2792d054", - "sha256:b79d41a65cfec71285433511b50271b05da3584a1da144a0752e9c621a285289" + "sha256:b9711bdfc51210211137499b5e355d3de5ec88a85d2025c520cbb921b5194367", + "sha256:d4ff7ded2873512938b4f8cbb98c9b07118f01d30ac585a30d7a88353ca36d22" ], - "version": "==5.2.0" + "version": "==6.0.0" }, "toml": { "hashes": [ @@ -1824,72 +1857,64 @@ "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==0.10.2" }, - "tomlkit": { - "hashes": [ - "sha256:5cd82d48a3dd89dee1f9d64420aa20ae65cfbd00668d6f094d7578a78efbb77b", - "sha256:7ca1cfc12232806517a8515047ba66a19369e71edf2439d0f5824f91032b6cc3" - ], - "markers": "python_version >= '3.7'", - "version": "==0.12.4" - }, "tornado": { "hashes": [ - "sha256:02ccefc7d8211e5a7f9e8bc3f9e5b0ad6262ba2fbb683a6443ecc804e5224ce0", - "sha256:10aeaa8006333433da48dec9fe417877f8bcc21f48dda8d661ae79da357b2a63", - "sha256:27787de946a9cffd63ce5814c33f734c627a87072ec7eed71f7fc4417bb16263", - "sha256:6f8a6c77900f5ae93d8b4ae1196472d0ccc2775cc1dfdc9e7727889145c45052", - "sha256:71ddfc23a0e03ef2df1c1397d859868d158c8276a0603b96cf86892bff58149f", - "sha256:72291fa6e6bc84e626589f1c29d90a5a6d593ef5ae68052ee2ef000dfd273dee", - "sha256:88b84956273fbd73420e6d4b8d5ccbe913c65d31351b4c004ae362eba06e1f78", - "sha256:e43bc2e5370a6a8e413e1e1cd0c91bedc5bd62a74a532371042a18ef19e10579", - "sha256:f0251554cdd50b4b44362f73ad5ba7126fc5b2c2895cc62b14a1c2d7ea32f212", - "sha256:f7894c581ecdcf91666a0912f18ce5e757213999e183ebfc2c3fdbf4d5bd764e", - "sha256:fd03192e287fbd0899dd8f81c6fb9cbbc69194d2074b38f384cb6fa72b80e9c2" + "sha256:163b0aafc8e23d8cdc3c9dfb24c5368af84a81e3364745ccb4427669bf84aec8", + "sha256:25486eb223babe3eed4b8aecbac33b37e3dd6d776bc730ca14e1bf93888b979f", + "sha256:454db8a7ecfcf2ff6042dde58404164d969b6f5d58b926da15e6b23817950fc4", + "sha256:613bf4ddf5c7a95509218b149b555621497a6cc0d46ac341b30bd9ec19eac7f3", + "sha256:6d5ce3437e18a2b66fbadb183c1d3364fb03f2be71299e7d10dbeeb69f4b2a14", + "sha256:8ae50a504a740365267b2a8d1a90c9fbc86b780a39170feca9bcc1787ff80842", + "sha256:92d3ab53183d8c50f8204a51e6f91d18a15d5ef261e84d452800d4ff6fc504e9", + "sha256:a02a08cc7a9314b006f653ce40483b9b3c12cda222d6a46d4ac63bb6c9057698", + "sha256:b24b8982ed444378d7f21d563f4180a2de31ced9d8d84443907a0a64da2072e7", + "sha256:d9a566c40b89757c9aa8e6f032bcdb8ca8795d7c1a9762910c722b1635c9de4d", + "sha256:e2e20b9113cd7293f164dc46fffb13535266e713cdb87bd2d15ddb336e96cfc4" ], "markers": "python_version >= '3.8'", - "version": "==6.4" + "version": "==6.4.1" }, "tox": { "hashes": [ - "sha256:0defb44f6dafd911b61788325741cc6b2e12ea71f987ac025ad4d649f1f1a104", - "sha256:2900c4eb7b716af4a928a7fdc2ed248ad6575294ed7cfae2ea41203937422847" + "sha256:35d472032ee1f73fe20c3e0e73d7073a4e85075c86ff02c576f9fc7c6a15a578", + "sha256:3c0c96bc3a568a5c7e66387a4cfcf8c875b52e09f4d47c9f7a277ec82f1a0b11" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==4.14.2" + "version": "==4.18.1" }, "traitlets": { "hashes": [ - "sha256:8cdd83c040dab7d1dee822678e5f5d100b514f7b72b01615b26fc5718916fdf9", - "sha256:fcdf85684a772ddeba87db2f398ce00b40ff550d1528c03c14dbf6a02003cd80" + "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7", + "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f" ], "markers": "python_version >= '3.8'", - "version": "==5.14.2" + "version": "==5.14.3" }, "twine": { "hashes": [ - "sha256:89b0cc7d370a4b66421cc6102f269aa910fe0f1861c124f573cf2ddedbc10cf4", - "sha256:a262933de0b484c53408f9edae2e7821c1c45a3314ff2df9bdd343aa7ab8edc0" + "sha256:215dbe7b4b94c2c50a7315c0275d2258399280fbb7d04182c7e55e24b5f93997", + "sha256:9aa0825139c02b3434d913545c7b847a21c835e11597f5255842d457da2322db" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==5.0.0" + "version": "==5.1.1" }, "types-python-dateutil": { "hashes": [ - "sha256:5d2f2e240b86905e40944dd787db6da9263f0deabef1076ddaed797351ec0202", - "sha256:6b8cb66d960771ce5ff974e9dd45e38facb81718cc1e208b10b1baccbfdbee3b" + "sha256:27c8cc2d058ccb14946eebcaaa503088f4f6dbc4fb6093d3d456a49aef2753f6", + "sha256:9706c3b68284c25adffc47319ecc7947e5bb86b3773f843c73906fd598bc176e" ], "markers": "python_version >= '3.8'", - "version": "==2.9.0.20240316" + "version": "==2.9.0.20240906" }, "typing-extensions": { "hashes": [ - "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475", - "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb" + "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", + "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8" ], "markers": "python_version >= '3.8'", - "version": "==4.10.0" + "version": "==4.12.2" }, "uri-template": { "hashes": [ @@ -1900,19 +1925,19 @@ }, "urllib3": { "hashes": [ - "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d", - "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19" + "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472", + "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168" ], "markers": "python_version >= '3.8'", - "version": "==2.2.1" + "version": "==2.2.2" }, "virtualenv": { "hashes": [ - "sha256:961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a", - "sha256:e08e13ecdca7a0bd53798f356d5831434afa5b07b93f0abdf0797b7a06ffe197" + "sha256:48f2695d9809277003f30776d155615ffc11328e6a0a8c1f0ec80188d7874a55", + "sha256:c17f4e0f3e6036e9f26700446f85c76ab11df65ff6d8a9cbfad9f71aabfcf23c" ], "markers": "python_version >= '3.7'", - "version": "==20.25.1" + "version": "==20.26.4" }, "wcwidth": { "hashes": [ @@ -1923,10 +1948,10 @@ }, "webcolors": { "hashes": [ - "sha256:29bc7e8752c0a1bd4a1f03c14d6e6a72e93d82193738fa860cbff59d0fcc11bf", - "sha256:c225b674c83fa923be93d235330ce0300373d02885cef23238813b0d5668304a" + "sha256:08b07af286a01bcd30d583a7acadf629583d1f79bfef27dd2c2c5c263817277d", + "sha256:fc4c3b59358ada164552084a8ebee637c221e4059267d0f8325b3b560f6c7f0a" ], - "version": "==1.13" + "version": "==24.8.0" }, "webencodings": { "hashes": [ @@ -1937,20 +1962,20 @@ }, "websocket-client": { "hashes": [ - "sha256:10e511ea3a8c744631d3bd77e61eb17ed09304c413ad42cf6ddfa4c7787e8fe6", - "sha256:f4c3d22fec12a2461427a29957ff07d35098ee2d976d3ba244e688b8b4057588" + "sha256:17b44cc997f5c498e809b22cdf2d9c7a9e71c02c8cc2b6c56e7c2d1239bfa526", + "sha256:3239df9f44da632f96012472805d40a23281a991027ce11d2f45a6f24ac4c3da" ], "markers": "python_version >= '3.8'", - "version": "==1.7.0" + "version": "==1.8.0" }, "wheel": { "hashes": [ - "sha256:465ef92c69fa5c5da2d1cf8ac40559a8c940886afcef87dcf14b9470862f1d85", - "sha256:55c570405f142630c6b9f72fe09d9b67cf1477fcf543ae5b8dcb1f5b7377da81" + "sha256:2376a90c98cc337d18623527a97c31797bd02bad0033d41547043a1cbfbe448f", + "sha256:a29c3f2817e95ab89aa4660681ad547c0e9547f20e75b0562fe7723c9a2a9d49" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==0.43.0" + "version": "==0.44.0" }, "wrapt": { "hashes": [ @@ -2038,11 +2063,11 @@ }, "zipp": { "hashes": [ - "sha256:206f5a15f2af3dbaee80769fb7dc6f249695e940acca08dfb2a4769fe61e538b", - "sha256:2884ed22e7d8961de1c9a05142eb69a247f120291bc0206a00a7642f09b5b715" + "sha256:9960cd8967c8f85a56f920d5d507274e74f9ff813a0ab8889a5b5be2daf44064", + "sha256:c22b14cc4763c5a5b04134207736c107db42e9d3ef2d9779d465f5f1bcba572b" ], "markers": "python_version >= '3.8'", - "version": "==3.18.1" + "version": "==3.20.1" } } } diff --git a/README.md b/README.md index fae11d7..5971d33 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ Nodes can be plain strings or objects
(De)Serialize to (compressed) JSON
Save as Mermaid flow diagram
Different traversal methods
+Generate random trees
Fully type annotated
Convert to RDF graph
Typed child nodes
diff --git a/docs/sphinx/conf.py b/docs/sphinx/conf.py index e5fa685..0b08295 100644 --- a/docs/sphinx/conf.py +++ b/docs/sphinx/conf.py @@ -119,7 +119,7 @@ # General information about the project. project = u'nutree' -copyright = u'2021-2023, Martin Wendt' +copyright = u'2021-2024, Martin Wendt' author = u'Martin Wendt' # The version info for the project you're documenting, acts as replacement for @@ -130,19 +130,25 @@ #version = '1.0' # The full version, including alpha/beta/rc tags. #release = '1.0' -import pkg_resources +import importlib try: - release = pkg_resources.get_distribution('nutree').version - # print( "release", release) - del pkg_resources -except pkg_resources.DistributionNotFound: - print('To build the documentation, The distribution information') - print('Has to be available. Either install the package into your') + # release = pkg_resources.get_distribution("nutree").version + release = importlib.metadata.version("nutree") +except importlib.metadata.PackageNotFoundError: + print("To build the documentation, The distribution information") + print("has to be available. Either install the package into your") print('development environment or run "setup.py develop" to setup the') - print('metadata. A virtualenv is recommended!') + print("metadata. A virtualenv is recommended!") + + print(f"sys.path: {sys.path}") + print(f"package_root: {package_root}") + for fn in os.listdir(package_root): + print("-", fn) sys.exit(1) +del importlib.metadata + version = '.'.join(release.split('.')[:2]) # The language for content autogenerated by Sphinx. Refer to documentation diff --git a/docs/sphinx/index.rst b/docs/sphinx/index.rst index 3ed7931..351651f 100644 --- a/docs/sphinx/index.rst +++ b/docs/sphinx/index.rst @@ -96,8 +96,9 @@ Nutree Facts * :ref:`(De)Serialize to (compressed) JSON ` * :ref:`Save as Mermaid flow diagram ` * :ref:`Different traversal methods ` - * :ref:`Fully type annotated ` + * :ref:`Generate random trees ` * :ref:`Convert to RDF graph ` + * :ref:`Fully type annotated ` * :ref:`Typed child nodes ` * :ref:`Pretty print ` * :ref:`Navigation ` diff --git a/docs/sphinx/reference_guide.rst b/docs/sphinx/reference_guide.rst index a8e263f..669d589 100644 --- a/docs/sphinx/reference_guide.rst +++ b/docs/sphinx/reference_guide.rst @@ -5,10 +5,18 @@ Reference Guide Class Overview ============== +nutree classes +-------------- + .. inheritance-diagram:: nutree.tree nutree.node nutree.typed_tree nutree.common :parts: 2 :private-bases: - :caption: nutree classes + +Random tree generator +--------------------- + +.. inheritance-diagram:: nutree.tree_generator + :parts: 2 .. API diff --git a/docs/sphinx/ug_basics.rst b/docs/sphinx/ug_basics.rst index 0915e05..f55315b 100644 --- a/docs/sphinx/ug_basics.rst +++ b/docs/sphinx/ug_basics.rst @@ -4,6 +4,12 @@ Basics .. py:currentmodule:: nutree +.. admonition:: TL;DR + + Nutree is a Python library for managing hierarchical data structures. + It stores arbitrary data objects in nodes and provides methods for + navigation, searching, and iteration. + Adding Nodes ------------ @@ -35,8 +41,8 @@ Nodes are usually created by adding a new data instance to a parent:: .. seealso:: - See :doc:`ug_objects` for details on how to manage arbitrary objects instead - of plain strings. + See :doc:`ug_objects` for details on how to manage arbitrary objects, dicts, + etc. instead of plain strings. Info and Navigation diff --git a/docs/sphinx/ug_clones.rst b/docs/sphinx/ug_clones.rst index a879b2e..4336f9f 100644 --- a/docs/sphinx/ug_clones.rst +++ b/docs/sphinx/ug_clones.rst @@ -6,6 +6,10 @@ Multiple Instances ('Clones') .. py:currentmodule:: nutree +.. admonition:: TL;DR + + Nutree allows to store multiple references to the same data object in a tree. + Every :class:`~nutree.node.Node` instance is unique within the tree and also has a unique `node.node_id` value. diff --git a/docs/sphinx/ug_diff.rst b/docs/sphinx/ug_diff.rst index 543c5e2..0ad30a9 100644 --- a/docs/sphinx/ug_diff.rst +++ b/docs/sphinx/ug_diff.rst @@ -6,6 +6,10 @@ Diff and Merge .. py:currentmodule:: nutree +.. admonition:: TL;DR + + Nutree provides a `diff` method to compare two trees and calculate the differences. + The :meth:`~nutree.tree.Tree.diff` method compares a tree (`T0`) against another one (`T1`) and returns a merged, annotated copy. diff --git a/docs/sphinx/ug_graphs.rst b/docs/sphinx/ug_graphs.rst index 4a1b862..2330b76 100644 --- a/docs/sphinx/ug_graphs.rst +++ b/docs/sphinx/ug_graphs.rst @@ -6,6 +6,15 @@ Graphs .. py:currentmodule:: nutree +.. admonition:: TL;DR + + Nutree implements conversion to `DOT `_ + and `Mermaid `_ formats. |br| + This allows to visualize trees as graphs in various formats like `png`, `svg`, etc. |br| + The :class:`~nutree.typed_tree.TypedTree` class introduces the concept of + `typed nodes`, which allows to generate labelled edges in the graph representation. + + .. note:: :class:`~nutree.tree.Tree` (and :class:`~nutree.typed_tree.TypedTree` even more so) has features that make mapping to a graph easy. diff --git a/docs/sphinx/ug_mutation.rst b/docs/sphinx/ug_mutation.rst index 115c32b..d5ccd9d 100644 --- a/docs/sphinx/ug_mutation.rst +++ b/docs/sphinx/ug_mutation.rst @@ -6,6 +6,12 @@ Mutation .. py:currentmodule:: nutree +.. admonition:: TL;DR + + Nutree provides methods to modify the tree structure in-place. |br| + This includes adding, moving, and deleting nodes, as well as filtering and sorting. + + Some in-place modifications are available:: # Tree diff --git a/docs/sphinx/ug_objects.rst b/docs/sphinx/ug_objects.rst index 1ec4ec7..a9ad9a7 100644 --- a/docs/sphinx/ug_objects.rst +++ b/docs/sphinx/ug_objects.rst @@ -6,6 +6,14 @@ Working with Objects .. py:currentmodule:: nutree +.. admonition:: TL;DR + + Nutree allows to store arbitrary objects in its nodes without the + need to modify them or derive from a common base class. |br| + It also supports shadow attributes for direct access to object attributes. |br| + Some objects like *dicts* or *dataclasses* are unhashable and require special + handling. + The previous examples used plain strings as data objects. However, any Python object can be stored, as long as it is `hashable`. @@ -37,7 +45,7 @@ We can add instances of these classes to our tree:: ... For bookkeeping, lookups, and serialization, every data object needs a `data_id`. -This value defaults to ``hash(data)``, which is good enough in many cases. :: +This value defaults to ``hash(data)``, which is good enough in many cases:: assert tree[alice].data_id == hash(alice) @@ -46,7 +54,7 @@ to be useful for persistence. In our example, we already have object GUIDs, whic we want to use instead. This can be achieved by passing a callback to the tree:: def _calc_id(tree, data): - if isinstance(data, fixture.Person): + if isinstance(data, Person): return data.guid return hash(data) @@ -79,13 +87,12 @@ Shadow Attributes (Attribute Aliasing) When storing arbitrary objects within a tree node, all its attributes must be accessed through the ``node.data`` attribute. |br| -This can be simplified by using the ``shadow_attrs`` argument, which allow to +This can be simplified by using the ``shadow_attrs`` argument, which allows to access ``node.data.age`` as ``node.age`` for example:: tree = Tree("Persons", shadow_attrs=True) - dev = tree.add(Department("Development")) alice = Person("Alice", age=23, guid="{123-456}") - alice_node = dev.add(alice) + alice_node = tree.add(alice) # Standard access using `node.data`: assert alice_node.data is alice @@ -96,15 +103,17 @@ access ``node.data.age`` as ``node.age`` for example:: assert alice_node.guid == "{123-456}" assert alice_node.age == 23 + # Note also: shadow attributes are readonly: + alice_node.age = 24 # ERROR: raises AttributeError + + # But we can still modify the data object directly: + alice_node.data.age = 24 # OK! + # Note caveat: `node.name` is not shadowed, but a native property: assert alice.data.name == "Alice" assert alice.name == "Person" - # Note also: shadow attributes are readonly: - alice.age = 24 # ERROR: raises AttributeError - alice.data.age = 24 # OK! - -.. note:: +.. warning:: Aliasing only works for attribute names that are **not** part of the native :class:`~nutree.node.Node` data model. So these attributes will always return @@ -114,3 +123,118 @@ access ``node.data.age`` as ``node.age`` for example:: Note also that shadow attributes are readonly. + +.. _generic-node-data: + +Dictionaries (GenericNodeData) +------------------------------ + +Python +`dictionaries `_ +are unhashable and cannot be used as node data objects. |br| +We can handle this in different ways: + +1. Explicitly set the `data_id` when adding the dict: |br| + ``tree.add({"name": "Alice", "age": 23, "guid": "{123-456}"}, data_id="{123-456}")`` +2. Use a custom `calc_data_id` callback function that returns a unique key for + the data object (see example above). +3. Wrap the dict in :class:`~nutree.common.GenericNodeData`. + +The :class:`~nutree.common.GenericNodeData` class is a simple wrapper around a +dictionary that + +- is hashable, so it can be used added to the tree as ``node.data`` +- stores a reference to the original dict internally as ``node.data._dict`` +- allows readonly access to dict keys as shadow attributes, i.e. + ``node.data._dict["name"]`` can be accessed as ``node.data.name``. |br| + If ``shadow_attrs=True`` is passed to the tree constructor, it can also be + accessed as ``node.name``. |br| + Note that shadow attributes are readonly. +- allows access to dict keys by index, i.e. ``node.data["name"]`` + +Examples :: + + from nutree import Tree, GenericNodeData + + tree = Tree(shadow_attrs=True) + + d = {"a": 1, "b": 2} + obj = GenericNodeData(d) + +We can now add the wrapped `dict` to the tree:: + + node = tree.add_child(obj) + + assert node.data._dict is d, "stored as reference" + assert node.data._dict["a"] == 1 + + assert node.data.a == 1, "accessible as data attribute" + assert node.data["a"] == 1, "accessible by index" + + # Since we enabled shadow_attrs, this is also possible: + assert node.a == 1, "accessible as node attribute" + + # Note: shadow attributes are readonly: + node.a = 99 # ERROR: raises AttributeError + node.data["a"] = 99 # ERROR: raises TypeError + + # We need to access the dict directly to modify it + node.data._dict["a"] = 99 + assert node.a == 99, "should reflect changes in dict" + + +GenericNodeData can also be initialized with keyword args like this:: + + obj = GenericNodeData(a=1, b=2) + + +Dataclasses +----------- + +`Dataclasses `_ are a great way +to define simple classes that hold data. However, they are not hashable by default. |br| +We can handle this in different ways:: + + from dataclasses import dataclass + + @dataclass + class Person: + name: str + age: int + guid: str = None + + alice = Person("Alice", age=23, guid="{123-456}") + +.. 1. Explicitly set the `data_id` when adding the dataclass instance. +.. ``tree.add(, data_id="{123-456}")`` +.. 2. Use a custom `calc_data_id` function that returns a unique key for the data object. +.. 3. Make the dataclass hashable by adding a `__hash__` method. +.. 4. Make the dataclass ``frozen=True`` (or ``unsafe_hash=True``). + +Example: Explicitly set the `data_id` when adding the dataclass instance:: + + tree.add(alice, data_id=alice.guid) + +Example: make the dataclass hashable by adding a `__hash__` method:: + + @dataclass + class Person: + name: str + age: int + guid: str = None + + def __hash__(self): + return hash(self.guid) + + alice = Person("Alice", age=23, guid="{123-456}") + + tree.add(alice) + +Example: Use a frozen dataclass instead, which is immutable and hashable by default:: + + @dataclass(frozen=True) + class Person: + name: str + age: int + guid: str = None + diff --git a/docs/sphinx/ug_pretty_print.rst b/docs/sphinx/ug_pretty_print.rst index 4eb1463..9b8695d 100644 --- a/docs/sphinx/ug_pretty_print.rst +++ b/docs/sphinx/ug_pretty_print.rst @@ -6,6 +6,12 @@ Pretty Print .. py:currentmodule:: nutree +.. admonition:: TL;DR + + Nutree provides a `format` method to generate a pretty printed string + representation of the tree structure. + + :meth:`~nutree.tree.Tree.format` produces a pretty formatted string representation:: diff --git a/docs/sphinx/ug_randomize.rst b/docs/sphinx/ug_randomize.rst new file mode 100644 index 0000000..b5edaa9 --- /dev/null +++ b/docs/sphinx/ug_randomize.rst @@ -0,0 +1,153 @@ +.. _randomize: + +--------------------- +Generate Random Trees +--------------------- + +.. py:currentmodule:: nutree + +.. admonition:: TL;DR + + Nutree can generate random tree structures from a structure definition. + +Nutree can generate random tree structures from a structure definition. +This can be used to create hierarchical data for test, demo, or benchmarking of +*nutree* itself. + +The result can also be used as a source for creating fixtures for other targets +in a following next step. |br| +See `Wundebaum demo `_ and the +`fixture generator `_ +for an example. + +The structure is defined as Python dictionary that describes the +parent-child relationships to be created. +This definition is then passed to :meth:`tree.Tree.build_random_tree`:: + + structure_def = { + ... + # Relations define the possible parent / child relationships between + # node types and optionally override the default properties. + "relations": { + "__root__": { # System root, i.e. we define the top nodes here + "TYPE_1": { + # How many instances to create: + ":count": 10, + # Attribute names and values for every instance: + "ATTR_1": "This is a top node", + "ATTR_2": True, + "ATTR_3": 42, + }, + }, + "TYPE_1": { # Potential child nodes of TYPE_1 + "TYPE_2": { + # How many instances to create: + ":count": 3, + # Attribute names and values for every instance: + "title": "This is a child node of TYPE_1", + }, + }, + }, + } + + tree = Tree.build_random_tree(structure_def) + +Example:: + + structure_def = { + #: Name of the new tree (str, optiona) + "name": "fmea", + #: Types define the default properties of the nodes + "types": { + #: Default properties for all node types + "*": { ... }, + #: Specific default properties for each node type (optional) + "TYPE_1": { ... }, + "TYPE_2": { ... }, + ... + }, + #: Relations define the possible parent / child relationships between + #: node types and optionally override the default properties. + "relations": { + "__root__": { + "TYPE_1": { + ":count": 10, + "ATTR_1": "Function {hier_idx}", + "expanded": True, + }, + }, + "function": { + "failure": { + ":count": RangeRandomizer(1, 3), + "title": "Failure {hier_idx}", + }, + }, + "failure": { + "cause": { + ":count": RangeRandomizer(1, 3), + "title": "Cause {hier_idx}", + }, + "effect": { + ":count": RangeRandomizer(1, 3), + "title": "Effect {hier_idx}", + }, + }, + }, + } + tree = Tree.build_random_tree(structure_def) + tree.print() + assert type(tree) is Tree + assert tree.calc_height() == 3 + +Example:: + + structure_def = { + "name": "fmea", + #: Types define the default properties of the nodes + "types": { + #: Default properties for all node types + "*": {":factory": GenericNodeData}, + #: Specific default properties for each node type + "function": {"icon": "bi bi-gear"}, + "failure": {"icon": "bi bi-exclamation-triangle"}, + "cause": {"icon": "bi bi-tools"}, + "effect": {"icon": "bi bi-lightning"}, + }, + #: Relations define the possible parent / child relationships between + #: node types and optionally override the default properties. + "relations": { + "__root__": { + "function": { + ":count": 10, + "title": "Function {hier_idx}", + "expanded": True, + }, + }, + "function": { + "failure": { + ":count": RangeRandomizer(1, 3), + "title": "Failure {hier_idx}", + }, + }, + "failure": { + "cause": { + ":count": RangeRandomizer(1, 3), + "title": "Cause {hier_idx}", + }, + "effect": { + ":count": RangeRandomizer(1, 3), + "title": "Effect {hier_idx}", + }, + }, + }, + } + tree = Tree.build_random_tree(structure_def) + tree.print() + assert type(tree) is Tree + assert tree.calc_height() == 3 + + tree2 = TypedTree.build_random_tree(structure_def) + tree2.print() + assert type(tree2) is TypedTree + assert tree2.calc_height() == 3 + diff --git a/docs/sphinx/ug_search_and_navigate.rst b/docs/sphinx/ug_search_and_navigate.rst index d8714f8..f8d3962 100644 --- a/docs/sphinx/ug_search_and_navigate.rst +++ b/docs/sphinx/ug_search_and_navigate.rst @@ -4,6 +4,10 @@ Search and Navigate .. py:currentmodule:: nutree +.. admonition:: TL;DR + + Nutree provides methods to search, navigate, and iterate tree structures. + .. _navigate: Assuming we have a tree like this:: @@ -101,7 +105,7 @@ Examples:: tree.add("A", data_id="123") assert tree.find("A") is None # not found assert tree.find("123") is None # not found - assert tree.find(data_id="123") is not None # works + assert tree.find(data_id="123") is not None # FOUND! .. _traversal: diff --git a/docs/sphinx/ug_serialize.rst b/docs/sphinx/ug_serialize.rst index 5a2a093..16acad3 100644 --- a/docs/sphinx/ug_serialize.rst +++ b/docs/sphinx/ug_serialize.rst @@ -6,6 +6,11 @@ .. py:currentmodule:: nutree +.. admonition:: TL;DR + + Nutree provides methods to serialize and deserialize tree structures as JSON. + Arbitrary objects can be stored and restored by implementing mappers. |br| + The native format supports compact formatting and optional zipping. Native Format ------------- diff --git a/docs/sphinx/user_guide.rst b/docs/sphinx/user_guide.rst index f3ac240..88ecfea 100644 --- a/docs/sphinx/user_guide.rst +++ b/docs/sphinx/user_guide.rst @@ -108,4 +108,5 @@ kind (str, readonly): ug_serialize ug_diff ug_graphs + ug_randomize ug_advanced diff --git a/nutree/__init__.py b/nutree/__init__.py index 822ae4a..013e163 100644 --- a/nutree/__init__.py +++ b/nutree/__init__.py @@ -20,6 +20,7 @@ from .common import ( AmbiguousMatchError, + GenericNodeData, IterMethod, SelectBranch, SkipBranch, @@ -39,6 +40,7 @@ AmbiguousMatchError, diff_node_formatter, DiffClassification, + GenericNodeData, IterMethod, load_tree_from_fs, SelectBranch, diff --git a/nutree/common.py b/nutree/common.py index 10dae41..792107d 100644 --- a/nutree/common.py +++ b/nutree/common.py @@ -1,4 +1,4 @@ -# (c) 2021-2023 Martin Wendt; see https://github.com/mar10/nutree +# (c) 2021-2024 Martin Wendt; see https://github.com/mar10/nutree # Licensed under the MIT license: https://www.opensource.org/licenses/mit-license.php """ Functions and declarations used by the :mod:`nutree.tree` and :mod:`nutree.node` @@ -13,12 +13,14 @@ from contextlib import contextmanager from enum import Enum from pathlib import Path -from typing import IO, TYPE_CHECKING, Any, Callable, Dict, List, Type, Union +from typing import IO, TYPE_CHECKING, Any, Callable, Dict, List, Type, TypeVar, Union if TYPE_CHECKING: # Imported by type checkers, but prevent circular includes from .node import Node from .tree import Tree + TTree = TypeVar("TTree", bound=Tree) + #: Used as ID for the system root node ROOT_ID: str = "__root__" @@ -158,6 +160,98 @@ def __init__(self, value=None): "round43c": (" ", "│ ", "╰── ", "├── ", "╰─┬ ", "├─┬ "), } +# ------------------------------------------------------------------------------ +# Generic data object to be used when nutree.Node instances +# ------------------------------------------------------------------------------ + + +class GenericNodeData: + """Can be used as `node.data` instance for dict-like data. + + Initialized with a dictionary of values. The values can be accessed + via the `node.data` attribute like `node.data["KEY"]`. + If the Tree is initialized with `shadow_attrs=True`, the values are also + available as attributes of the node like `node.KEY`. + + If the tree is serialized, the values are copied to the serialized data. + + Examples:: + + tree = Tree(shadow_attrs=True) + + d = {"a": 1, "b": 2} + obj = GenericNodeData(d) + node = tree.add_child(obj) + + assert node.data.values is d, "stored as reference" + assert node.data.values["a"] == 1 + + assert node.data.a == 1, "accessible as data attribute" + assert node.data["a"] == 1, "accessible by index" + + # Since we enabled shadow_attrs, this is also possible: + assert node.a == 1, "accessible as node attribute" + + + Alternatively, the data can be initialized with keyword args like this:: + + obj = GenericNodeData(a=1, b=2) + + or with a dictionary like this. Note that in this case we unpack the dictionary + which creates a copy:: + + d = {"a": 1, "b": 2} + obj = GenericNodeData(**d) + + See :ref:`generic-node-data` for details. + """ + + __slots__ = ("_dict",) + + def __init__(self, dict_inst: dict | None = None, **values) -> None: + if dict_inst is not None: + # A dictionary was passed: store a reference to that instance + if not isinstance(dict_inst, dict): + self._dict = None + raise TypeError("dict_inst must be a dictionary or None") + if values: + self._dict = None + raise ValueError("Cannot pass both dict_inst and **values") + self._dict: dict = dict_inst + else: + # Single keyword arguments are passed (probably from unpacked dict): + # store them in a new dictionary + self._dict: dict = values + + def __repr__(self): + return f"{self.__class__.__name__}<{self._dict}>" + + def __getitem__(self, key): + return self._dict[key] + + def __getattr__(self, name: str) -> Any: + """Allow to access values as attributes. + + Assuming the GenericNodeData instance is stored in a Node.data instance, + this allows to access the values like this:: + + node.data.NAME + + If shadow_attrs is enabled, this also allows to access the values like this:: + + node.NAME + + See :ref:`generic-node-data`. + """ + try: + return self._dict[name] + except KeyError: + raise AttributeError(name) from None + + @staticmethod + def serialize_mapper(nutree_node, data): + return nutree_node.data._dict.copy() + def get_version() -> str: from nutree import __version__ @@ -263,7 +357,7 @@ def open_as_uncompressed_input_stream( *, encoding: str = "utf8", auto_uncompress: bool = True, -) -> IO[str]: +) -> IO[str]: # type: ignore """Open a file for reading, decompressing if necessary. Decompression is done by checking for the magic header (independent of the @@ -296,7 +390,7 @@ def open_as_compressed_output_stream( *, compression: bool | int = True, encoding: str = "utf8", -) -> IO[str]: +) -> IO[str]: # type: ignore """Open a file for writing, ZIP-compressing if requested. Example:: diff --git a/nutree/diff.py b/nutree/diff.py index d825a40..31864e0 100644 --- a/nutree/diff.py +++ b/nutree/diff.py @@ -1,4 +1,4 @@ -# (c) 2021-2023 Martin Wendt and contributors; see https://github.com/mar10/nutree +# (c) 2021-2024 Martin Wendt and contributors; see https://github.com/mar10/nutree # Licensed under the MIT license: https://www.opensource.org/licenses/mit-license.php """ Implement diff/merge algorithms. diff --git a/nutree/dot.py b/nutree/dot.py index c1fbdfe..b23fdbe 100644 --- a/nutree/dot.py +++ b/nutree/dot.py @@ -1,4 +1,4 @@ -# (c) 2021-2023 Martin Wendt; see https://github.com/mar10/nutree +# (c) 2021-2024 Martin Wendt; see https://github.com/mar10/nutree # Licensed under the MIT license: https://www.opensource.org/licenses/mit-license.php """ Functions and declarations to support diff --git a/nutree/fs.py b/nutree/fs.py index 949423e..b4a093c 100644 --- a/nutree/fs.py +++ b/nutree/fs.py @@ -1,4 +1,4 @@ -# (c) 2021-2023 Martin Wendt; see https://github.com/mar10/nutree +# (c) 2021-2024 Martin Wendt; see https://github.com/mar10/nutree # Licensed under the MIT license: https://www.opensource.org/licenses/mit-license.php """ Methods and classes to support file system related functionality. diff --git a/nutree/mermaid.py b/nutree/mermaid.py index e0b907a..ce51dde 100644 --- a/nutree/mermaid.py +++ b/nutree/mermaid.py @@ -1,4 +1,4 @@ -# (c) 2021-2023 Martin Wendt; see https://github.com/mar10/nutree +# (c) 2021-2024 Martin Wendt; see https://github.com/mar10/nutree # Licensed under the MIT license: https://www.opensource.org/licenses/mit-license.php """ Functions and declarations to support diff --git a/nutree/node.py b/nutree/node.py index 41f2698..2da16cf 100644 --- a/nutree/node.py +++ b/nutree/node.py @@ -1,4 +1,4 @@ -# (c) 2021-2023 Martin Wendt; see https://github.com/mar10/nutree +# (c) 2021-2024 Martin Wendt; see https://github.com/mar10/nutree # Licensed under the MIT license: https://www.opensource.org/licenses/mit-license.php """ Declare the :class:`~nutree.node.Node` class. @@ -150,7 +150,7 @@ def __getattr__(self, name: str) -> Any: See :ref:`shadow-attributes`. """ if self._tree._shadow_attrs: - return getattr(self.data, name) + return getattr(self._data, name) raise AttributeError # def __iadd__(self, other) -> None: diff --git a/nutree/rdf.py b/nutree/rdf.py index 67db673..c4f2be2 100644 --- a/nutree/rdf.py +++ b/nutree/rdf.py @@ -1,4 +1,4 @@ -# (c) 2021-2023 Martin Wendt; see https://github.com/mar10/nutree +# (c) 2021-2024 Martin Wendt; see https://github.com/mar10/nutree # Licensed under the MIT license: https://www.opensource.org/licenses/mit-license.php """ Functions and declarations to implement `rdflib `_. diff --git a/nutree/tree.py b/nutree/tree.py index 67f96c6..3e6751d 100644 --- a/nutree/tree.py +++ b/nutree/tree.py @@ -1,4 +1,4 @@ -# (c) 2021-2023 Martin Wendt; see https://github.com/mar10/nutree +# (c) 2021-2024 Martin Wendt; see https://github.com/mar10/nutree # Licensed under the MIT license: https://www.opensource.org/licenses/mit-license.php """ Declare the :class:`~nutree.tree.Tree` class. @@ -9,7 +9,7 @@ import random import threading from pathlib import Path -from typing import IO, Any, Iterable, Iterator +from typing import IO, TYPE_CHECKING, Any, Iterable, Iterator from nutree.diff import diff_tree from nutree.mermaid import ( @@ -43,6 +43,9 @@ from .node import Node from .rdf import tree_to_rdf +if TYPE_CHECKING: # Imported by type checkers, but prevent circular includes + from nutree.common import TTree + _DELETED_TAG = "" #: Minimal Python version that is supported by WsgiDAV @@ -842,6 +845,22 @@ def _self_check(self) -> True: assert clone_count == len(node_list) return True + @classmethod + def build_random_tree(cls: type[TTree], structure_def: dict) -> TTree: + """Build a random tree for . + + Returns a new :class:`Tree` instance with random nodes, as defined by + structure_def. + If called like ``TypedTree.build_random_tree(structure_def)``, this + method will return a :class:`~nutree.typed_tree.TypedTree` instance. + + See :ref:`randomize` for details. + """ + from nutree.tree_generator import build_random_tree + + tt = build_random_tree(tree_class=cls, structure_def=structure_def) + return tt + # ------------------------------------------------------------------------------ # - _SystemRootNode diff --git a/nutree/tree_generator.py b/nutree/tree_generator.py new file mode 100644 index 0000000..c81a02a --- /dev/null +++ b/nutree/tree_generator.py @@ -0,0 +1,469 @@ +""" +Implements a generator that creates a random tree structure from a specification. + +Returns a nutree.TypedTree with random data from a specification. + +See :ref:`randomize` for details. + +Example: + +```py +from tree_generator import RangeRandomizer, TextRandomizer, generate_tree + + +structure_definition = { + "name": "fmea", + #: Types define the default properties of the nodes + "types": { + #: Default properties for all node types + # "*": {":factory": WbNode}, + #: Specific default properties for each node type + "function": {"icon": "bi bi-gear"}, + "failure": {"icon": "bi bi-exclamation-triangle"}, + "cause": {"icon": "bi bi-tools"}, + "effect": {"icon": "bi bi-lightning"}, + }, + #: Relations define the possible parent / child relationships between + #: node types and optionally override the default properties. + "relations": { + "__root__": { + "function": { + ":count": 10, + "title": TextRandomizer(("{i}: Provide $(Noun:plural)",)), + "expanded": True, + }, + }, + "function": { + "failure": { + ":count": RangeRandomizer(1, 3), + "title": TextRandomizer("$(Noun:plural) not provided"), + }, + }, + "failure": { + "cause": { + ":count": RangeRandomizer(1, 3), + "title": TextRandomizer("$(Noun:plural) not provided"), + }, + "effect": { + ":count": RangeRandomizer(1, 3), + "title": TextRandomizer("$(Noun:plural) not provided"), + }, + }, + }, +} +tree = generate_tree(structure_definition) +tree.print() +``` +""" + +import random +import sys +from abc import ABC, abstractmethod +from datetime import date, datetime, timedelta, timezone +from typing import TYPE_CHECKING, Any, Sequence, Type, Union + +from nutree.common import GenericNodeData +from nutree.node import Node +from nutree.typed_tree import TypedNode + +try: + from fabulist import Fabulist # type: ignore + + fab = Fabulist() +except ImportError: + # We run without fabulist (with reduced functionality in this case) + Fabulist = None + fab = None + +if TYPE_CHECKING: # Imported by type checkers, but prevent circular includes + from nutree.common import TTree + + +# ------------------------------------------------------------------------------ +# Randomizers +# ------------------------------------------------------------------------------ +class Randomizer(ABC): + """ + Abstract base class for randomizers. + Args: + probability (float, optional): The probability of using the randomizer. + Must be in the range [0.0, 1.0]. Defaults to 1.0. + Attributes: + probability (float): The probability of using the randomizer. + """ + + def __init__(self, *, probability: float = 1.0) -> None: + assert ( + type(probability) is float and 0.0 <= probability <= 1.0 + ), f"probality must be in the range [0.0 .. 1.0]: {probability}" + self.probability = probability + + def _skip_value(self) -> bool: + use = self.probability == 1.0 or random.random() <= self.probability + return not use + + @abstractmethod + def generate(self) -> Any: ... + + +class RangeRandomizer(Randomizer): + """ + A randomizer class that generates random values within a specified range. + + Args: + min_val (Union[float, int]): The minimum value of the range. + max_val (Union[float, int]): The maximum value of the range. + probability (float, optional): The probability of generating a value. + Defaults to 1.0. + none_value (Any, optional): The value to return when skipping generation. + Defaults to None. + + Returns: + Union[float, int, None]: The generated random value, or none_value + if generation is skipped. + """ + + """""" + + def __init__( + self, + min_val: Union[float, int], + max_val: Union[float, int], + *, + probability: float = 1.0, + none_value: Any = None, + ) -> None: + super().__init__(probability=probability) + assert type(min_val) is type( + max_val + ), f"min_val and max_val must be of the same type: {min_val}, {max_val}" + self.is_float = type(min_val) is float + self.min = min_val + self.max = max_val + self.none_value = none_value + assert self.max > self.min + + def generate(self) -> Union[float, int, None]: + if self._skip_value(): + return self.none_value + if self.is_float: + return random.uniform(self.min, self.max) + return random.randrange(self.min, self.max) + + +class DateRangeRandomizer(Randomizer): + """ + A randomizer class that generates random dates within a specified range. + + Args: + min_dt (date): The minimum date of the range. + max_dt (Union[date, int]): The maximum date of the range. + Pass an integer to specify the number of days from min_dt. + as_js_stamp (bool, optional): If True, return the date as a JavaScript + timestamp. Defaults to True. + probability (float, optional): The probability of generating a value. + Defaults to 1.0. + Examples: + >>> DateRangeRandomizer(date(2020, 1, 1), date(2020, 12, 31)).generate() + datetime.date(2020, 3, 7) + >>> DateRangeRandomizer(date(2020, 1, 1), 365).generate() + """ + + def __init__( + self, + min_dt: date, + max_dt: Union[date, int], + *, + as_js_stamp=True, + probability: float = 1.0, + ) -> None: + super().__init__(probability=probability) + assert type(min_dt) is date, f"min_dt must be a date: {min_dt}" + assert type(max_dt) in (date, int), f"max_dt must be a date or int: {max_dt}" + + if type(max_dt) is int: + self.delta_days = max_dt + max_dt = min_dt + timedelta(days=self.delta_days) + else: + self.delta_days = (max_dt - min_dt).days + + assert ( + max_dt > min_dt + ), f"max_dt must be greater than min_dt: {min_dt}, {max_dt}" + + self.min = min_dt + self.max = max_dt + self.as_js_stamp = as_js_stamp + + def generate(self) -> Union[date, None]: + # print(self.min, self.max, self.delta_days, self.probability) + if self._skip_value(): + # print("SKIP") + return + res = self.min + timedelta(days=random.randrange(self.delta_days)) + # print(res) + if self.as_js_stamp: + ONE_DAY_SEC = 24 * 60 * 60 + dt = datetime(res.year, res.month, res.day) + # print(f"{dt=}") + # print(f"{dt=}, {dt.timestamp()=}") + dt_utc = dt.replace(tzinfo=timezone.utc) + stamp_ms = (dt_utc.timestamp() + ONE_DAY_SEC) * 1000.0 + # print(self.min, self.max, self.delta_days, res, stamp_ms) + res = stamp_ms + return res + + +class ValueRandomizer(Randomizer): + """ + A randomizer class that generates a fixed value with a given probability. + + Args: + value (Any): The value to generate. + probability (float): The probability of generating a value [0.0 .. 1.0]. + """ + + def __init__(self, value: Any, *, probability: float) -> None: + super().__init__(probability=probability) + self.value = value + + def generate(self) -> Any: + if self._skip_value(): + return + return self.value + + +class SparseBoolRandomizer(ValueRandomizer): + """ + A randomizer class that generates a boolean value with a given probability. + If the value is False, it is returned as None. + """ + + def __init__(self, *, probability: float) -> None: + super().__init__(True, probability=probability) + + +class SampleRandomizer(Randomizer): + """ + A randomizer class that generates a random value from a sample list. + """ + + def __init__( + self, sample_list: Sequence, *, counts=None, probability: float = 1.0 + ) -> None: + super().__init__(probability=probability) + self.sample_list = sample_list + # TODO: remove this when support for Python 3.8 is removed + if sys.version_info < (3, 9) and counts: + raise RuntimeError("counts argument requires Python 3.9 or later.") + + self.counts = counts + + def generate(self) -> Any: + if self._skip_value(): + return + # TODO: remove this when support for Python 3.8 is removed + if sys.version_info < (3, 9) and not self.counts: + return random.sample(self.sample_list, 1)[0] + return random.sample(self.sample_list, 1, counts=self.counts)[0] + + +# class BoolRandomizer(SampleRandomizer): +# def __init__(self, *, allow_none: bool = False) -> None: +# if allow_none: +# super().__init__((True, False, None)) +# else: +# super().__init__((True, False)) + + +class TextRandomizer(Randomizer): + """ + A randomizer class that generates a random string value from a Fabulist template. + + Uses the [`fabulist`](https://github.com/mar10/fabulist/) library to generate + text values. + + Args: + template (str | list): A template string or list of strings. + probability (float, optional): The probability of generating a value. + Defaults to 1.0. + """ + + def __init__(self, template: Union[str, list], *, probability: float = 1.0) -> None: + super().__init__(probability=probability) + if not fab: + raise RuntimeError("Need fabulist installed to generate random text.") + self.template = template + + def generate(self) -> Any: + if self._skip_value(): + return + return fab.get_quote(self.template) + + +class BlindTextRandomizer(Randomizer): + """ + A randomizer class that generates a random lorem ipsum text value from a template. + + Uses the [`fabulist`](https://github.com/mar10/fabulist/) library to generate + text values. + + Args: + sentence_count (int | tuple, optional): The number of sentences to generate. + Defaults to (2, 6). + dialect (str, optional): The dialect of the text. Defaults to "ipsum". + entropy (int, optional): The entropy of the text. Defaults to 2. + keep_first (bool, optional): If True, keep the first sentence. + Defaults to False. + words_per_sentence (int | tuple, optional): The number of words per sentence. + Defaults to (3, 15). + probability (float, optional): The probability of generating a value. + Defaults to 1.0. + """ + + def __init__( + self, + *, + sentence_count: Union[int, tuple] = (2, 6), + dialect: str = "ipsum", + entropy: int = 2, + keep_first: bool = False, + words_per_sentence: Union[int, tuple] = (3, 15), + probability: float = 1.0, + ) -> None: + super().__init__(probability=probability) + if not fab: + raise RuntimeError("Need fabulist installed to generate random text.") + + self.sentence_count = sentence_count + self.dialect = dialect + self.entropy = entropy + self.keep_first = keep_first + self.words_per_sentence = words_per_sentence + + def generate(self) -> Any: + if self._skip_value(): + return + return fab.get_lorem_paragraph( + sentence_count=self.sentence_count, + dialect=self.dialect, + entropy=self.entropy, + keep_first=self.keep_first, + words_per_sentence=self.words_per_sentence, + ) + + +def _resolve_random(val: Any) -> Any: + if isinstance(val, Randomizer): + return val.generate() + return val + + +def _resolve_random_dict(d: dict, *, macros: dict = None) -> None: + remove = [] + for key in d.keys(): + val = d[key] + + if isinstance(val, Randomizer): + val = val.generate() + if val is None: # Skip due to probability + remove.append(key) + else: + d[key] = val + + if macros and isinstance(val, str): + d[key] = val.format(**macros) + + for key in remove: + d.pop(key) + return + + +# ------------------------------------------------------------------------------ +# Tree Builder +# ------------------------------------------------------------------------------ + + +def _merge_specs(node_type: str, spec: dict, types: dict) -> dict: + res = types.get("*", {}).copy() + res.update(types.get(node_type, {})) + res.update(spec) + return res + + +def _make_tree( + *, + parent_node: Node, + parent_type: str, + types: dict, + relations: dict, + prefix: str, +): + child_specs = relations[parent_type] + + for node_type, spec in child_specs.items(): + spec = _merge_specs(node_type, spec, types) + count = spec.pop(":count", 1) + count = _resolve_random(count) or 0 + callback = spec.pop(":callback", None) + factory = spec.pop(":factory", GenericNodeData) + + for i in range(count): + i += 1 # 1-based + p = f"{prefix}.{i}" if prefix else f"{i}" + + # Resolve `Randomizer` values and expand `{idx}` and `{hier_idx}` macros + data = spec.copy() + + _resolve_random_dict(data, macros={"idx": i, "hier_idx": p}) + + if callback: + callback(data) + + node_data = factory(**data) + + if isinstance(parent_node, TypedNode): + node = parent_node.add_child(node_data, kind=node_type) + else: + node = parent_node.add_child(node_data) + + # Generate child relations + if node_type in relations: + _make_tree( + parent_node=node, + parent_type=node_type, + types=types, + relations=relations, + prefix=p, + ) + + return + + +def build_random_tree(*, tree_class: Type["TTree"], structure_def: dict) -> "TTree": + """ + Return a nutree.TypedTree with random data from a specification. + See :ref:`randomize` for details. + """ + structure_def = structure_def.copy() + + name = structure_def.pop("name", None) + types = structure_def.pop("types", {}) + relations = structure_def.pop("relations") # mandatory + assert not structure_def, f"found extra data: {structure_def}" + assert "__root__" in relations, "missing '__root__' relation" + + tree: TTree = tree_class( + name=name, + shadow_attrs=True, + ) + + _make_tree( + parent_node=tree.system_root, + parent_type="__root__", + types=types, + relations=relations, + prefix="", + ) + + return tree diff --git a/nutree/typed_tree.py b/nutree/typed_tree.py index f1841ca..38f7bfc 100644 --- a/nutree/typed_tree.py +++ b/nutree/typed_tree.py @@ -1,4 +1,4 @@ -# (c) 2021-2023 Martin Wendt; see https://github.com/mar10/nutree +# (c) 2021-2024 Martin Wendt; see https://github.com/mar10/nutree # Licensed under the MIT license: https://www.opensource.org/licenses/mit-license.php """ Declare the :class:`~nutree.tree.TypedTree` class. @@ -9,7 +9,7 @@ from pathlib import Path from typing import IO, Any, Iterator -from nutree.common import ( +from .common import ( ROOT_ID, CalcIdCallbackType, DeserializeMapperType, @@ -23,7 +23,6 @@ ValueMapType, call_mapper, ) - from .node import Node from .tree import Tree @@ -778,6 +777,12 @@ def load( """ return super().load(target, mapper=mapper, file_meta=file_meta) + # @classmethod + # def build_random_tree(cls, structure_def: dict) -> TypedTree: + # """Build a random tree for testing.""" + # tt = build_random_tree(cls, structure_def) + # return tt + # ------------------------------------------------------------------------------ # - _SystemRootTypedNode diff --git a/pyproject.toml b/pyproject.toml index b6dd178..8c5823f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,3 +50,33 @@ ignore = [ # [tool.ruff.pydocstyle] # convention = "google" + +# --- Coverage Settings -------------------------------------------------------- +[tool.pytest.ini_options] +# addopts = "-ra -q --cov=nutree --cov-report=html" +addopts = "-ra -q --cov=nutree" +# addopts = "--cov=nutree --cov-report=html --cov-report=term-missing" + +[tool.coverage.run] +# branch = true +omit = [ + "tests/*", + # nutree/leaves_cli.py + # nutree/cli_common.py + # nutree/monitor/* +] + +[tool.coverage.report] +precision = 1 +# show_missing = true +sort = "Name" +exclude_lines = [ + "pragma: no cover", + "raise NotImplementedError", + "if __name__ == .__main__.:", + "if TYPE_CHECKING:", +] + +[tool.coverage.html] +directory = "build/coverage" + diff --git a/setup.cfg b/setup.cfg index fbae0ea..44abd57 100644 --- a/setup.cfg +++ b/setup.cfg @@ -74,6 +74,8 @@ install_requires = graph = pydot; rdflib; graphviz # pdf = ReportLab>=1.2; RXP # rest = docutils>=0.3; pack ==1.1, ==1.3 +random = fabulist +all = pydot; rdflib; graphviz; fabulist [options.packages.find] where = . @@ -101,26 +103,26 @@ universal = false # docs/sphinx-build # docs/sphinx-build/* -# --- Coverage Settings -------------------------------------------------------- - -[coverage:run] -# branch = True -omit = - tests/* - # nutree/leaves_cli.py - # nutree/cli_common.py - # nutree/monitor/* - -[coverage:report] -precision = 1 -# show_missing = True -sort = Name -exclude_lines = - pragma: no cover - raise NotImplementedError - if __name__ == .__main__.: - if TYPE_CHECKING: - -[coverage:html] -directory = build/coverage +# # --- Coverage Settings -------------------------------------------------------- + +# [coverage:run] +# # branch = True +# omit = +# tests/* +# # nutree/leaves_cli.py +# # nutree/cli_common.py +# # nutree/monitor/* + +# [coverage:report] +# precision = 1 +# # show_missing = True +# sort = Name +# exclude_lines = +# pragma: no cover +# raise NotImplementedError +# if __name__ == .__main__.: +# if TYPE_CHECKING: + +# [coverage:html] +# directory = build/coverage diff --git a/tests/fixture.py b/tests/fixture.py index 63ea796..e8b93ec 100644 --- a/tests/fixture.py +++ b/tests/fixture.py @@ -1,4 +1,4 @@ -# (c) 2021-2023 Martin Wendt; see https://github.com/mar10/nutree +# (c) 2021-2024 Martin Wendt; see https://github.com/mar10/nutree # Licensed under the MIT license: https://www.opensource.org/licenses/mit-license.php """ Test helpers. diff --git a/tests/pytest.ini b/tests/pytest.ini index 09a19bc..aa0702b 100644 --- a/tests/pytest.ini +++ b/tests/pytest.ini @@ -1,6 +1,9 @@ [pytest] # Silence `PytestDeprecationWarning` junit_family = legacy + +# See also pyproject.toml + ; testpaths = ; tests ; src diff --git a/tests/test_bench.py b/tests/test_bench.py index 0e46c07..f2f6d00 100644 --- a/tests/test_bench.py +++ b/tests/test_bench.py @@ -1,4 +1,4 @@ -# (c) 2021-2023 Martin Wendt; see https://github.com/mar10/nutree +# (c) 2021-2024 Martin Wendt; see https://github.com/mar10/nutree # Licensed under the MIT license: https://www.opensource.org/licenses/mit-license.php """ """ diff --git a/tests/test_clones.py b/tests/test_clones.py index c5e8700..094c936 100644 --- a/tests/test_clones.py +++ b/tests/test_clones.py @@ -1,4 +1,4 @@ -# (c) 2021-2023 Martin Wendt; see https://github.com/mar10/nutree +# (c) 2021-2024 Martin Wendt; see https://github.com/mar10/nutree # Licensed under the MIT license: https://www.opensource.org/licenses/mit-license.php """ """ diff --git a/tests/test_core.py b/tests/test_core.py index 54da45a..f97c84c 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -1,4 +1,4 @@ -# (c) 2021-2023 Martin Wendt; see https://github.com/mar10/nutree +# (c) 2021-2024 Martin Wendt; see https://github.com/mar10/nutree # Licensed under the MIT license: https://www.opensource.org/licenses/mit-license.php """ """ diff --git a/tests/test_diff.py b/tests/test_diff.py index dcedb9f..fde3edb 100644 --- a/tests/test_diff.py +++ b/tests/test_diff.py @@ -1,4 +1,4 @@ -# (c) 2021-2023 Martin Wendt; see https://github.com/mar10/nutree +# (c) 2021-2024 Martin Wendt; see https://github.com/mar10/nutree # Licensed under the MIT license: https://www.opensource.org/licenses/mit-license.php """ """ diff --git a/tests/test_objects.py b/tests/test_objects.py index fda1788..0dc221c 100644 --- a/tests/test_objects.py +++ b/tests/test_objects.py @@ -1,4 +1,4 @@ -# (c) 2021-2023 Martin Wendt; see https://github.com/mar10/nutree +# (c) 2021-2024 Martin Wendt; see https://github.com/mar10/nutree # Licensed under the MIT license: https://www.opensource.org/licenses/mit-license.php """ """ @@ -7,6 +7,7 @@ import pytest from nutree import Tree +from nutree.common import GenericNodeData class Item: @@ -114,3 +115,143 @@ def test_shadow_attrs_true(self): # Shadow attributes are readonly with pytest.raises(AttributeError): let_it_be_node.price = 9.99 + + +class TestGenericNodeData: + def setup_method(self): + self.tree = Tree("fixture") + + def teardown_method(self): + self.tree = None + + def test_constructor(self): + d: dict = {"a": 1, "b": 2} + + with pytest.raises(TypeError, match="dict_inst must be a dictionary"): + _ = GenericNodeData("foo") + + with pytest.raises(TypeError): + _ = GenericNodeData("foo", **d) + + with pytest.raises(TypeError): + _ = GenericNodeData("foo", d) + + with pytest.raises(ValueError): + _ = GenericNodeData(d, foo="bar") + + gnd = GenericNodeData(d) + assert gnd._dict is d, "dict should be stored as reference" + + assert gnd.a == 1, "GenericNodeData should support attribute access" + with pytest.raises(AttributeError): + _ = gnd.foo + + assert gnd["a"] == 1, "GenericNodeData should support item access" + with pytest.raises(KeyError): + _ = gnd["foo"] + + gnd = GenericNodeData(**d) + assert gnd._dict is not d, "unpacked dict should be stored as copy" + + def test_dict(self): + tree = Tree(shadow_attrs=True) + + d: dict = {"a": 1, "b": 2} + + # We cannot simply add a dict, because it is unhashable + with pytest.raises(TypeError, match="unhashable type: 'dict'"): + _ = tree.add(d) + + # But we can wrap it in a GenericNodeData instance + node = tree.add(GenericNodeData(d)) + + # The dict is stored as reference + + assert isinstance(node.data, GenericNodeData) + assert node.data._dict is d, "dict should be stored as reference" + assert node.a == 1, "should support attribute access via shadowing" + + with pytest.raises(AttributeError): + # should not allow access to non-existing attributes + _ = node.foo + + with pytest.raises(TypeError, match="'Node' object is not subscriptable"): + # should NOT support item access via indexing + _ = node["a"] + + assert node.data.a == 1, "should support attribute access via data" + + with pytest.raises(AttributeError): + # should not allow access to non-existing attributes + _ = node.data.foo + + assert node.data["a"] == 1, "should support item access via data" + + with pytest.raises(AttributeError, match="object has no attribute 'a'"): + # Shadowing is read-only + _ = node.data.a = 99 + + with pytest.raises( + TypeError, match="'GenericNodeData' object does not support item assignment" + ): + # Index access is read-only + _ = node.data["a"] = 99 + + with pytest.raises( + TypeError, match="'GenericNodeData' object does not support item assignment" + ): + _ = node.data["foo"] = 99 + + # We need to access the dict directly to modify it + node.data._dict["a"] = 99 + assert node.a == 99, "should reflect changes in dict" + + def test_generic_node_data_unpacked(self): + tree = Tree(shadow_attrs=True) + + d: dict = {"a": 1, "b": 2} + + # We can also unpack the dict + node = tree.add(GenericNodeData(**d)) + + assert node.data._dict is not d, "unpacked dict should be stored as copy" + assert node.data._dict == {"a": 1, "b": 2} + assert node.a == 1, "GenericNodeData should support attribute access" + + def test_dataclass(self): + + from dataclasses import FrozenInstanceError, dataclass + + @dataclass + class Item: + name: str + price: float + count: int + + @dataclass(frozen=True) + class FrozenItem: + name: str + price: float + count: int + + tree = Tree(shadow_attrs=True) + + # We cannot simply add a dataclass, because it is mutable and unhashable + with pytest.raises(TypeError, match="unhashable type: 'Item'"): + _ = tree.add(Item("Let It Be", 12.34, 17)) + + # But we can add frozen dataclasses + item = FrozenItem("Let It Be", 12.34, 17) + dict_node = tree.add(item) + + # Frozen dataclasses are immutable + with pytest.raises(FrozenInstanceError): + item.count += 1 + + tree.print() + + assert isinstance(dict_node.data, FrozenItem) + assert dict_node.data is item, "dataclass should be stored as reference" + assert dict_node.price == 12.34, "should support attribute access via shadowing" + with pytest.raises(AttributeError): + _ = dict_node.foo diff --git a/tests/test_serialize.py b/tests/test_serialize.py index 649ff80..b57c3c7 100644 --- a/tests/test_serialize.py +++ b/tests/test_serialize.py @@ -1,4 +1,4 @@ -# (c) 2021-2023 Martin Wendt; see https://github.com/mar10/nutree +# (c) 2021-2024 Martin Wendt; see https://github.com/mar10/nutree # Licensed under the MIT license: https://www.opensource.org/licenses/mit-license.php """ """ @@ -829,9 +829,11 @@ def test_serialize_mermaid_typed(self): Path(__file__).parent / "temp/test_serialize_2.md", ) - @pytest.mark.xfail(reason="mmdc may not be installed") + # @pytest.mark.xfail(reason="mmdc may not be installed") def test_serialize_mermaid_svg(self): """Save/load as typed object tree with clones.""" + if not shutil.which("mmdc"): + raise pytest.skip("mmdc not installed") KEEP_FILES = not fixture.is_running_on_ci() and False tree = fixture.create_typed_tree(style="simple", clones=True, name="Root") diff --git a/tests/test_tree_generator.py b/tests/test_tree_generator.py new file mode 100644 index 0000000..bfc6711 --- /dev/null +++ b/tests/test_tree_generator.py @@ -0,0 +1,133 @@ +""" +Generic tree generator for test data. +""" + +import datetime + +import pytest + +from nutree.common import GenericNodeData +from nutree.tree import Tree +from nutree.tree_generator import ( + BlindTextRandomizer, + DateRangeRandomizer, + RangeRandomizer, + SampleRandomizer, + SparseBoolRandomizer, + TextRandomizer, + ValueRandomizer, + fab, +) +from nutree.typed_tree import TypedTree + + +def test_simple(): + structure_def = { + "name": "fmea", + #: Types define the default properties of the nodes + "types": { + #: Default properties for all node types + "*": {":factory": GenericNodeData}, + #: Specific default properties for each node type + "function": {"icon": "bi bi-gear"}, + "failure": {"icon": "bi bi-exclamation-triangle"}, + "cause": {"icon": "bi bi-tools"}, + "effect": {"icon": "bi bi-lightning"}, + }, + #: Relations define the possible parent / child relationships between + #: node types and optionally override the default properties. + "relations": { + "__root__": { + "function": { + ":count": 3, + "title": "Function {hier_idx}", + "date": DateRangeRandomizer( + datetime.date(2020, 1, 1), datetime.date(2020, 12, 31) + ), + "date2": DateRangeRandomizer( + datetime.date(2020, 1, 1), 365, probability=0.99 + ), + "value": ValueRandomizer("foo", probability=0.5), + "expanded": SparseBoolRandomizer(probability=0.5), + "state": SampleRandomizer(["open", "closed"], probability=0.99), + }, + }, + "function": { + "failure": { + ":count": RangeRandomizer(1, 3), + "title": "Failure {hier_idx}", + }, + }, + "failure": { + "cause": { + ":count": RangeRandomizer(1, 3, probability=0.99), + "title": "Cause {hier_idx}", + }, + "effect": { + ":count": RangeRandomizer(1, 3), + "title": "Effect {hier_idx}", + }, + }, + }, + } + tree = Tree.build_random_tree(structure_def) + tree.print() + assert type(tree) is Tree + assert tree.calc_height() == 3 + + tree2 = TypedTree.build_random_tree(structure_def) + tree2.print() + assert type(tree2) is TypedTree + assert tree2.calc_height() == 3 + + +def test_fabulist(): + + if not fab: + pytest.skip("fabulist not installed") + + structure_def = { + "name": "fmea", + #: Types define the default properties of the nodes + "types": { + #: Default properties for all node types (optional, default + #: is GenericNodeData) + "*": {":factory": GenericNodeData}, + #: Specific default properties for each node type + "function": {"icon": "bi bi-gear"}, + "failure": {"icon": "bi bi-exclamation-triangle"}, + "cause": {"icon": "bi bi-tools"}, + "effect": {"icon": "bi bi-lightning"}, + }, + #: Relations define the possible parent / child relationships between + #: node types and optionally override the default properties. + "relations": { + "__root__": { + "function": { + ":count": 3, + "title": TextRandomizer(("{idx}: Provide $(Noun:plural)",)), + "details": BlindTextRandomizer(dialect="ipsum"), + "expanded": True, + }, + }, + "function": { + "failure": { + ":count": RangeRandomizer(1, 3), + "title": TextRandomizer("$(Noun:plural) not provided"), + }, + }, + "failure": { + "cause": { + ":count": RangeRandomizer(1, 3), + "title": TextRandomizer("$(Noun:plural) not provided"), + }, + "effect": { + ":count": RangeRandomizer(1, 3), + "title": TextRandomizer("$(Noun:plural) not provided"), + }, + }, + }, + } + tree = TypedTree.build_random_tree(structure_def) + tree.print() + assert type(tree) is TypedTree diff --git a/tests/test_typed_tree.py b/tests/test_typed_tree.py index 65eed6e..4eb1a4d 100644 --- a/tests/test_typed_tree.py +++ b/tests/test_typed_tree.py @@ -1,4 +1,4 @@ -# (c) 2021-2023 Martin Wendt; see https://github.com/mar10/nutree +# (c) 2021-2024 Martin Wendt; see https://github.com/mar10/nutree # Licensed under the MIT license: https://www.opensource.org/licenses/mit-license.php """ """ diff --git a/tests/test_typing_concept.py b/tests/test_typing_concept.py index ba9649b..4efe686 100644 --- a/tests/test_typing_concept.py +++ b/tests/test_typing_concept.py @@ -1,4 +1,4 @@ -# (c) 2021-2023 Martin Wendt; see https://github.com/mar10/nutree +# (c) 2021-2024 Martin Wendt; see https://github.com/mar10/nutree # Licensed under the MIT license: https://www.opensource.org/licenses/mit-license.php """ """ diff --git a/tests/tutorial_script.py b/tests/tutorial_script.py index f12b01c..623bdd8 100644 --- a/tests/tutorial_script.py +++ b/tests/tutorial_script.py @@ -1,4 +1,4 @@ -# (c) 2021-2023 Martin Wendt; see https://github.com/mar10/nutree +# (c) 2021-2024 Martin Wendt; see https://github.com/mar10/nutree # Licensed under the MIT license: https://www.opensource.org/licenses/mit-license.php """ """ diff --git a/tox.ini b/tox.ini index 9d327e6..0833798 100644 --- a/tox.ini +++ b/tox.ini @@ -1,13 +1,14 @@ [tox] basepython = python3.12 envlist = - check, - py312, - py311, - py310, - py39, - py38, - ; py37, + check + ; py313 # EoL: 2029-10 + py312 # EoL: 2028-10 + py311 # EoL: 2027-10 + py310 # EoL: 2026-10 + py39 # EoL: 2025-10 + py38 # EoL: 2024-10 + ; py37 # Eol: 2023-06-27 coverage, skip_missing_interpreters = true @@ -24,6 +25,7 @@ setenv = COVERAGE_FILE=.coverage.{envname} # Note: also honors .coveragerc: deps = + fabulist pydot pytest pytest-cov @@ -73,7 +75,7 @@ commands = [testenv:format] -description = Reformat python code using Black and isort +description = Reformat python code using Black, ruff, isort, and pyupgrade # skip_install = true deps = {[testenv:check]deps} @@ -89,6 +91,23 @@ commands = black nutree tests setup.py {[testenv:lint]commands} +[testenv:format-no-pyupgrade] +description = Same a `format` but without pyupgrade, so it runs on windows +# skip_install = true +deps = + {[testenv:check]deps} + pyupgrade +allowlist_externals: + bash +changedir = {toxinidir} +commands = + ; bash -ec 'pyupgrade --py38-plus --exit-zero-even-if-changed nutree/*.py tests/*.py setup.py' + ruff check --fix nutree tests setup.py + ; ruff format nutree tests setup.py + isort --profile black nutree tests setup.py {posargs} + black nutree tests setup.py + {[testenv:lint]commands} + [testenv:docs] description = Build Sphinx documentation (output directory: docs/sphinx-build)