diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index 6ba8a7d..99fb5cd 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -33,6 +33,10 @@ jobs: run: | nix-shell --run "true" + - name: Compile cython + run: | + nix-shell --run "pipenv run make" + - name: Build run: | echo "IMAGE_PATH=$(nix-build --no-out-link)" >> $GITHUB_ENV diff --git a/.gitignore b/.gitignore index 9a32144..58089a3 100644 --- a/.gitignore +++ b/.gitignore @@ -199,3 +199,6 @@ pyrightconfig.json result data/* cert/* + +cython_lib/*.c +cython_lib/*.html diff --git a/Makefile b/Makefile index bf39122..42f1c2d 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,9 @@ -.PHONY: build version dev-start dev-stop dev-logs +.PHONY: setup docker version dev-start dev-stop dev-logs -build: +setup: + python setup.py build_ext --build-lib cython_lib + +docker: docker load < $$(nix-build --no-out-link) version: diff --git a/Pipfile b/Pipfile index e0ad25a..1573735 100644 --- a/Pipfile +++ b/Pipfile @@ -9,6 +9,7 @@ asyncache = "*" authlib = "*" brotlipy = "*" cachetools = "*" +cython = "*" dacite = "*" fastapi = "*" feedgen = "*" @@ -18,11 +19,11 @@ jinja2 = "*" mapbox-vector-tile = "*" motor = "*" networkx = "*" -numba = "*" numpy = "*" orjson = "*" pillow = "*" psutil = "*" +pyinstrument = "*" pyproj = "*" python-dateutil = "*" python-magic = "*" diff --git a/Pipfile.lock b/Pipfile.lock index 964a709..a76572c 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "1939095e68185f7d1d99f198e178e0342448ecae60e78fdc0475a852cff98787" + "sha256": "783a4557aeaaf8e961b5aeed7b9e530c6705e76e400283fa760c19242fb37078" }, "pipfile-spec": 6, "requires": { @@ -18,11 +18,11 @@ "default": { "annotated-types": { "hashes": [ - "sha256:47cdc3490d9ac1506ce92c7aaa76c579dc3509ff11e098fc867e5130ab7be802", - "sha256:58da39888f92c276ad970249761ebea80ba544b77acddaa1a4d6cf78287d45fd" + "sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43", + "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d" ], - "markers": "python_version >= '3.7'", - "version": "==0.5.0" + "markers": "python_version >= '3.8'", + "version": "==0.6.0" }, "anyio": { "hashes": [ @@ -42,11 +42,11 @@ }, "authlib": { "hashes": [ - "sha256:421f7c6b468d907ca2d9afede256f068f87e34d23dd221c07d13d4c234726afb", - "sha256:c88984ea00149a90e3537c964327da930779afa4564e354edfd98410bea01911" + "sha256:959ea62a5b7b5123c5059758296122b57cd2585ae2ed1c0622c21b371ffdae06", + "sha256:9637e4de1fb498310a56900b3e2043a206b03cb11c05422014b0302cbc814be3" ], "index": "pypi", - "version": "==1.2.1" + "version": "==1.3.0" }, "brotlipy": { "hashes": [ @@ -102,88 +102,77 @@ }, "cachetools": { "hashes": [ - "sha256:95ef631eeaea14ba2e36f06437f36463aac3a096799e876ee55e5cdccb102590", - "sha256:dce83f2d9b4e1f732a8cd44af8e8fab2dbe46201467fc98b3ef8f269092bf62b" + "sha256:086ee420196f7b2ab9ca2db2520aca326318b68fe5ba8bc4d49cca91add450f2", + "sha256:861f35a13a451f94e301ce2bec7cac63e881232ccce7ed67fab9b5df4d3beaa1" ], "index": "pypi", - "version": "==5.3.1" + "version": "==5.3.2" }, "certifi": { "hashes": [ - "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082", - "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9" + "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1", + "sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474" ], "markers": "python_version >= '3.6'", - "version": "==2023.7.22" + "version": "==2023.11.17" }, "cffi": { "hashes": [ - "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5", - "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef", - "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104", - "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426", - "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405", - "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375", - "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a", - "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e", - "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc", - "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf", - "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185", - "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497", - "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3", - "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35", - "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c", - "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83", - "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21", - "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca", - "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984", - "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac", - "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd", - "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee", - "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a", - "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2", - "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192", - "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7", - "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585", - "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f", - "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e", - "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27", - "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b", - "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e", - "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e", - "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d", - "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c", - "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415", - "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82", - "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02", - "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314", - "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325", - "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c", - "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3", - "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914", - "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045", - "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d", - "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9", - "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5", - "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2", - "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c", - "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3", - "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2", - "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8", - "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d", - "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d", - "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9", - "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162", - "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76", - "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4", - "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e", - "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9", - "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6", - "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b", - "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01", - "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0" + "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" ], - "version": "==1.15.1" + "markers": "python_version >= '3.8'", + "version": "==1.16.0" }, "click": { "hashes": [ @@ -195,32 +184,89 @@ }, "cryptography": { "hashes": [ - "sha256:004b6ccc95943f6a9ad3142cfabcc769d7ee38a3f60fb0dddbfb431f818c3a67", - "sha256:047c4603aeb4bbd8db2756e38f5b8bd7e94318c047cfe4efeb5d715e08b49311", - "sha256:0d9409894f495d465fe6fda92cb70e8323e9648af912d5b9141d616df40a87b8", - "sha256:23a25c09dfd0d9f28da2352503b23e086f8e78096b9fd585d1d14eca01613e13", - "sha256:2ed09183922d66c4ec5fdaa59b4d14e105c084dd0febd27452de8f6f74704143", - "sha256:35c00f637cd0b9d5b6c6bd11b6c3359194a8eba9c46d4e875a3660e3b400005f", - "sha256:37480760ae08065437e6573d14be973112c9e6dcaf5f11d00147ee74f37a3829", - "sha256:3b224890962a2d7b57cf5eeb16ccaafba6083f7b811829f00476309bce2fe0fd", - "sha256:5a0f09cefded00e648a127048119f77bc2b2ec61e736660b5789e638f43cc397", - "sha256:5b72205a360f3b6176485a333256b9bcd48700fc755fef51c8e7e67c4b63e3ac", - "sha256:7e53db173370dea832190870e975a1e09c86a879b613948f09eb49324218c14d", - "sha256:7febc3094125fc126a7f6fb1f420d0da639f3f32cb15c8ff0dc3997c4549f51a", - "sha256:80907d3faa55dc5434a16579952ac6da800935cd98d14dbd62f6f042c7f5e839", - "sha256:86defa8d248c3fa029da68ce61fe735432b047e32179883bdb1e79ed9bb8195e", - "sha256:8ac4f9ead4bbd0bc8ab2d318f97d85147167a488be0e08814a37eb2f439d5cf6", - "sha256:93530900d14c37a46ce3d6c9e6fd35dbe5f5601bf6b3a5c325c7bffc030344d9", - "sha256:9eeb77214afae972a00dee47382d2591abe77bdae166bda672fb1e24702a3860", - "sha256:b5f4dfe950ff0479f1f00eda09c18798d4f49b98f4e2006d644b3301682ebdca", - "sha256:c3391bd8e6de35f6f1140e50aaeb3e2b3d6a9012536ca23ab0d9c35ec18c8a91", - "sha256:c880eba5175f4307129784eca96f4e70b88e57aa3f680aeba3bab0e980b0f37d", - "sha256:cecfefa17042941f94ab54f769c8ce0fe14beff2694e9ac684176a2535bf9714", - "sha256:e40211b4923ba5a6dc9769eab704bdb3fbb58d56c5b336d30996c24fcf12aadb", - "sha256:efc8ad4e6fc4f1752ebfb58aefece8b4e3c4cae940b0994d43649bdfce8d0d4f" + "sha256:079b85658ea2f59c4f43b70f8119a52414cdb7be34da5d019a77bf96d473b960", + "sha256:09616eeaef406f99046553b8a40fbf8b1e70795a91885ba4c96a70793de5504a", + "sha256:13f93ce9bea8016c253b34afc6bd6a75993e5c40672ed5405a9c832f0d4a00bc", + "sha256:37a138589b12069efb424220bf78eac59ca68b95696fc622b6ccc1c0a197204a", + "sha256:3c78451b78313fa81607fa1b3f1ae0a5ddd8014c38a02d9db0616133987b9cdf", + "sha256:43f2552a2378b44869fe8827aa19e69512e3245a219104438692385b0ee119d1", + "sha256:48a0476626da912a44cc078f9893f292f0b3e4c739caf289268168d8f4702a39", + "sha256:49f0805fc0b2ac8d4882dd52f4a3b935b210935d500b6b805f321addc8177406", + "sha256:5429ec739a29df2e29e15d082f1d9ad683701f0ec7709ca479b3ff2708dae65a", + "sha256:5a1b41bc97f1ad230a41657d9155113c7521953869ae57ac39ac7f1bb471469a", + "sha256:68a2dec79deebc5d26d617bfdf6e8aab065a4f34934b22d3b5010df3ba36612c", + "sha256:7a698cb1dac82c35fcf8fe3417a3aaba97de16a01ac914b89a0889d364d2f6be", + "sha256:841df4caa01008bad253bce2a6f7b47f86dc9f08df4b433c404def869f590a15", + "sha256:90452ba79b8788fa380dfb587cca692976ef4e757b194b093d845e8d99f612f2", + "sha256:928258ba5d6f8ae644e764d0f996d61a8777559f72dfeb2eea7e2fe0ad6e782d", + "sha256:af03b32695b24d85a75d40e1ba39ffe7db7ffcb099fe507b39fd41a565f1b157", + "sha256:b640981bf64a3e978a56167594a0e97db71c89a479da8e175d8bb5be5178c003", + "sha256:c5ca78485a255e03c32b513f8c2bc39fedb7f5c5f8535545bdc223a03b24f248", + "sha256:c7f3201ec47d5207841402594f1d7950879ef890c0c495052fa62f58283fde1a", + "sha256:d5ec85080cce7b0513cfd233914eb8b7bbd0633f1d1703aa28d1dd5a72f678ec", + "sha256:d6c391c021ab1f7a82da5d8d0b3cee2f4b2c455ec86c8aebbc84837a631ff309", + "sha256:e3114da6d7f95d2dee7d3f4eec16dacff819740bbab931aff8648cb13c5ff5e7", + "sha256:f983596065a18a2183e7f79ab3fd4c475205b839e02cbc0efbbf9666c4b3083d" ], "markers": "python_version >= '3.7'", - "version": "==41.0.4" + "version": "==41.0.7" + }, + "cython": { + "hashes": [ + "sha256:01b94304aab87496e81d1f546e71abf57b430b39be4269df1cd7da9928d70b5b", + "sha256:0c636c9ab92c7838231a1ba769e519d953af8294612f3f772a54d3a5250ff23f", + "sha256:0d8a98c7d86ac4d05b251c39faf49423780381aab55fbf2e147f6e006a34a58a", + "sha256:13211b67b29f6ed8e87c137496c73d93aff0330d97940b4fbed72eae37a4a2a0", + "sha256:133057ac45b6fa7fe5d7baada9d3545d09339432f75c0545f556e8c6fecc2932", + "sha256:167b3f3894dcc697cefefac1d198304fae8eb4d5860a7b8bc2459d572e838470", + "sha256:225f8bba6428b8d711ca2d6c738d2e3a4667f6a2ae40f8a7a5256f69f6a3600e", + "sha256:22d2a684122dfb531853d57c8c85c1d5d44be709e12466dca99fa6aee7d8054f", + "sha256:23ceac5315fe899c229e874328742154e331fa41337bb03f6f5264636c351c9e", + "sha256:2c67105f2c6ccf5b3adbcfaecf3c5c9fa8940f9f97955c9ad7d2542151d97d93", + "sha256:30eb2d2938b9195e2c82951713429aff3ad1be9f104437d1536a04eb0cb3dc0e", + "sha256:34d51709e10ad6213b4bf094af7be7ff82bab43216b3c92a07d05b451deeca79", + "sha256:3a83e04fde663b84905f3a20213a4333d13a07b79434300704b70dc552761f8b", + "sha256:3f02c7240abab48d59f0d5fef7064f18f01a2a204616165fa6367a8abf5a8832", + "sha256:45319d2471f4dbf19893ca53785a421107266e18b8cccd2054fce1e3f72a85f1", + "sha256:4e8bf00ec1dd1d92e9ae74d2e6891f087a939e1dfb40c9c7fa5d8d6a26c94f5a", + "sha256:51e8164b1270625ff101e95c3c1c234421520c07a0a3a20ded9e9431d98afce7", + "sha256:539ad5a21141e6420035cf616bcba48d999bf878839e52692f97fc7e2f16265c", + "sha256:55f93d3822bc196b37a8bdfa4ec6a35232a399e97f2baa714bd5ed8ea9b0ce68", + "sha256:5e3a038332973b12e72236e8884dc99601a840334c2c46cfbbb5851cb94166eb", + "sha256:612d83fd1eb5aaa5401a755c1f1aafacd9dab404cd350b90d5f404c98b33e4b3", + "sha256:6a1859af761977530df2cd5c36e31d54e8d6708ad2c4656e7125c482364dc216", + "sha256:79868ec74e4907a8a6e63effe13547c6157f196a162920b1de066da5849ffb8e", + "sha256:79f20c61114c7948cf1214585066406cef4b54a9b935160980e0b6e70ada3a69", + "sha256:7c8d579d13cb81abe704c8b0908d122b81d6e2623265a19c4a6a7377f440debb", + "sha256:812b193c26553f1f375d4f1c50f805c227b24ed2d595bc9cdaf78c992ecc64a4", + "sha256:816f5285d596062c7ef22790de7d75354b58d4417a9fc64cba914aeeb900db0b", + "sha256:82f27a0134fc6bb46032ca5f728d8af984f3be94a3cb01cb70ff1224e551b9cf", + "sha256:848a28ea49166454c3bff927e5a47629eecf1aa755d6fb3290569cba0fc93766", + "sha256:861cf254bf5836d47c2aee86aa75dd93d3de00ccd1b077c3c7a2bb22cba358e7", + "sha256:8ad7c2303a338b2c0b6c6c68f101a6768725934538756096cf3388a5c07a7525", + "sha256:8ea936cf5931297ba07bce121388c4c6266c1b63a9f4d648ae16c92ff090204b", + "sha256:931aade65f77cf59f2a702ac1f549a4836ce221107c740502cbad18d6d8e9511", + "sha256:936ec37b261b226d7404eff23a9aad284098338150d42a53d6a9af12b18d3892", + "sha256:9fcd9a18ee3ac7f460e0841954feb495102ffbdbec0e6c78562f3495cda000dd", + "sha256:b1853bc34ced5ff6473e881fcf6de29da83262552c8f268a0df53b49c2b89e2c", + "sha256:b227643d8a40b68554dc7d37fcd03fc97b4fb0bd2614aeb5f2e07ab244642d36", + "sha256:b65abca78aa5ebc8675c8480b9a53006f6efea9910ad099cf32c9fb5617ef251", + "sha256:b9d0dae6dccd349b8ccf197c10ef2d05c711ca36a649c7eddbab1de2c90b63a1", + "sha256:cd6ae43ef2e596c9a88dbf2a8895be2e32cc2f5bc3c8ba2e7753b69068fc0b2d", + "sha256:e13abb14843397b76d0472c7d33cd260d5f262ab05cc27ed423317e645e29643", + "sha256:e1bdf8a107fdf9e174991aa87a0be7504f60de1ec6bfb1ccfb30e33acac818a0", + "sha256:e34b4b08d795ccca920fa26b099558f4f1e4e3f794e4ba8d3433c5bc2454d50a", + "sha256:e3c0e19bb41de6be9d8afc85795159ca16296be81a586cd9588be0400d44a855", + "sha256:ef5bb0268bfe5992da3ef9292463a5a895ed8700b134ed2c00008d5471b3ba6e", + "sha256:f2602a5c97a3d618b3b847514204ef3349fb414c59e1126c0c2c708d2c5680f8", + "sha256:f3845c4506e0d207c5e268fb02813928f3a1e135de954a379f165ef0d581da47", + "sha256:f674be92673e87dd8ee7cfe553d5960ec4effc5ab15063b9a5e265a51585a31a", + "sha256:f6d8ff62ad55dc0393686438eac4b457a916e4d1118a0b550746bb52b4c756cc", + "sha256:fb299acf3a578573c190c858d49e0cf9d75f4bc49c3f24c5a63804997ef09213", + "sha256:fed25959e4025870fdde5f895fcb126196d22affd4f4fad85a2823e0dddc85b0" + ], + "index": "pypi", + "version": "==3.0.7" }, "dacite": { "hashes": [ @@ -239,18 +285,18 @@ }, "fastapi": { "hashes": [ - "sha256:345844e6a82062f06a096684196aaf96c1198b25c06b72c1311b882aa2d8a35d", - "sha256:5e5f17e826dbd9e9b5a5145976c5cd90bcaa61f2bf9a69aca423f2bcebe44d83" + "sha256:193c2f1b495d1d6561a3dc1ca02a150757322247d895ff6bf15b6eefee24feb9", + "sha256:c7e7453ac8c4b7414bbafcf90127d743559808eee286ae2c9f99a501f0b534a0" ], "index": "pypi", - "version": "==0.103.1" + "version": "==0.106.0" }, "feedgen": { "hashes": [ - "sha256:8e811bdbbed6570034950db23a4388453628a70e689a6e8303ccec430f5a804a" + "sha256:d9bd51c3b5e956a2a52998c3708c4d2c729f2fcc311188e1e5d3b9726393546a" ], "index": "pypi", - "version": "==0.9.0" + "version": "==1.0.0" }, "h11": { "hashes": [ @@ -321,19 +367,19 @@ }, "httpcore": { "hashes": [ - "sha256:13b5e5cd1dca1a6636a6aaea212b19f4f85cd88c366a2b82304181b769aab3c9", - "sha256:adc5398ee0a476567bf87467063ee63584a8bce86078bf748e48754f60202ced" + "sha256:096cc05bca73b8e459a1fc3dcf585148f63e534eae4339559c9b8a8d6399acc7", + "sha256:9fc092e4799b26174648e54b74ed5f683132a464e95643b226e00c2ed2fa6535" ], "markers": "python_version >= '3.8'", - "version": "==0.18.0" + "version": "==1.0.2" }, "httpx": { "hashes": [ - "sha256:181ea7f8ba3a82578be86ef4171554dd45fec26a02556a744db029a0a27b7100", - "sha256:47ecda285389cb32bb2691cc6e069e3ab0205956f681c5b2ad2325719751d875" + "sha256:451b55c30d5185ea6b23c2c793abf9bb237d2a7dfb901ced6ff69ad37ec1dfaf", + "sha256:8915f5a3627c4d47b73e8202457cb28f1266982d1159bd5779d86a80c0eab1cd" ], "index": "pypi", - "version": "==0.25.0" + "version": "==0.26.0" }, "hyperframe": { "hashes": [ @@ -345,11 +391,11 @@ }, "idna": { "hashes": [ - "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4", - "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2" + "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca", + "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f" ], "markers": "python_version >= '3.5'", - "version": "==3.4" + "version": "==3.6" }, "jinja2": { "hashes": [ @@ -367,133 +413,104 @@ "markers": "python_version >= '3.7'", "version": "==1.3.2" }, - "llvmlite": { - "hashes": [ - "sha256:013000a11df84a8b5e4f7fbf2513896ca48441c527d9ae8e375da92bc5575d08", - "sha256:0c79cb7e88403d6c64385bf1e63797af0884caf1f4afa3c8c4bbef1920e28148", - "sha256:0d94e531c763340344198f2c31af6af7b665e9cd2b354e31afa5cf4abfce0a8e", - "sha256:21191c6a9fb4a86d71ec72debbaf39db49590a950c8a2a4ac792c41d16b0a61a", - "sha256:24b3f7e258ea7c07ebf9f70c772e25619de8d207192254beb7644b818a97440b", - "sha256:27d9d11c8dcdb8a8e14e92d0be5bba60f15bdf2fc116b8d27cab40221093a1b0", - "sha256:57c0a3fd031936461f9f24f4cace80a86c9ba09d8b02fa87c209607aae2463cb", - "sha256:6c40e290d930b09bbebe0d05c750b8a9e20af147e8cec8d62aa42e874f46dbfa", - "sha256:6e477d23afbdddb3dde789d29a771e23bcfa1b12485156370dba9df05d529d94", - "sha256:70feadac822f8840f2db6cbb662f1b349fe5d375d8ceb9c907f3919e005dc705", - "sha256:741bb2ab7712c4763483189f0684163fb3ac44087c617698c50654c7d7ab6a24", - "sha256:7d41db345d76d2dfa31871178ce0d8e9fd8aa015aa1b7d4dab84b5cb393901e0", - "sha256:8218d307bd89535207fea1cc1ef5498afcb6d0203153dba214058715fecdb699", - "sha256:876cd5f53cfe51d3a5cf7952dc1a25bd6158f5795739b1f8159c3591b32ed3cb", - "sha256:93ce07a0a6d98ff2fcc34e7d2d315d8d09f6a737539e089f1a8cbe4a3a0313bf", - "sha256:a4af8722ad6cb0dd2d5454ebc5a7bf90867df5f3fcb0787396a3261052caefda", - "sha256:acc81c1279f858e5eab460844cc381e30d6666bc8eea04724b54d4eeb1fd1e54", - "sha256:d8997264291e822689f7d6df4716638f35ff586bef5b8be40e2ba77d6bd9405c", - "sha256:dabfb1a28d26b8c01228f59aec90a61324203dda6b1465c596d577d6380545e8", - "sha256:de31585b867e8d9bae0c15f03e8bf541afcff66ffa5f61e401a738274702bdcd", - "sha256:f150e127d6bc0e74633b8ba210776b0b6fdc82af6dfebf0794318ea97634acd0", - "sha256:f1b5df30581eb8dbdee0e17a1217debb1d7dcd61a092a09726afff441dad5a67", - "sha256:f7b7022f1e2f652722ddd5697987f1aeaf0c9a64f2ee324e03f6e060b28a1bbd", - "sha256:fe265129ecd18957d3653cfb17df1632fa2c57fd0bac1960bc20a8c3ca961197" - ], - "markers": "python_version >= '3.8'", - "version": "==0.41.0" - }, "lxml": { "hashes": [ - "sha256:05186a0f1346ae12553d66df1cfce6f251589fea3ad3da4f3ef4e34b2d58c6a3", - "sha256:075b731ddd9e7f68ad24c635374211376aa05a281673ede86cbe1d1b3455279d", - "sha256:081d32421db5df44c41b7f08a334a090a545c54ba977e47fd7cc2deece78809a", - "sha256:0a3d3487f07c1d7f150894c238299934a2a074ef590b583103a45002035be120", - "sha256:0bfd0767c5c1de2551a120673b72e5d4b628737cb05414f03c3277bf9bed3305", - "sha256:0c0850c8b02c298d3c7006b23e98249515ac57430e16a166873fc47a5d549287", - "sha256:0e2cb47860da1f7e9a5256254b74ae331687b9672dfa780eed355c4c9c3dbd23", - "sha256:120fa9349a24c7043854c53cae8cec227e1f79195a7493e09e0c12e29f918e52", - "sha256:1247694b26342a7bf47c02e513d32225ededd18045264d40758abeb3c838a51f", - "sha256:141f1d1a9b663c679dc524af3ea1773e618907e96075262726c7612c02b149a4", - "sha256:14e019fd83b831b2e61baed40cab76222139926b1fb5ed0e79225bc0cae14584", - "sha256:1509dd12b773c02acd154582088820893109f6ca27ef7291b003d0e81666109f", - "sha256:17a753023436a18e27dd7769e798ce302963c236bc4114ceee5b25c18c52c693", - "sha256:1e224d5755dba2f4a9498e150c43792392ac9b5380aa1b845f98a1618c94eeef", - "sha256:1f447ea5429b54f9582d4b955f5f1985f278ce5cf169f72eea8afd9502973dd5", - "sha256:23eed6d7b1a3336ad92d8e39d4bfe09073c31bfe502f20ca5116b2a334f8ec02", - "sha256:25f32acefac14ef7bd53e4218fe93b804ef6f6b92ffdb4322bb6d49d94cad2bc", - "sha256:2c74524e179f2ad6d2a4f7caf70e2d96639c0954c943ad601a9e146c76408ed7", - "sha256:303bf1edce6ced16bf67a18a1cf8339d0db79577eec5d9a6d4a80f0fb10aa2da", - "sha256:3331bece23c9ee066e0fb3f96c61322b9e0f54d775fccefff4c38ca488de283a", - "sha256:3e9bdd30efde2b9ccfa9cb5768ba04fe71b018a25ea093379c857c9dad262c40", - "sha256:411007c0d88188d9f621b11d252cce90c4a2d1a49db6c068e3c16422f306eab8", - "sha256:42871176e7896d5d45138f6d28751053c711ed4d48d8e30b498da155af39aebd", - "sha256:46f409a2d60f634fe550f7133ed30ad5321ae2e6630f13657fb9479506b00601", - "sha256:48628bd53a426c9eb9bc066a923acaa0878d1e86129fd5359aee99285f4eed9c", - "sha256:48d6ed886b343d11493129e019da91d4039826794a3e3027321c56d9e71505be", - "sha256:4930be26af26ac545c3dffb662521d4e6268352866956672231887d18f0eaab2", - "sha256:4aec80cde9197340bc353d2768e2a75f5f60bacda2bab72ab1dc499589b3878c", - "sha256:4c28a9144688aef80d6ea666c809b4b0e50010a2aca784c97f5e6bf143d9f129", - "sha256:4d2d1edbca80b510443f51afd8496be95529db04a509bc8faee49c7b0fb6d2cc", - "sha256:4dd9a263e845a72eacb60d12401e37c616438ea2e5442885f65082c276dfb2b2", - "sha256:4f1026bc732b6a7f96369f7bfe1a4f2290fb34dce00d8644bc3036fb351a4ca1", - "sha256:4fb960a632a49f2f089d522f70496640fdf1218f1243889da3822e0a9f5f3ba7", - "sha256:50670615eaf97227d5dc60de2dc99fb134a7130d310d783314e7724bf163f75d", - "sha256:50baa9c1c47efcaef189f31e3d00d697c6d4afda5c3cde0302d063492ff9b477", - "sha256:53ace1c1fd5a74ef662f844a0413446c0629d151055340e9893da958a374f70d", - "sha256:5515edd2a6d1a5a70bfcdee23b42ec33425e405c5b351478ab7dc9347228f96e", - "sha256:56dc1f1ebccc656d1b3ed288f11e27172a01503fc016bcabdcbc0978b19352b7", - "sha256:578695735c5a3f51569810dfebd05dd6f888147a34f0f98d4bb27e92b76e05c2", - "sha256:57aba1bbdf450b726d58b2aea5fe47c7875f5afb2c4a23784ed78f19a0462574", - "sha256:57d6ba0ca2b0c462f339640d22882acc711de224d769edf29962b09f77129cbf", - "sha256:5c245b783db29c4e4fbbbfc9c5a78be496c9fea25517f90606aa1f6b2b3d5f7b", - "sha256:5c31c7462abdf8f2ac0577d9f05279727e698f97ecbb02f17939ea99ae8daa98", - "sha256:64f479d719dc9f4c813ad9bb6b28f8390360660b73b2e4beb4cb0ae7104f1c12", - "sha256:65299ea57d82fb91c7f019300d24050c4ddeb7c5a190e076b5f48a2b43d19c42", - "sha256:6689a3d7fd13dc687e9102a27e98ef33730ac4fe37795d5036d18b4d527abd35", - "sha256:690dafd0b187ed38583a648076865d8c229661ed20e48f2335d68e2cf7dc829d", - "sha256:6fc3c450eaa0b56f815c7b62f2b7fba7266c4779adcf1cece9e6deb1de7305ce", - "sha256:704f61ba8c1283c71b16135caf697557f5ecf3e74d9e453233e4771d68a1f42d", - "sha256:71c52db65e4b56b8ddc5bb89fb2e66c558ed9d1a74a45ceb7dcb20c191c3df2f", - "sha256:71d66ee82e7417828af6ecd7db817913cb0cf9d4e61aa0ac1fde0583d84358db", - "sha256:7d298a1bd60c067ea75d9f684f5f3992c9d6766fadbc0bcedd39750bf344c2f4", - "sha256:8b77946fd508cbf0fccd8e400a7f71d4ac0e1595812e66025bac475a8e811694", - "sha256:8d7e43bd40f65f7d97ad8ef5c9b1778943d02f04febef12def25f7583d19baac", - "sha256:8df133a2ea5e74eef5e8fc6f19b9e085f758768a16e9877a60aec455ed2609b2", - "sha256:8ed74706b26ad100433da4b9d807eae371efaa266ffc3e9191ea436087a9d6a7", - "sha256:92af161ecbdb2883c4593d5ed4815ea71b31fafd7fd05789b23100d081ecac96", - "sha256:97047f0d25cd4bcae81f9ec9dc290ca3e15927c192df17331b53bebe0e3ff96d", - "sha256:9719fe17307a9e814580af1f5c6e05ca593b12fb7e44fe62450a5384dbf61b4b", - "sha256:9767e79108424fb6c3edf8f81e6730666a50feb01a328f4a016464a5893f835a", - "sha256:9a92d3faef50658dd2c5470af249985782bf754c4e18e15afb67d3ab06233f13", - "sha256:9bb6ad405121241e99a86efff22d3ef469024ce22875a7ae045896ad23ba2340", - "sha256:9e28c51fa0ce5674be9f560c6761c1b441631901993f76700b1b30ca6c8378d6", - "sha256:aca086dc5f9ef98c512bac8efea4483eb84abbf926eaeedf7b91479feb092458", - "sha256:ae8b9c6deb1e634ba4f1930eb67ef6e6bf6a44b6eb5ad605642b2d6d5ed9ce3c", - "sha256:b0a545b46b526d418eb91754565ba5b63b1c0b12f9bd2f808c852d9b4b2f9b5c", - "sha256:b4e4bc18382088514ebde9328da057775055940a1f2e18f6ad2d78aa0f3ec5b9", - "sha256:b6420a005548ad52154c8ceab4a1290ff78d757f9e5cbc68f8c77089acd3c432", - "sha256:b86164d2cff4d3aaa1f04a14685cbc072efd0b4f99ca5708b2ad1b9b5988a991", - "sha256:bb3bb49c7a6ad9d981d734ef7c7193bc349ac338776a0360cc671eaee89bcf69", - "sha256:bef4e656f7d98aaa3486d2627e7d2df1157d7e88e7efd43a65aa5dd4714916cf", - "sha256:c0781a98ff5e6586926293e59480b64ddd46282953203c76ae15dbbbf302e8bb", - "sha256:c2006f5c8d28dee289f7020f721354362fa304acbaaf9745751ac4006650254b", - "sha256:c41bfca0bd3532d53d16fd34d20806d5c2b1ace22a2f2e4c0008570bf2c58833", - "sha256:cd47b4a0d41d2afa3e58e5bf1f62069255aa2fd6ff5ee41604418ca925911d76", - "sha256:cdb650fc86227eba20de1a29d4b2c1bfe139dc75a0669270033cb2ea3d391b85", - "sha256:cef2502e7e8a96fe5ad686d60b49e1ab03e438bd9123987994528febd569868e", - "sha256:d27be7405547d1f958b60837dc4c1007da90b8b23f54ba1f8b728c78fdb19d50", - "sha256:d37017287a7adb6ab77e1c5bee9bcf9660f90ff445042b790402a654d2ad81d8", - "sha256:d3ff32724f98fbbbfa9f49d82852b159e9784d6094983d9a8b7f2ddaebb063d4", - "sha256:d73d8ecf8ecf10a3bd007f2192725a34bd62898e8da27eb9d32a58084f93962b", - "sha256:dd708cf4ee4408cf46a48b108fb9427bfa00b9b85812a9262b5c668af2533ea5", - "sha256:e3cd95e10c2610c360154afdc2f1480aea394f4a4f1ea0a5eacce49640c9b190", - "sha256:e4da8ca0c0c0aea88fd46be8e44bd49716772358d648cce45fe387f7b92374a7", - "sha256:eadfbbbfb41b44034a4c757fd5d70baccd43296fb894dba0295606a7cf3124aa", - "sha256:ed667f49b11360951e201453fc3967344d0d0263aa415e1619e85ae7fd17b4e0", - "sha256:f3df3db1d336b9356dd3112eae5f5c2b8b377f3bc826848567f10bfddfee77e9", - "sha256:f6bdac493b949141b733c5345b6ba8f87a226029cbabc7e9e121a413e49441e0", - "sha256:fbf521479bcac1e25a663df882c46a641a9bff6b56dc8b0fafaebd2f66fb231b", - "sha256:fc9b106a1bf918db68619fdcd6d5ad4f972fdd19c01d19bdb6bf63f3589a9ec5", - "sha256:fcdd00edfd0a3001e0181eab3e63bd5c74ad3e67152c84f93f13769a40e073a7", - "sha256:fe4bda6bd4340caa6e5cf95e73f8fea5c4bfc55763dd42f1b50a94c1b4a2fbd4" + "sha256:00e91573183ad273e242db5585b52670eddf92bacad095ce25c1e682da14ed91", + "sha256:01bf1df1db327e748dcb152d17389cf6d0a8c5d533ef9bab781e9d5037619229", + "sha256:056a17eaaf3da87a05523472ae84246f87ac2f29a53306466c22e60282e54ff8", + "sha256:0a08c89b23117049ba171bf51d2f9c5f3abf507d65d016d6e0fa2f37e18c0fc5", + "sha256:1343df4e2e6e51182aad12162b23b0a4b3fd77f17527a78c53f0f23573663545", + "sha256:1449f9451cd53e0fd0a7ec2ff5ede4686add13ac7a7bfa6988ff6d75cff3ebe2", + "sha256:16b9ec51cc2feab009e800f2c6327338d6ee4e752c76e95a35c4465e80390ccd", + "sha256:1f10f250430a4caf84115b1e0f23f3615566ca2369d1962f82bef40dd99cd81a", + "sha256:231142459d32779b209aa4b4d460b175cadd604fed856f25c1571a9d78114771", + "sha256:232fd30903d3123be4c435fb5159938c6225ee8607b635a4d3fca847003134ba", + "sha256:23d891e5bdc12e2e506e7d225d6aa929e0a0368c9916c1fddefab88166e98b20", + "sha256:266f655d1baff9c47b52f529b5f6bec33f66042f65f7c56adde3fcf2ed62ae8b", + "sha256:273473d34462ae6e97c0f4e517bd1bf9588aa67a1d47d93f760a1282640e24ac", + "sha256:2bd9ac6e44f2db368ef8986f3989a4cad3de4cd55dbdda536e253000c801bcc7", + "sha256:33714fcf5af4ff7e70a49731a7cc8fd9ce910b9ac194f66eaa18c3cc0a4c02be", + "sha256:359a8b09d712df27849e0bcb62c6a3404e780b274b0b7e4c39a88826d1926c28", + "sha256:365005e8b0718ea6d64b374423e870648ab47c3a905356ab6e5a5ff03962b9a9", + "sha256:389d2b2e543b27962990ab529ac6720c3dded588cc6d0f6557eec153305a3622", + "sha256:3b505f2bbff50d261176e67be24e8909e54b5d9d08b12d4946344066d66b3e43", + "sha256:3d74d4a3c4b8f7a1f676cedf8e84bcc57705a6d7925e6daef7a1e54ae543a197", + "sha256:3f3f00a9061605725df1816f5713d10cd94636347ed651abdbc75828df302b20", + "sha256:43498ea734ccdfb92e1886dfedaebeb81178a241d39a79d5351ba2b671bff2b2", + "sha256:4855161013dfb2b762e02b3f4d4a21cc7c6aec13c69e3bffbf5022b3e708dd97", + "sha256:4d973729ce04784906a19108054e1fd476bc85279a403ea1a72fdb051c76fa48", + "sha256:4ece9cca4cd1c8ba889bfa67eae7f21d0d1a2e715b4d5045395113361e8c533d", + "sha256:506becdf2ecaebaf7f7995f776394fcc8bd8a78022772de66677c84fb02dd33d", + "sha256:520486f27f1d4ce9654154b4494cf9307b495527f3a2908ad4cb48e4f7ed7ef7", + "sha256:5557461f83bb7cc718bc9ee1f7156d50e31747e5b38d79cf40f79ab1447afd2d", + "sha256:562778586949be7e0d7435fcb24aca4810913771f845d99145a6cee64d5b67ca", + "sha256:59bb5979f9941c61e907ee571732219fa4774d5a18f3fa5ff2df963f5dfaa6bc", + "sha256:606d445feeb0856c2b424405236a01c71af7c97e5fe42fbc778634faef2b47e4", + "sha256:6197c3f3c0b960ad033b9b7d611db11285bb461fc6b802c1dd50d04ad715c225", + "sha256:647459b23594f370c1c01768edaa0ba0959afc39caeeb793b43158bb9bb6a663", + "sha256:647bfe88b1997d7ae8d45dabc7c868d8cb0c8412a6e730a7651050b8c7289cf2", + "sha256:6bee9c2e501d835f91460b2c904bc359f8433e96799f5c2ff20feebd9bb1e590", + "sha256:6dbdacf5752fbd78ccdb434698230c4f0f95df7dd956d5f205b5ed6911a1367c", + "sha256:701847a7aaefef121c5c0d855b2affa5f9bd45196ef00266724a80e439220e46", + "sha256:786d6b57026e7e04d184313c1359ac3d68002c33e4b1042ca58c362f1d09ff58", + "sha256:7b378847a09d6bd46047f5f3599cdc64fcb4cc5a5a2dd0a2af610361fbe77b16", + "sha256:7d1d6c9e74c70ddf524e3c09d9dc0522aba9370708c2cb58680ea40174800013", + "sha256:857d6565f9aa3464764c2cb6a2e3c2e75e1970e877c188f4aeae45954a314e0c", + "sha256:8671622256a0859f5089cbe0ce4693c2af407bc053dcc99aadff7f5310b4aa02", + "sha256:88f7c383071981c74ec1998ba9b437659e4fd02a3c4a4d3efc16774eb108d0ec", + "sha256:8aecb5a7f6f7f8fe9cac0bcadd39efaca8bbf8d1bf242e9f175cbe4c925116c3", + "sha256:91bbf398ac8bb7d65a5a52127407c05f75a18d7015a270fdd94bbcb04e65d573", + "sha256:936e8880cc00f839aa4173f94466a8406a96ddce814651075f95837316369899", + "sha256:953dd5481bd6252bd480d6ec431f61d7d87fdcbbb71b0d2bdcfc6ae00bb6fb10", + "sha256:95ae6c5a196e2f239150aa4a479967351df7f44800c93e5a975ec726fef005e2", + "sha256:9a2b5915c333e4364367140443b59f09feae42184459b913f0f41b9fed55794a", + "sha256:9ae6c3363261021144121427b1552b29e7b59de9d6a75bf51e03bc072efb3c37", + "sha256:9b556596c49fa1232b0fff4b0e69b9d4083a502e60e404b44341e2f8fb7187f5", + "sha256:9c131447768ed7bc05a02553d939e7f0e807e533441901dd504e217b76307745", + "sha256:9d9d5726474cbbef279fd709008f91a49c4f758bec9c062dfbba88eab00e3ff9", + "sha256:a1bdcbebd4e13446a14de4dd1825f1e778e099f17f79718b4aeaf2403624b0f7", + "sha256:a602ed9bd2c7d85bd58592c28e101bd9ff9c718fbde06545a70945ffd5d11868", + "sha256:a8edae5253efa75c2fc79a90068fe540b197d1c7ab5803b800fccfe240eed33c", + "sha256:a905affe76f1802edcac554e3ccf68188bea16546071d7583fb1b693f9cf756b", + "sha256:a9e7c6d89c77bb2770c9491d988f26a4b161d05c8ca58f63fb1f1b6b9a74be45", + "sha256:aa9b5abd07f71b081a33115d9758ef6077924082055005808f68feccb27616bd", + "sha256:aaa5c173a26960fe67daa69aa93d6d6a1cd714a6eb13802d4e4bd1d24a530644", + "sha256:ac7674d1638df129d9cb4503d20ffc3922bd463c865ef3cb412f2c926108e9a4", + "sha256:b1541e50b78e15fa06a2670157a1962ef06591d4c998b998047fff5e3236880e", + "sha256:b1980dbcaad634fe78e710c8587383e6e3f61dbe146bcbfd13a9c8ab2d7b1192", + "sha256:bafa65e3acae612a7799ada439bd202403414ebe23f52e5b17f6ffc2eb98c2be", + "sha256:bb5bd6212eb0edfd1e8f254585290ea1dadc3687dd8fd5e2fd9a87c31915cdab", + "sha256:bbdd69e20fe2943b51e2841fc1e6a3c1de460d630f65bde12452d8c97209464d", + "sha256:bc354b1393dce46026ab13075f77b30e40b61b1a53e852e99d3cc5dd1af4bc85", + "sha256:bcee502c649fa6351b44bb014b98c09cb00982a475a1912a9881ca28ab4f9cd9", + "sha256:bdd9abccd0927673cffe601d2c6cdad1c9321bf3437a2f507d6b037ef91ea307", + "sha256:c42ae7e010d7d6bc51875d768110c10e8a59494855c3d4c348b068f5fb81fdcd", + "sha256:c71b5b860c5215fdbaa56f715bc218e45a98477f816b46cfde4a84d25b13274e", + "sha256:c7721a3ef41591341388bb2265395ce522aba52f969d33dacd822da8f018aff8", + "sha256:ca8e44b5ba3edb682ea4e6185b49661fc22b230cf811b9c13963c9f982d1d964", + "sha256:cb53669442895763e61df5c995f0e8361b61662f26c1b04ee82899c2789c8f69", + "sha256:cc02c06e9e320869d7d1bd323df6dd4281e78ac2e7f8526835d3d48c69060683", + "sha256:d3caa09e613ece43ac292fbed513a4bce170681a447d25ffcbc1b647d45a39c5", + "sha256:d82411dbf4d3127b6cde7da0f9373e37ad3a43e89ef374965465928f01c2b979", + "sha256:dbcb2dc07308453db428a95a4d03259bd8caea97d7f0776842299f2d00c72fc8", + "sha256:dd4fda67f5faaef4f9ee5383435048ee3e11ad996901225ad7615bc92245bc8e", + "sha256:ddd92e18b783aeb86ad2132d84a4b795fc5ec612e3545c1b687e7747e66e2b53", + "sha256:de362ac8bc962408ad8fae28f3967ce1a262b5d63ab8cefb42662566737f1dc7", + "sha256:e214025e23db238805a600f1f37bf9f9a15413c7bf5f9d6ae194f84980c78722", + "sha256:e8f9f93a23634cfafbad6e46ad7d09e0f4a25a2400e4a64b1b7b7c0fbaa06d9d", + "sha256:e96a1788f24d03e8d61679f9881a883ecdf9c445a38f9ae3f3f193ab6c591c66", + "sha256:ec53a09aee61d45e7dbe7e91252ff0491b6b5fee3d85b2d45b173d8ab453efc1", + "sha256:f10250bb190fb0742e3e1958dd5c100524c2cc5096c67c8da51233f7448dc137", + "sha256:f1faee2a831fe249e1bae9cbc68d3cd8a30f7e37851deee4d7962b17c410dd56", + "sha256:f610d980e3fccf4394ab3806de6065682982f3d27c12d4ce3ee46a8183d64a6a", + "sha256:f6c35b2f87c004270fa2e703b872fcc984d714d430b305145c39d53074e1ffe0", + "sha256:f836f39678cb47c9541f04d8ed4545719dc31ad850bf1832d6b4171e30d65d23", + "sha256:f99768232f036b4776ce419d3244a04fe83784bce871b16d2c2e984c7fcea847", + "sha256:fd814847901df6e8de13ce69b84c31fc9b3fb591224d6762d0b256d510cbf382", + "sha256:fdb325b7fba1e2c40b9b1db407f85642e32404131c08480dd652110fc908561b" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==4.9.3" + "version": "==4.9.4" }, "mapbox-vector-tile": { "hashes": [ @@ -571,242 +588,216 @@ }, "motor": { "hashes": [ - "sha256:a0dee83ad0d47b353932ac37467ba397b1e649ce7e3eea7f5a90554883d7cdbe", - "sha256:c5eb400e27d722a3db03a9826656b6d13acf9b6c70c2fb4604f474eac9da5be4" + "sha256:6fe7e6f0c4f430b9e030b9d22549b732f7c2226af3ab71ecc309e4a1b7d19953", + "sha256:d2fc38de15f1c8058f389c1a44a4d4105c0405c48c061cd492a654496f7bc26a" ], "index": "pypi", - "version": "==3.3.1" + "version": "==3.3.2" }, "networkx": { "hashes": [ - "sha256:4f33f68cb2afcf86f28a45f43efc27a9386b535d567d2127f8f61d51dec58d36", - "sha256:de346335408f84de0eada6ff9fafafff9bcda11f0a0dfaa931133debb146ab61" + "sha256:9f1bb5cf3409bf324e0a722c20bdb4c20ee39bf1c30ce8ae499c8502b0b5e0c6", + "sha256:f18c69adc97877c42332c170849c96cefa91881c99a7cb3e95b7c659ebdc1ec2" ], "index": "pypi", - "version": "==3.1" - }, - "numba": { - "hashes": [ - "sha256:0734614d3e92eb01f848b8595be116f9c8ad997f8cf77672f3ba53c511f1429d", - "sha256:0ce322178ff7006b7f50dad25b042ef64c6393f2fafafa79c0498d789b1aac27", - "sha256:0d7a5e81e4047a23986f816b48ac46616ceb4eadbff6bbe739944d36b3bdbfe7", - "sha256:121bf98a2b02e0611af3bfab3995fed990db58c4bfc6c225332ccdaf37e312e7", - "sha256:2f146c11af62ad25021d93fccf48715a96d1ea76d43c1c3bc97dca561c6a2693", - "sha256:398ab539257df8e980ec2f9cdfae836bb965fadc2dd30db3fcfbf3aefa542836", - "sha256:477f429bb593dd3fc8d84b44f199e8e30268a7cfeb96c8464cb393d401de4f45", - "sha256:48bcaae337ee450e38bf3796b4e1a166909c339f1757b6110e6adcf42c1e6c3e", - "sha256:5cee5f22f7fbb2ef445e422aeafe5d38bf71a52c8bb34d22c1e145afa4034d6b", - "sha256:7e182f3296dfcbafcd23b9263baeb350ad5adcacd081f1b3ec927a9fb325cca8", - "sha256:7ee9f5fd962e0ada0e68df67a6ff881f95b45e0ae7cb96141e913337040d490b", - "sha256:8059ee491651885f89655f08856a107aa610e3355b373f3b7437f1da96f09703", - "sha256:8a9b69cc6259131791822c5eb893b03cd9372f4aae669d020500565b6d5d80bc", - "sha256:8bd9edd27ab29e80bcf4083f9955c4a8871075a13a370b3bef99f81e184541fa", - "sha256:9dade55ee5f1b8c5e3e0db95449fdc5b7b4244c1a7fa133bd664cbfc1027bafe", - "sha256:a5f99806d5c9671dc927a8a489bc0c88e79be51e9775d6a3c68dbfdf585cd7e9", - "sha256:e5d5a318dc65a101ef846d7fd93f3cf2f7942494019e8342e51238b360739125", - "sha256:e61a1fa0ab7d290f0a43d8523b372f96765db6ceb6a691660c17e9ed609cb470", - "sha256:e7b42b23c36cf08fcfe1a8f2acf3a0af95b41f9ee07fc81b28d7b9b5ada85d8c", - "sha256:f3934eab4eb1c07c8f067e99350b99f70b2ca77d5aa3911d365643171f771157", - "sha256:f80aee7889e82ab9c4770e02b21ca4e3ca15cc8c829c173fc27b77ab0529b5cb" - ], - "index": "pypi", - "version": "==0.58.0" + "version": "==3.2.1" }, "numpy": { "hashes": [ - "sha256:0d60fbae8e0019865fc4784745814cff1c421df5afee233db6d88ab4f14655a2", - "sha256:1a1329e26f46230bf77b02cc19e900db9b52f398d6722ca853349a782d4cff55", - "sha256:1b9735c27cea5d995496f46a8b1cd7b408b3f34b6d50459d9ac8fe3a20cc17bf", - "sha256:2792d23d62ec51e50ce4d4b7d73de8f67a2fd3ea710dcbc8563a51a03fb07b01", - "sha256:3e0746410e73384e70d286f93abf2520035250aad8c5714240b0492a7302fdca", - "sha256:4c3abc71e8b6edba80a01a52e66d83c5d14433cbcd26a40c329ec7ed09f37901", - "sha256:5883c06bb92f2e6c8181df7b39971a5fb436288db58b5a1c3967702d4278691d", - "sha256:5c97325a0ba6f9d041feb9390924614b60b99209a71a69c876f71052521d42a4", - "sha256:60e7f0f7f6d0eee8364b9a6304c2845b9c491ac706048c7e8cf47b83123b8dbf", - "sha256:76b4115d42a7dfc5d485d358728cdd8719be33cc5ec6ec08632a5d6fca2ed380", - "sha256:7dc869c0c75988e1c693d0e2d5b26034644399dd929bc049db55395b1379e044", - "sha256:834b386f2b8210dca38c71a6e0f4fd6922f7d3fcff935dbe3a570945acb1b545", - "sha256:8b77775f4b7df768967a7c8b3567e309f617dd5e99aeb886fa14dc1a0791141f", - "sha256:90319e4f002795ccfc9050110bbbaa16c944b1c37c0baeea43c5fb881693ae1f", - "sha256:b79e513d7aac42ae918db3ad1341a015488530d0bb2a6abcbdd10a3a829ccfd3", - "sha256:bb33d5a1cf360304754913a350edda36d5b8c5331a8237268c48f91253c3a364", - "sha256:bec1e7213c7cb00d67093247f8c4db156fd03075f49876957dca4711306d39c9", - "sha256:c5462d19336db4560041517dbb7759c21d181a67cb01b36ca109b2ae37d32418", - "sha256:c5652ea24d33585ea39eb6a6a15dac87a1206a692719ff45d53c5282e66d4a8f", - "sha256:d7806500e4f5bdd04095e849265e55de20d8cc4b661b038957354327f6d9b295", - "sha256:db3ccc4e37a6873045580d413fe79b68e47a681af8db2e046f1dacfa11f86eb3", - "sha256:dfe4a913e29b418d096e696ddd422d8a5d13ffba4ea91f9f60440a3b759b0187", - "sha256:eb942bfb6f84df5ce05dbf4b46673ffed0d3da59f13635ea9b926af3deb76926", - "sha256:f08f2e037bba04e707eebf4bc934f1972a315c883a9e0ebfa8a7756eabf9e357", - "sha256:fd608e19c8d7c55021dffd43bfe5492fab8cc105cc8986f813f8c3c048b38760" + "sha256:06fa1ed84aa60ea6ef9f91ba57b5ed963c3729534e6e54055fc151fad0423f0a", + "sha256:174a8880739c16c925799c018f3f55b8130c1f7c8e75ab0a6fa9d41cab092fd6", + "sha256:1a13860fdcd95de7cf58bd6f8bc5a5ef81c0b0625eb2c9a783948847abbef2c2", + "sha256:1cc3d5029a30fb5f06704ad6b23b35e11309491c999838c31f124fee32107c79", + "sha256:22f8fc02fdbc829e7a8c578dd8d2e15a9074b630d4da29cda483337e300e3ee9", + "sha256:26c9d33f8e8b846d5a65dd068c14e04018d05533b348d9eaeef6c1bd787f9919", + "sha256:2b3fca8a5b00184828d12b073af4d0fc5fdd94b1632c2477526f6bd7842d700d", + "sha256:2beef57fb031dcc0dc8fa4fe297a742027b954949cabb52a2a376c144e5e6060", + "sha256:36340109af8da8805d8851ef1d74761b3b88e81a9bd80b290bbfed61bd2b4f75", + "sha256:3703fc9258a4a122d17043e57b35e5ef1c5a5837c3db8be396c82e04c1cf9b0f", + "sha256:3ced40d4e9e18242f70dd02d739e44698df3dcb010d31f495ff00a31ef6014fe", + "sha256:4a06263321dfd3598cacb252f51e521a8cb4b6df471bb12a7ee5cbab20ea9167", + "sha256:4eb8df4bf8d3d90d091e0146f6c28492b0be84da3e409ebef54349f71ed271ef", + "sha256:5d5244aabd6ed7f312268b9247be47343a654ebea52a60f002dc70c769048e75", + "sha256:64308ebc366a8ed63fd0bf426b6a9468060962f1a4339ab1074c228fa6ade8e3", + "sha256:6a3cdb4d9c70e6b8c0814239ead47da00934666f668426fc6e94cce869e13fd7", + "sha256:854ab91a2906ef29dc3925a064fcd365c7b4da743f84b123002f6139bcb3f8a7", + "sha256:94cc3c222bb9fb5a12e334d0479b97bb2df446fbe622b470928f5284ffca3f8d", + "sha256:96ca5482c3dbdd051bcd1fce8034603d6ebfc125a7bd59f55b40d8f5d246832b", + "sha256:a2bbc29fcb1771cd7b7425f98b05307776a6baf43035d3b80c4b0f29e9545186", + "sha256:a4cd6ed4a339c21f1d1b0fdf13426cb3b284555c27ac2f156dfdaaa7e16bfab0", + "sha256:aa18428111fb9a591d7a9cc1b48150097ba6a7e8299fb56bdf574df650e7d1f1", + "sha256:aa317b2325f7aa0a9471663e6093c210cb2ae9c0ad824732b307d2c51983d5b6", + "sha256:b04f5dc6b3efdaab541f7857351aac359e6ae3c126e2edb376929bd3b7f92d7e", + "sha256:b272d4cecc32c9e19911891446b72e986157e6a1809b7b56518b4f3755267523", + "sha256:b361d369fc7e5e1714cf827b731ca32bff8d411212fccd29ad98ad622449cc36", + "sha256:b96e7b9c624ef3ae2ae0e04fa9b460f6b9f17ad8b4bec6d7756510f1f6c0c841", + "sha256:baf8aab04a2c0e859da118f0b38617e5ee65d75b83795055fb66c0d5e9e9b818", + "sha256:bcc008217145b3d77abd3e4d5ef586e3bdfba8fe17940769f8aa09b99e856c00", + "sha256:bd3f0091e845164a20bd5a326860c840fe2af79fa12e0469a12768a3ec578d80", + "sha256:cc392fdcbd21d4be6ae1bb4475a03ce3b025cd49a9be5345d76d7585aea69440", + "sha256:d73a3abcac238250091b11caef9ad12413dab01669511779bc9b29261dd50210", + "sha256:f43740ab089277d403aa07567be138fc2a89d4d9892d113b76153e0e412409f8", + "sha256:f65738447676ab5777f11e6bbbdb8ce11b785e105f690bc45966574816b6d3ea", + "sha256:f79b231bf5c16b1f39c7f4875e1ded36abee1591e98742b05d8a0fb55d8a3eec", + "sha256:fe6b44fb8fcdf7eda4ef4461b97b3f63c466b27ab151bec2366db8b197387841" ], "index": "pypi", - "version": "==1.25.2" + "version": "==1.26.2" }, "orjson": { "hashes": [ - "sha256:01d647b2a9c45a23a84c3e70e19d120011cba5f56131d185c1b78685457320bb", - "sha256:0eb850a87e900a9c484150c414e21af53a6125a13f6e378cf4cc11ae86c8f9c5", - "sha256:11c10f31f2c2056585f89d8229a56013bc2fe5de51e095ebc71868d070a8dd81", - "sha256:14d3fb6cd1040a4a4a530b28e8085131ed94ebc90d72793c59a713de34b60838", - "sha256:154fd67216c2ca38a2edb4089584504fbb6c0694b518b9020ad35ecc97252bb9", - "sha256:1c3cee5c23979deb8d1b82dc4cc49be59cccc0547999dbe9adb434bb7af11cf7", - "sha256:1eb0b0b2476f357eb2975ff040ef23978137aa674cd86204cfd15d2d17318588", - "sha256:1f8b47650f90e298b78ecf4df003f66f54acdba6a0f763cc4df1eab048fe3738", - "sha256:21a3344163be3b2c7e22cef14fa5abe957a892b2ea0525ee86ad8186921b6cf0", - "sha256:23be6b22aab83f440b62a6f5975bcabeecb672bc627face6a83bc7aeb495dc7e", - "sha256:26ffb398de58247ff7bde895fe30817a036f967b0ad0e1cf2b54bda5f8dcfdd9", - "sha256:2f8fcf696bbbc584c0c7ed4adb92fd2ad7d153a50258842787bc1524e50d7081", - "sha256:355efdbbf0cecc3bd9b12589b8f8e9f03c813a115efa53f8dc2a523bfdb01334", - "sha256:36b1df2e4095368ee388190687cb1b8557c67bc38400a942a1a77713580b50ae", - "sha256:38e34c3a21ed41a7dbd5349e24c3725be5416641fdeedf8f56fcbab6d981c900", - "sha256:3aab72d2cef7f1dd6104c89b0b4d6b416b0db5ca87cc2fac5f79c5601f549cc2", - "sha256:410aa9d34ad1089898f3db461b7b744d0efcf9252a9415bbdf23540d4f67589f", - "sha256:45a47f41b6c3beeb31ac5cf0ff7524987cfcce0a10c43156eb3ee8d92d92bf22", - "sha256:4891d4c934f88b6c29b56395dfc7014ebf7e10b9e22ffd9877784e16c6b2064f", - "sha256:4c616b796358a70b1f675a24628e4823b67d9e376df2703e893da58247458956", - "sha256:5198633137780d78b86bb54dafaaa9baea698b4f059456cd4554ab7009619221", - "sha256:5a2937f528c84e64be20cb80e70cea76a6dfb74b628a04dab130679d4454395c", - "sha256:5da9032dac184b2ae2da4bce423edff7db34bfd936ebd7d4207ea45840f03905", - "sha256:5e736815b30f7e3c9044ec06a98ee59e217a833227e10eb157f44071faddd7c5", - "sha256:63ef3d371ea0b7239ace284cab9cd00d9c92b73119a7c274b437adb09bda35e6", - "sha256:70b9a20a03576c6b7022926f614ac5a6b0914486825eac89196adf3267c6489d", - "sha256:76a0fc023910d8a8ab64daed8d31d608446d2d77c6474b616b34537aa7b79c7f", - "sha256:7951af8f2998045c656ba8062e8edf5e83fd82b912534ab1de1345de08a41d2b", - "sha256:7a34a199d89d82d1897fd4a47820eb50947eec9cda5fd73f4578ff692a912f89", - "sha256:7bab596678d29ad969a524823c4e828929a90c09e91cc438e0ad79b37ce41166", - "sha256:7ea3e63e61b4b0beeb08508458bdff2daca7a321468d3c4b320a758a2f554d31", - "sha256:80acafe396ab689a326ab0d80f8cc61dec0dd2c5dca5b4b3825e7b1e0132c101", - "sha256:82720ab0cf5bb436bbd97a319ac529aee06077ff7e61cab57cee04a596c4f9b4", - "sha256:83cc275cf6dcb1a248e1876cdefd3f9b5f01063854acdfd687ec360cd3c9712a", - "sha256:85e39198f78e2f7e054d296395f6c96f5e02892337746ef5b6a1bf3ed5910142", - "sha256:8769806ea0b45d7bf75cad253fba9ac6700b7050ebb19337ff6b4e9060f963fa", - "sha256:8bdb6c911dae5fbf110fe4f5cba578437526334df381b3554b6ab7f626e5eeca", - "sha256:8f4b0042d8388ac85b8330b65406c84c3229420a05068445c13ca28cc222f1f7", - "sha256:90fe73a1f0321265126cbba13677dcceb367d926c7a65807bd80916af4c17047", - "sha256:915e22c93e7b7b636240c5a79da5f6e4e84988d699656c8e27f2ac4c95b8dcc0", - "sha256:9274ba499e7dfb8a651ee876d80386b481336d3868cba29af839370514e4dce0", - "sha256:9d62c583b5110e6a5cf5169ab616aa4ec71f2c0c30f833306f9e378cf51b6c86", - "sha256:9ef82157bbcecd75d6296d5d8b2d792242afcd064eb1ac573f8847b52e58f677", - "sha256:a19e4074bc98793458b4b3ba35a9a1d132179345e60e152a1bb48c538ab863c4", - "sha256:a347d7b43cb609e780ff8d7b3107d4bcb5b6fd09c2702aa7bdf52f15ed09fa09", - "sha256:b4fb306c96e04c5863d52ba8d65137917a3d999059c11e659eba7b75a69167bd", - "sha256:b6df858e37c321cefbf27fe7ece30a950bcc3a75618a804a0dcef7ed9dd9c92d", - "sha256:b8e59650292aa3a8ea78073fc84184538783966528e442a1b9ed653aa282edcf", - "sha256:bcb9a60ed2101af2af450318cd89c6b8313e9f8df4e8fb12b657b2e97227cf08", - "sha256:c3ba725cf5cf87d2d2d988d39c6a2a8b6fc983d78ff71bc728b0be54c869c884", - "sha256:ca1706e8b8b565e934c142db6a9592e6401dc430e4b067a97781a997070c5378", - "sha256:cd3e7aae977c723cc1dbb82f97babdb5e5fbce109630fbabb2ea5053523c89d3", - "sha256:cf334ce1d2fadd1bf3e5e9bf15e58e0c42b26eb6590875ce65bd877d917a58aa", - "sha256:d8692948cada6ee21f33db5e23460f71c8010d6dfcfe293c9b96737600a7df78", - "sha256:e5205ec0dfab1887dd383597012199f5175035e782cdb013c542187d280ca443", - "sha256:e7e7f44e091b93eb39db88bb0cb765db09b7a7f64aea2f35e7d86cbf47046c65", - "sha256:e94b7b31aa0d65f5b7c72dd8f8227dbd3e30354b99e7a9af096d967a77f2a580", - "sha256:f26fb3e8e3e2ee405c947ff44a3e384e8fa1843bc35830fe6f3d9a95a1147b6e", - "sha256:f738fee63eb263530efd4d2e9c76316c1f47b3bbf38c1bf45ae9625feed0395e", - "sha256:f9e01239abea2f52a429fe9d95c96df95f078f0172489d691b4a848ace54a476" + "sha256:06ad5543217e0e46fd7ab7ea45d506c76f878b87b1b4e369006bdb01acc05a83", + "sha256:0a73160e823151f33cdc05fe2cea557c5ef12fdf276ce29bb4f1c571c8368a60", + "sha256:1234dc92d011d3554d929b6cf058ac4a24d188d97be5e04355f1b9223e98bbe9", + "sha256:1d0dc4310da8b5f6415949bd5ef937e60aeb0eb6b16f95041b5e43e6200821fb", + "sha256:2a11b4b1a8415f105d989876a19b173f6cdc89ca13855ccc67c18efbd7cbd1f8", + "sha256:2e2ecd1d349e62e3960695214f40939bbfdcaeaaa62ccc638f8e651cf0970e5f", + "sha256:3a2ce5ea4f71681623f04e2b7dadede3c7435dfb5e5e2d1d0ec25b35530e277b", + "sha256:3e892621434392199efb54e69edfff9f699f6cc36dd9553c5bf796058b14b20d", + "sha256:3fb205ab52a2e30354640780ce4587157a9563a68c9beaf52153e1cea9aa0921", + "sha256:4689270c35d4bb3102e103ac43c3f0b76b169760aff8bcf2d401a3e0e58cdb7f", + "sha256:49f8ad582da6e8d2cf663c4ba5bf9f83cc052570a3a767487fec6af839b0e777", + "sha256:4bd176f528a8151a6efc5359b853ba3cc0e82d4cd1fab9c1300c5d957dc8f48c", + "sha256:4cf7837c3b11a2dfb589f8530b3cff2bd0307ace4c301e8997e95c7468c1378e", + "sha256:4fd72fab7bddce46c6826994ce1e7de145ae1e9e106ebb8eb9ce1393ca01444d", + "sha256:5148bab4d71f58948c7c39d12b14a9005b6ab35a0bdf317a8ade9a9e4d9d0bd5", + "sha256:5869e8e130e99687d9e4be835116c4ebd83ca92e52e55810962446d841aba8de", + "sha256:602a8001bdf60e1a7d544be29c82560a7b49319a0b31d62586548835bbe2c862", + "sha256:61804231099214e2f84998316f3238c4c2c4aaec302df12b21a64d72e2a135c7", + "sha256:666c6fdcaac1f13eb982b649e1c311c08d7097cbda24f32612dae43648d8db8d", + "sha256:674eb520f02422546c40401f4efaf8207b5e29e420c17051cddf6c02783ff5ca", + "sha256:7ec960b1b942ee3c69323b8721df2a3ce28ff40e7ca47873ae35bfafeb4555ca", + "sha256:7f433be3b3f4c66016d5a20e5b4444ef833a1f802ced13a2d852c637f69729c1", + "sha256:7f8fb7f5ecf4f6355683ac6881fd64b5bb2b8a60e3ccde6ff799e48791d8f864", + "sha256:81a3a3a72c9811b56adf8bcc829b010163bb2fc308877e50e9910c9357e78521", + "sha256:858379cbb08d84fe7583231077d9a36a1a20eb72f8c9076a45df8b083724ad1d", + "sha256:8b9ba0ccd5a7f4219e67fbbe25e6b4a46ceef783c42af7dbc1da548eb28b6531", + "sha256:92af0d00091e744587221e79f68d617b432425a7e59328ca4c496f774a356071", + "sha256:9ebbdbd6a046c304b1845e96fbcc5559cd296b4dfd3ad2509e33c4d9ce07d6a1", + "sha256:9edd2856611e5050004f4722922b7b1cd6268da34102667bd49d2a2b18bafb81", + "sha256:a353bf1f565ed27ba71a419b2cd3db9d6151da426b61b289b6ba1422a702e643", + "sha256:b5b7d4a44cc0e6ff98da5d56cde794385bdd212a86563ac321ca64d7f80c80d1", + "sha256:b90f340cb6397ec7a854157fac03f0c82b744abdd1c0941a024c3c29d1340aff", + "sha256:c18a4da2f50050a03d1da5317388ef84a16013302a5281d6f64e4a3f406aabc4", + "sha256:c338ed69ad0b8f8f8920c13f529889fe0771abbb46550013e3c3d01e5174deef", + "sha256:c5a02360e73e7208a872bf65a7554c9f15df5fe063dc047f79738998b0506a14", + "sha256:c62b6fa2961a1dcc51ebe88771be5319a93fd89bd247c9ddf732bc250507bc2b", + "sha256:c812312847867b6335cfb264772f2a7e85b3b502d3a6b0586aa35e1858528ab1", + "sha256:c943b35ecdf7123b2d81d225397efddf0bce2e81db2f3ae633ead38e85cd5ade", + "sha256:ce0a29c28dfb8eccd0f16219360530bc3cfdf6bf70ca384dacd36e6c650ef8e8", + "sha256:cf80b550092cc480a0cbd0750e8189247ff45457e5a023305f7ef1bcec811616", + "sha256:cff7570d492bcf4b64cc862a6e2fb77edd5e5748ad715f487628f102815165e9", + "sha256:d2c1e559d96a7f94a4f581e2a32d6d610df5840881a8cba8f25e446f4d792df3", + "sha256:deeb3922a7a804755bbe6b5be9b312e746137a03600f488290318936c1a2d4dc", + "sha256:e28a50b5be854e18d54f75ef1bb13e1abf4bc650ab9d635e4258c58e71eb6ad5", + "sha256:e99c625b8c95d7741fe057585176b1b8783d46ed4b8932cf98ee145c4facf499", + "sha256:ec6f18f96b47299c11203edfbdc34e1b69085070d9a3d1f302810cc23ad36bf3", + "sha256:ed8bc367f725dfc5cabeed1ae079d00369900231fbb5a5280cf0736c30e2adf7", + "sha256:ee5926746232f627a3be1cc175b2cfad24d0170d520361f4ce3fa2fd83f09e1d", + "sha256:f295efcd47b6124b01255d1491f9e46f17ef40d3d7eabf7364099e463fb45f0f", + "sha256:fb0b361d73f6b8eeceba47cd37070b5e6c9de5beaeaa63a1cb35c7e1a73ef088" ], "index": "pypi", - "version": "==3.9.7" + "version": "==3.9.10" }, "pillow": { "hashes": [ - "sha256:0462b1496505a3462d0f35dc1c4d7b54069747d65d00ef48e736acda2c8cbdff", - "sha256:186f7e04248103482ea6354af6d5bcedb62941ee08f7f788a1c7707bc720c66f", - "sha256:19e9adb3f22d4c416e7cd79b01375b17159d6990003633ff1d8377e21b7f1b21", - "sha256:28444cb6ad49726127d6b340217f0627abc8732f1194fd5352dec5e6a0105635", - "sha256:2872f2d7846cf39b3dbff64bc1104cc48c76145854256451d33c5faa55c04d1a", - "sha256:2cc6b86ece42a11f16f55fe8903595eff2b25e0358dec635d0a701ac9586588f", - "sha256:2d7e91b4379f7a76b31c2dda84ab9e20c6220488e50f7822e59dac36b0cd92b1", - "sha256:2fa6dd2661838c66f1a5473f3b49ab610c98a128fc08afbe81b91a1f0bf8c51d", - "sha256:32bec7423cdf25c9038fef614a853c9d25c07590e1a870ed471f47fb80b244db", - "sha256:3855447d98cced8670aaa63683808df905e956f00348732448b5a6df67ee5849", - "sha256:3a04359f308ebee571a3127fdb1bd01f88ba6f6fb6d087f8dd2e0d9bff43f2a7", - "sha256:3a0d3e54ab1df9df51b914b2233cf779a5a10dfd1ce339d0421748232cea9876", - "sha256:44e7e4587392953e5e251190a964675f61e4dae88d1e6edbe9f36d6243547ff3", - "sha256:459307cacdd4138edee3875bbe22a2492519e060660eaf378ba3b405d1c66317", - "sha256:4ce90f8a24e1c15465048959f1e94309dfef93af272633e8f37361b824532e91", - "sha256:50bd5f1ebafe9362ad622072a1d2f5850ecfa44303531ff14353a4059113b12d", - "sha256:522ff4ac3aaf839242c6f4e5b406634bfea002469656ae8358644fc6c4856a3b", - "sha256:552912dbca585b74d75279a7570dd29fa43b6d93594abb494ebb31ac19ace6bd", - "sha256:5d6c9049c6274c1bb565021367431ad04481ebb54872edecfcd6088d27edd6ed", - "sha256:697a06bdcedd473b35e50a7e7506b1d8ceb832dc238a336bd6f4f5aa91a4b500", - "sha256:71671503e3015da1b50bd18951e2f9daf5b6ffe36d16f1eb2c45711a301521a7", - "sha256:723bd25051454cea9990203405fa6b74e043ea76d4968166dfd2569b0210886a", - "sha256:764d2c0daf9c4d40ad12fbc0abd5da3af7f8aa11daf87e4fa1b834000f4b6b0a", - "sha256:787bb0169d2385a798888e1122c980c6eff26bf941a8ea79747d35d8f9210ca0", - "sha256:7f771e7219ff04b79e231d099c0a28ed83aa82af91fd5fa9fdb28f5b8d5addaf", - "sha256:847e8d1017c741c735d3cd1883fa7b03ded4f825a6e5fcb9378fd813edee995f", - "sha256:84efb46e8d881bb06b35d1d541aa87f574b58e87f781cbba8d200daa835b42e1", - "sha256:898f1d306298ff40dc1b9ca24824f0488f6f039bc0e25cfb549d3195ffa17088", - "sha256:8b451d6ead6e3500b6ce5c7916a43d8d8d25ad74b9102a629baccc0808c54971", - "sha256:8f06be50669087250f319b706decf69ca71fdecd829091a37cc89398ca4dc17a", - "sha256:92a23b0431941a33242b1f0ce6c88a952e09feeea9af4e8be48236a68ffe2205", - "sha256:93139acd8109edcdeffd85e3af8ae7d88b258b3a1e13a038f542b79b6d255c54", - "sha256:98533fd7fa764e5f85eebe56c8e4094db912ccbe6fbf3a58778d543cadd0db08", - "sha256:9f665d1e6474af9f9da5e86c2a3a2d2d6204e04d5af9c06b9d42afa6ebde3f21", - "sha256:b059ac2c4c7a97daafa7dc850b43b2d3667def858a4f112d1aa082e5c3d6cf7d", - "sha256:b1be1c872b9b5fcc229adeadbeb51422a9633abd847c0ff87dc4ef9bb184ae08", - "sha256:b7cf63d2c6928b51d35dfdbda6f2c1fddbe51a6bc4a9d4ee6ea0e11670dd981e", - "sha256:bc2e3069569ea9dbe88d6b8ea38f439a6aad8f6e7a6283a38edf61ddefb3a9bf", - "sha256:bcf1207e2f2385a576832af02702de104be71301c2696d0012b1b93fe34aaa5b", - "sha256:ca26ba5767888c84bf5a0c1a32f069e8204ce8c21d00a49c90dabeba00ce0145", - "sha256:cbe68deb8580462ca0d9eb56a81912f59eb4542e1ef8f987405e35a0179f4ea2", - "sha256:d6caf3cd38449ec3cd8a68b375e0c6fe4b6fd04edb6c9766b55ef84a6e8ddf2d", - "sha256:d72967b06be9300fed5cfbc8b5bafceec48bf7cdc7dab66b1d2549035287191d", - "sha256:d889b53ae2f030f756e61a7bff13684dcd77e9af8b10c6048fb2c559d6ed6eaf", - "sha256:de596695a75496deb3b499c8c4f8e60376e0516e1a774e7bc046f0f48cd620ad", - "sha256:e6a90167bcca1216606223a05e2cf991bb25b14695c518bc65639463d7db722d", - "sha256:ed2d9c0704f2dc4fa980b99d565c0c9a543fe5101c25b3d60488b8ba80f0cce1", - "sha256:ee7810cf7c83fa227ba9125de6084e5e8b08c59038a7b2c9045ef4dde61663b4", - "sha256:f0b4b06da13275bc02adfeb82643c4a6385bd08d26f03068c2796f60d125f6f2", - "sha256:f11c9102c56ffb9ca87134bd025a43d2aba3f1155f508eff88f694b33a9c6d19", - "sha256:f5bb289bb835f9fe1a1e9300d011eef4d69661bb9b34d5e196e5e82c4cb09b37", - "sha256:f6d3d4c905e26354e8f9d82548475c46d8e0889538cb0657aa9c6f0872a37aa4", - "sha256:fcb59711009b0168d6ee0bd8fb5eb259c4ab1717b2f538bbf36bacf207ef7a68", - "sha256:fd2a5403a75b54661182b75ec6132437a181209b901446ee5724b589af8edef1" + "sha256:00f438bb841382b15d7deb9a05cc946ee0f2c352653c7aa659e75e592f6fa17d", + "sha256:0248f86b3ea061e67817c47ecbe82c23f9dd5d5226200eb9090b3873d3ca32de", + "sha256:04f6f6149f266a100374ca3cc368b67fb27c4af9f1cc8cb6306d849dcdf12616", + "sha256:062a1610e3bc258bff2328ec43f34244fcec972ee0717200cb1425214fe5b839", + "sha256:0a026c188be3b443916179f5d04548092e253beb0c3e2ee0a4e2cdad72f66099", + "sha256:0f7c276c05a9767e877a0b4c5050c8bee6a6d960d7f0c11ebda6b99746068c2a", + "sha256:1a8413794b4ad9719346cd9306118450b7b00d9a15846451549314a58ac42219", + "sha256:1ab05f3db77e98f93964697c8efc49c7954b08dd61cff526b7f2531a22410106", + "sha256:1c3ac5423c8c1da5928aa12c6e258921956757d976405e9467c5f39d1d577a4b", + "sha256:1c41d960babf951e01a49c9746f92c5a7e0d939d1652d7ba30f6b3090f27e412", + "sha256:1fafabe50a6977ac70dfe829b2d5735fd54e190ab55259ec8aea4aaea412fa0b", + "sha256:1fb29c07478e6c06a46b867e43b0bcdb241b44cc52be9bc25ce5944eed4648e7", + "sha256:24fadc71218ad2b8ffe437b54876c9382b4a29e030a05a9879f615091f42ffc2", + "sha256:2cdc65a46e74514ce742c2013cd4a2d12e8553e3a2563c64879f7c7e4d28bce7", + "sha256:2ef6721c97894a7aa77723740a09547197533146fba8355e86d6d9a4a1056b14", + "sha256:3b834f4b16173e5b92ab6566f0473bfb09f939ba14b23b8da1f54fa63e4b623f", + "sha256:3d929a19f5469b3f4df33a3df2983db070ebb2088a1e145e18facbc28cae5b27", + "sha256:41f67248d92a5e0a2076d3517d8d4b1e41a97e2df10eb8f93106c89107f38b57", + "sha256:47e5bf85b80abc03be7455c95b6d6e4896a62f6541c1f2ce77a7d2bb832af262", + "sha256:4d0152565c6aa6ebbfb1e5d8624140a440f2b99bf7afaafbdbf6430426497f28", + "sha256:50d08cd0a2ecd2a8657bd3d82c71efd5a58edb04d9308185d66c3a5a5bed9610", + "sha256:61f1a9d247317fa08a308daaa8ee7b3f760ab1809ca2da14ecc88ae4257d6172", + "sha256:6932a7652464746fcb484f7fc3618e6503d2066d853f68a4bd97193a3996e273", + "sha256:7a7e3daa202beb61821c06d2517428e8e7c1aab08943e92ec9e5755c2fc9ba5e", + "sha256:7dbaa3c7de82ef37e7708521be41db5565004258ca76945ad74a8e998c30af8d", + "sha256:7df5608bc38bd37ef585ae9c38c9cd46d7c81498f086915b0f97255ea60c2818", + "sha256:806abdd8249ba3953c33742506fe414880bad78ac25cc9a9b1c6ae97bedd573f", + "sha256:883f216eac8712b83a63f41b76ddfb7b2afab1b74abbb413c5df6680f071a6b9", + "sha256:912e3812a1dbbc834da2b32299b124b5ddcb664ed354916fd1ed6f193f0e2d01", + "sha256:937bdc5a7f5343d1c97dc98149a0be7eb9704e937fe3dc7140e229ae4fc572a7", + "sha256:9882a7451c680c12f232a422730f986a1fcd808da0fd428f08b671237237d651", + "sha256:9a92109192b360634a4489c0c756364c0c3a2992906752165ecb50544c251312", + "sha256:9d7bc666bd8c5a4225e7ac71f2f9d12466ec555e89092728ea0f5c0c2422ea80", + "sha256:a5f63b5a68daedc54c7c3464508d8c12075e56dcfbd42f8c1bf40169061ae666", + "sha256:a646e48de237d860c36e0db37ecaecaa3619e6f3e9d5319e527ccbc8151df061", + "sha256:a89b8312d51715b510a4fe9fc13686283f376cfd5abca8cd1c65e4c76e21081b", + "sha256:a92386125e9ee90381c3369f57a2a50fa9e6aa8b1cf1d9c4b200d41a7dd8e992", + "sha256:ae88931f93214777c7a3aa0a8f92a683f83ecde27f65a45f95f22d289a69e593", + "sha256:afc8eef765d948543a4775f00b7b8c079b3321d6b675dde0d02afa2ee23000b4", + "sha256:b0eb01ca85b2361b09480784a7931fc648ed8b7836f01fb9241141b968feb1db", + "sha256:b1c25762197144e211efb5f4e8ad656f36c8d214d390585d1d21281f46d556ba", + "sha256:b4005fee46ed9be0b8fb42be0c20e79411533d1fd58edabebc0dd24626882cfd", + "sha256:b920e4d028f6442bea9a75b7491c063f0b9a3972520731ed26c83e254302eb1e", + "sha256:baada14941c83079bf84c037e2d8b7506ce201e92e3d2fa0d1303507a8538212", + "sha256:bb40c011447712d2e19cc261c82655f75f32cb724788df315ed992a4d65696bb", + "sha256:c0949b55eb607898e28eaccb525ab104b2d86542a85c74baf3a6dc24002edec2", + "sha256:c9aeea7b63edb7884b031a35305629a7593272b54f429a9869a4f63a1bf04c34", + "sha256:cfe96560c6ce2f4c07d6647af2d0f3c54cc33289894ebd88cfbb3bcd5391e256", + "sha256:d27b5997bdd2eb9fb199982bb7eb6164db0426904020dc38c10203187ae2ff2f", + "sha256:d921bc90b1defa55c9917ca6b6b71430e4286fc9e44c55ead78ca1a9f9eba5f2", + "sha256:e6bf8de6c36ed96c86ea3b6e1d5273c53f46ef518a062464cd7ef5dd2cf92e38", + "sha256:eaed6977fa73408b7b8a24e8b14e59e1668cfc0f4c40193ea7ced8e210adf996", + "sha256:fa1d323703cfdac2036af05191b969b910d8f115cf53093125e4058f62012c9a", + "sha256:fe1e26e1ffc38be097f0ba1d0d07fcade2bcfd1d023cda5b29935ae8052bd793" ], "index": "pypi", - "version": "==10.0.1" + "version": "==10.1.0" }, "protobuf": { "hashes": [ - "sha256:067f750169bc644da2e1ef18c785e85071b7c296f14ac53e0900e605da588719", - "sha256:12e9ad2ec079b833176d2921be2cb24281fa591f0b119b208b788adc48c2561d", - "sha256:1b182c7181a2891e8f7f3a1b5242e4ec54d1f42582485a896e4de81aa17540c2", - "sha256:20651f11b6adc70c0f29efbe8f4a94a74caf61b6200472a9aea6e19898f9fcf4", - "sha256:2da777d34b4f4f7613cdf85c70eb9a90b1fbef9d36ae4a0ccfe014b0b07906f1", - "sha256:3d42e9e4796a811478c783ef63dc85b5a104b44aaaca85d4864d5b886e4b05e3", - "sha256:6e514e8af0045be2b56e56ae1bb14f43ce7ffa0f68b1c793670ccbe2c4fc7d2b", - "sha256:b0271a701e6782880d65a308ba42bc43874dabd1a0a0f41f72d2dac3b57f8e76", - "sha256:ba53c2f04798a326774f0e53b9c759eaef4f6a568ea7072ec6629851c8435959", - "sha256:e29d79c913f17a60cf17c626f1041e5288e9885c8579832580209de8b75f2a52", - "sha256:f631bb982c5478e0c1c70eab383af74a84be66945ebf5dd6b06fc90079668d0b", - "sha256:f6ccbcf027761a2978c1406070c3788f6de4a4b2cc20800cc03d52df716ad675", - "sha256:f6f8dc65625dadaad0c8545319c2e2f0424fede988368893ca3844261342c11a" + "sha256:0bf384e75b92c42830c0a679b0cd4d6e2b36ae0cf3dbb1e1dfdda48a244f4bcd", + "sha256:0f881b589ff449bf0b931a711926e9ddaad3b35089cc039ce1af50b21a4ae8cb", + "sha256:1484f9e692091450e7edf418c939e15bfc8fc68856e36ce399aed6889dae8bb0", + "sha256:193f50a6ab78a970c9b4f148e7c750cfde64f59815e86f686c22e26b4fe01ce7", + "sha256:3497c1af9f2526962f09329fd61a36566305e6c72da2590ae0d7d1322818843b", + "sha256:57d65074b4f5baa4ab5da1605c02be90ac20c8b40fb137d6a8df9f416b0d0ce2", + "sha256:8bdbeaddaac52d15c6dce38c71b03038ef7772b977847eb6d374fc86636fa510", + "sha256:a19731d5e83ae4737bb2a089605e636077ac001d18781b3cf489b9546c7c80d6", + "sha256:abc0525ae2689a8000837729eef7883b9391cd6aa7950249dcf5a4ede230d5dd", + "sha256:becc576b7e6b553d22cbdf418686ee4daa443d7217999125c045ad56322dda10", + "sha256:ca37bf6a6d0046272c152eea90d2e4ef34593aaa32e8873fc14c16440f22d4b7" ], - "markers": "python_version >= '3.7'", - "version": "==4.24.3" + "markers": "python_version >= '3.8'", + "version": "==4.25.1" }, "psutil": { "hashes": [ - "sha256:104a5cc0e31baa2bcf67900be36acde157756b9c44017b86b2c049f11957887d", - "sha256:3c6f686f4225553615612f6d9bc21f1c0e305f75d7d8454f9b46e901778e7217", - "sha256:4aef137f3345082a3d3232187aeb4ac4ef959ba3d7c10c33dd73763fbc063da4", - "sha256:5410638e4df39c54d957fc51ce03048acd8e6d60abc0f5107af51e5fb566eb3c", - "sha256:5b9b8cb93f507e8dbaf22af6a2fd0ccbe8244bf30b1baad6b3954e935157ae3f", - "sha256:7a7dd9997128a0d928ed4fb2c2d57e5102bb6089027939f3b722f3a210f9a8da", - "sha256:89518112647f1276b03ca97b65cc7f64ca587b1eb0278383017c2a0dcc26cbe4", - "sha256:8c5f7c5a052d1d567db4ddd231a9d27a74e8e4a9c3f44b1032762bd7b9fdcd42", - "sha256:ab8ed1a1d77c95453db1ae00a3f9c50227ebd955437bcf2a574ba8adbf6a74d5", - "sha256:acf2aef9391710afded549ff602b5887d7a2349831ae4c26be7c807c0a39fac4", - "sha256:b258c0c1c9d145a1d5ceffab1134441c4c5113b2417fafff7315a917a026c3c9", - "sha256:be8929ce4313f9f8146caad4272f6abb8bf99fc6cf59344a3167ecd74f4f203f", - "sha256:c607bb3b57dc779d55e1554846352b4e358c10fff3abf3514a7a6601beebdb30", - "sha256:ea8518d152174e1249c4f2a1c89e3e6065941df2fa13a1ab45327716a23c2b48" + "sha256:032f4f2c909818c86cea4fe2cc407f1c0f0cde8e6c6d702b28b8ce0c0d143340", + "sha256:0bd41bf2d1463dfa535942b2a8f0e958acf6607ac0be52265ab31f7923bcd5e6", + "sha256:1132704b876e58d277168cd729d64750633d5ff0183acf5b3c986b8466cd0284", + "sha256:1d4bc4a0148fdd7fd8f38e0498639ae128e64538faa507df25a20f8f7fb2341c", + "sha256:3c4747a3e2ead1589e647e64aad601981f01b68f9398ddf94d01e3dc0d1e57c7", + "sha256:3f02134e82cfb5d089fddf20bb2e03fd5cd52395321d1c8458a9e58500ff417c", + "sha256:44969859757f4d8f2a9bd5b76eba8c3099a2c8cf3992ff62144061e39ba8568e", + "sha256:4c03362e280d06bbbfcd52f29acd79c733e0af33d707c54255d21029b8b32ba6", + "sha256:5794944462509e49d4d458f4dbfb92c47539e7d8d15c796f141f474010084056", + "sha256:b27f8fdb190c8c03914f908a4555159327d7481dac2f01008d483137ef3311a9", + "sha256:c727ca5a9b2dd5193b8644b9f0c883d54f1248310023b5ad3e92036c5e2ada68", + "sha256:e469990e28f1ad738f65a42dcfc17adaed9d0f325d55047593cb9033a0ab63df", + "sha256:ea36cc62e69a13ec52b2f625c27527f6e4479bca2b340b7a452af55b34fcbe2e", + "sha256:f37f87e4d73b79e6c5e749440c3113b81d1ee7d26f21c19c47371ddea834f414", + "sha256:fe361f743cb3389b8efda21980d93eb55c1f1e3898269bc9a2a1d0bb7b1f6508", + "sha256:fe8b7f07948f1304497ce4f4684881250cd859b16d06a1dc4d7941eeb6233bfe" ], "index": "pypi", - "version": "==5.9.5" + "version": "==5.9.7" }, "pyclipper": { "hashes": [ @@ -866,210 +857,276 @@ }, "pydantic": { "hashes": [ - "sha256:1607cc106602284cd4a00882986570472f193fde9cb1259bceeaedb26aa79a6d", - "sha256:45b5e446c6dfaad9444819a293b921a40e1db1aa61ea08aede0522529ce90e81" + "sha256:b3ef57c62535b0941697cce638c08900d87fcb67e29cfa99e8a68f747f393f7a", + "sha256:d0caf5954bee831b6bfe7e338c32b9e30c85dfe080c843680783ac2b631673b4" ], "markers": "python_version >= '3.7'", - "version": "==2.3.0" + "version": "==2.5.3" }, "pydantic-core": { "hashes": [ - "sha256:002d0ea50e17ed982c2d65b480bd975fc41086a5a2f9c924ef8fc54419d1dea3", - "sha256:02e1c385095efbd997311d85c6021d32369675c09bcbfff3b69d84e59dc103f6", - "sha256:046af9cfb5384f3684eeb3f58a48698ddab8dd870b4b3f67f825353a14441418", - "sha256:04fe5c0a43dec39aedba0ec9579001061d4653a9b53a1366b113aca4a3c05ca7", - "sha256:07a1aec07333bf5adebd8264047d3dc518563d92aca6f2f5b36f505132399efc", - "sha256:1480fa4682e8202b560dcdc9eeec1005f62a15742b813c88cdc01d44e85308e5", - "sha256:1508f37ba9e3ddc0189e6ff4e2228bd2d3c3a4641cbe8c07177162f76ed696c7", - "sha256:171a4718860790f66d6c2eda1d95dd1edf64f864d2e9f9115840840cf5b5713f", - "sha256:19e20f8baedd7d987bd3f8005c146e6bcbda7cdeefc36fad50c66adb2dd2da48", - "sha256:1a0ddaa723c48af27d19f27f1c73bdc615c73686d763388c8683fe34ae777bad", - "sha256:1aa712ba150d5105814e53cb141412217146fedc22621e9acff9236d77d2a5ef", - "sha256:1ac1750df1b4339b543531ce793b8fd5c16660a95d13aecaab26b44ce11775e9", - "sha256:1c721bfc575d57305dd922e6a40a8fe3f762905851d694245807a351ad255c58", - "sha256:1ce8c84051fa292a5dc54018a40e2a1926fd17980a9422c973e3ebea017aa8da", - "sha256:1fa1f6312fb84e8c281f32b39affe81984ccd484da6e9d65b3d18c202c666149", - "sha256:22134a4453bd59b7d1e895c455fe277af9d9d9fbbcb9dc3f4a97b8693e7e2c9b", - "sha256:23470a23614c701b37252618e7851e595060a96a23016f9a084f3f92f5ed5881", - "sha256:240a015102a0c0cc8114f1cba6444499a8a4d0333e178bc504a5c2196defd456", - "sha256:252851b38bad3bfda47b104ffd077d4f9604a10cb06fe09d020016a25107bf98", - "sha256:2a20c533cb80466c1d42a43a4521669ccad7cf2967830ac62c2c2f9cece63e7e", - "sha256:2dd50d6a1aef0426a1d0199190c6c43ec89812b1f409e7fe44cb0fbf6dfa733c", - "sha256:340e96c08de1069f3d022a85c2a8c63529fd88709468373b418f4cf2c949fb0e", - "sha256:3796a6152c545339d3b1652183e786df648ecdf7c4f9347e1d30e6750907f5bb", - "sha256:37a822f630712817b6ecc09ccc378192ef5ff12e2c9bae97eb5968a6cdf3b862", - "sha256:3a750a83b2728299ca12e003d73d1264ad0440f60f4fc9cee54acc489249b728", - "sha256:3c8945a105f1589ce8a693753b908815e0748f6279959a4530f6742e1994dcb6", - "sha256:3ccc13afee44b9006a73d2046068d4df96dc5b333bf3509d9a06d1b42db6d8bf", - "sha256:3f90e5e3afb11268628c89f378f7a1ea3f2fe502a28af4192e30a6cdea1e7d5e", - "sha256:4292ca56751aebbe63a84bbfc3b5717abb09b14d4b4442cc43fd7c49a1529efd", - "sha256:430ddd965ffd068dd70ef4e4d74f2c489c3a313adc28e829dd7262cc0d2dd1e8", - "sha256:439a0de139556745ae53f9cc9668c6c2053444af940d3ef3ecad95b079bc9987", - "sha256:44b4f937b992394a2e81a5c5ce716f3dcc1237281e81b80c748b2da6dd5cf29a", - "sha256:48c1ed8b02ffea4d5c9c220eda27af02b8149fe58526359b3c07eb391cb353a2", - "sha256:4ef724a059396751aef71e847178d66ad7fc3fc969a1a40c29f5aac1aa5f8784", - "sha256:50555ba3cb58f9861b7a48c493636b996a617db1a72c18da4d7f16d7b1b9952b", - "sha256:522a9c4a4d1924facce7270c84b5134c5cabcb01513213662a2e89cf28c1d309", - "sha256:5493a7027bfc6b108e17c3383959485087d5942e87eb62bbac69829eae9bc1f7", - "sha256:56ea80269077003eaa59723bac1d8bacd2cd15ae30456f2890811efc1e3d4413", - "sha256:5a2a3c9ef904dcdadb550eedf3291ec3f229431b0084666e2c2aa8ff99a103a2", - "sha256:5cfde4fab34dd1e3a3f7f3db38182ab6c95e4ea91cf322242ee0be5c2f7e3d2f", - "sha256:5e4a2cf8c4543f37f5dc881de6c190de08096c53986381daebb56a355be5dfe6", - "sha256:5e9c068f36b9f396399d43bfb6defd4cc99c36215f6ff33ac8b9c14ba15bdf6b", - "sha256:5ed7ceca6aba5331ece96c0e328cd52f0dcf942b8895a1ed2642de50800b79d3", - "sha256:5fa159b902d22b283b680ef52b532b29554ea2a7fc39bf354064751369e9dbd7", - "sha256:615a31b1629e12445c0e9fc8339b41aaa6cc60bd53bf802d5fe3d2c0cda2ae8d", - "sha256:621afe25cc2b3c4ba05fff53525156d5100eb35c6e5a7cf31d66cc9e1963e378", - "sha256:6656a0ae383d8cd7cc94e91de4e526407b3726049ce8d7939049cbfa426518c8", - "sha256:672174480a85386dd2e681cadd7d951471ad0bb028ed744c895f11f9d51b9ebe", - "sha256:692b4ff5c4e828a38716cfa92667661a39886e71136c97b7dac26edef18767f7", - "sha256:6bcc1ad776fffe25ea5c187a028991c031a00ff92d012ca1cc4714087e575973", - "sha256:6bf7d610ac8f0065a286002a23bcce241ea8248c71988bda538edcc90e0c39ad", - "sha256:75c0ebbebae71ed1e385f7dfd9b74c1cff09fed24a6df43d326dd7f12339ec34", - "sha256:788be9844a6e5c4612b74512a76b2153f1877cd845410d756841f6c3420230eb", - "sha256:7dc2ce039c7290b4ef64334ec7e6ca6494de6eecc81e21cb4f73b9b39991408c", - "sha256:813aab5bfb19c98ae370952b6f7190f1e28e565909bfc219a0909db168783465", - "sha256:8421cf496e746cf8d6b677502ed9a0d1e4e956586cd8b221e1312e0841c002d5", - "sha256:84e87c16f582f5c753b7f39a71bd6647255512191be2d2dbf49458c4ef024588", - "sha256:84f8bb34fe76c68c9d96b77c60cef093f5e660ef8e43a6cbfcd991017d375950", - "sha256:85cc4d105747d2aa3c5cf3e37dac50141bff779545ba59a095f4a96b0a460e70", - "sha256:883daa467865e5766931e07eb20f3e8152324f0adf52658f4d302242c12e2c32", - "sha256:8b2b1bfed698fa410ab81982f681f5b1996d3d994ae8073286515ac4d165c2e7", - "sha256:8ecbac050856eb6c3046dea655b39216597e373aa8e50e134c0e202f9c47efec", - "sha256:930bfe73e665ebce3f0da2c6d64455098aaa67e1a00323c74dc752627879fc67", - "sha256:9616567800bdc83ce136e5847d41008a1d602213d024207b0ff6cab6753fe645", - "sha256:9680dd23055dd874173a3a63a44e7f5a13885a4cfd7e84814be71be24fba83db", - "sha256:99faba727727b2e59129c59542284efebbddade4f0ae6a29c8b8d3e1f437beb7", - "sha256:9a718d56c4d55efcfc63f680f207c9f19c8376e5a8a67773535e6f7e80e93170", - "sha256:9b33bf9658cb29ac1a517c11e865112316d09687d767d7a0e4a63d5c640d1b17", - "sha256:9e8b374ef41ad5c461efb7a140ce4730661aadf85958b5c6a3e9cf4e040ff4bb", - "sha256:9e9b65a55bbabda7fccd3500192a79f6e474d8d36e78d1685496aad5f9dbd92c", - "sha256:a0b7486d85293f7f0bbc39b34e1d8aa26210b450bbd3d245ec3d732864009819", - "sha256:a53e3195f134bde03620d87a7e2b2f2046e0e5a8195e66d0f244d6d5b2f6d31b", - "sha256:a87c54e72aa2ef30189dc74427421e074ab4561cf2bf314589f6af5b37f45e6d", - "sha256:a892b5b1871b301ce20d40b037ffbe33d1407a39639c2b05356acfef5536d26a", - "sha256:a8acc9dedd304da161eb071cc7ff1326aa5b66aadec9622b2574ad3ffe225525", - "sha256:aaafc776e5edc72b3cad1ccedb5fd869cc5c9a591f1213aa9eba31a781be9ac1", - "sha256:acafc4368b289a9f291e204d2c4c75908557d4f36bd3ae937914d4529bf62a76", - "sha256:b0a5d7edb76c1c57b95df719af703e796fc8e796447a1da939f97bfa8a918d60", - "sha256:b25afe9d5c4f60dcbbe2b277a79be114e2e65a16598db8abee2a2dcde24f162b", - "sha256:b44c42edc07a50a081672e25dfe6022554b47f91e793066a7b601ca290f71e42", - "sha256:b594b64e8568cf09ee5c9501ede37066b9fc41d83d58f55b9952e32141256acd", - "sha256:b962700962f6e7a6bd77e5f37320cabac24b4c0f76afeac05e9f93cf0c620014", - "sha256:bb128c30cf1df0ab78166ded1ecf876620fb9aac84d2413e8ea1594b588c735d", - "sha256:bf9d42a71a4d7a7c1f14f629e5c30eac451a6fc81827d2beefd57d014c006c4a", - "sha256:c6595b0d8c8711e8e1dc389d52648b923b809f68ac1c6f0baa525c6440aa0daa", - "sha256:c8c6660089a25d45333cb9db56bb9e347241a6d7509838dbbd1931d0e19dbc7f", - "sha256:c9d469204abcca28926cbc28ce98f28e50e488767b084fb3fbdf21af11d3de26", - "sha256:d38bbcef58220f9c81e42c255ef0bf99735d8f11edef69ab0b499da77105158a", - "sha256:d4eb77df2964b64ba190eee00b2312a1fd7a862af8918ec70fc2d6308f76ac64", - "sha256:d63b7545d489422d417a0cae6f9898618669608750fc5e62156957e609e728a5", - "sha256:d7050899026e708fb185e174c63ebc2c4ee7a0c17b0a96ebc50e1f76a231c057", - "sha256:d79f1f2f7ebdb9b741296b69049ff44aedd95976bfee38eb4848820628a99b50", - "sha256:d85463560c67fc65cd86153a4975d0b720b6d7725cf7ee0b2d291288433fc21b", - "sha256:d9140ded382a5b04a1c030b593ed9bf3088243a0a8b7fa9f071a5736498c5483", - "sha256:d9b4916b21931b08096efed090327f8fe78e09ae8f5ad44e07f5c72a7eedb51b", - "sha256:df14f6332834444b4a37685810216cc8fe1fe91f447332cd56294c984ecbff1c", - "sha256:e49ce7dc9f925e1fb010fc3d555250139df61fa6e5a0a95ce356329602c11ea9", - "sha256:e61eae9b31799c32c5f9b7be906be3380e699e74b2db26c227c50a5fc7988698", - "sha256:ea053cefa008fda40f92aab937fb9f183cf8752e41dbc7bc68917884454c6362", - "sha256:f06e21ad0b504658a3a9edd3d8530e8cea5723f6ea5d280e8db8efc625b47e49", - "sha256:f14546403c2a1d11a130b537dda28f07eb6c1805a43dae4617448074fd49c282", - "sha256:f1a5d8f18877474c80b7711d870db0eeef9442691fcdb00adabfc97e183ee0b0", - "sha256:f2969e8f72c6236c51f91fbb79c33821d12a811e2a94b7aa59c65f8dbdfad34a", - "sha256:f468d520f47807d1eb5d27648393519655eadc578d5dd862d06873cce04c4d1b", - "sha256:f70dc00a91311a1aea124e5f64569ea44c011b58433981313202c46bccbec0e1", - "sha256:f93255b3e4d64785554e544c1c76cd32f4a354fa79e2eeca5d16ac2e7fdd57aa" + "sha256:00646784f6cd993b1e1c0e7b0fdcbccc375d539db95555477771c27555e3c556", + "sha256:00b1087dabcee0b0ffd104f9f53d7d3eaddfaa314cdd6726143af6bc713aa27e", + "sha256:0348b1dc6b76041516e8a854ff95b21c55f5a411c3297d2ca52f5528e49d8411", + "sha256:036137b5ad0cb0004c75b579445a1efccd072387a36c7f217bb8efd1afbe5245", + "sha256:095b707bb287bfd534044166ab767bec70a9bba3175dcdc3371782175c14e43c", + "sha256:0c08de15d50fa190d577e8591f0329a643eeaed696d7771760295998aca6bc66", + "sha256:1302a54f87b5cd8528e4d6d1bf2133b6aa7c6122ff8e9dc5220fbc1e07bffebd", + "sha256:172de779e2a153d36ee690dbc49c6db568d7b33b18dc56b69a7514aecbcf380d", + "sha256:1b027c86c66b8627eb90e57aee1f526df77dc6d8b354ec498be9a757d513b92b", + "sha256:1ce830e480f6774608dedfd4a90c42aac4a7af0a711f1b52f807130c2e434c06", + "sha256:1fd0c1d395372843fba13a51c28e3bb9d59bd7aebfeb17358ffaaa1e4dbbe948", + "sha256:23598acb8ccaa3d1d875ef3b35cb6376535095e9405d91a3d57a8c7db5d29341", + "sha256:24368e31be2c88bd69340fbfe741b405302993242ccb476c5c3ff48aeee1afe0", + "sha256:26a92ae76f75d1915806b77cf459811e772d8f71fd1e4339c99750f0e7f6324f", + "sha256:27e524624eace5c59af499cd97dc18bb201dc6a7a2da24bfc66ef151c69a5f2a", + "sha256:2b8719037e570639e6b665a4050add43134d80b687288ba3ade18b22bbb29dd2", + "sha256:2c5bcf3414367e29f83fd66f7de64509a8fd2368b1edf4351e862910727d3e51", + "sha256:2dbe357bc4ddda078f79d2a36fc1dd0494a7f2fad83a0a684465b6f24b46fe80", + "sha256:2f5fa187bde8524b1e37ba894db13aadd64faa884657473b03a019f625cee9a8", + "sha256:2f6ffc6701a0eb28648c845f4945a194dc7ab3c651f535b81793251e1185ac3d", + "sha256:314ccc4264ce7d854941231cf71b592e30d8d368a71e50197c905874feacc8a8", + "sha256:36026d8f99c58d7044413e1b819a67ca0e0b8ebe0f25e775e6c3d1fabb3c38fb", + "sha256:36099c69f6b14fc2c49d7996cbf4f87ec4f0e66d1c74aa05228583225a07b590", + "sha256:36fa402dcdc8ea7f1b0ddcf0df4254cc6b2e08f8cd80e7010d4c4ae6e86b2a87", + "sha256:370ffecb5316ed23b667d99ce4debe53ea664b99cc37bfa2af47bc769056d534", + "sha256:3860c62057acd95cc84044e758e47b18dcd8871a328ebc8ccdefd18b0d26a21b", + "sha256:399ac0891c284fa8eb998bcfa323f2234858f5d2efca3950ae58c8f88830f145", + "sha256:3a0b5db001b98e1c649dd55afa928e75aa4087e587b9524a4992316fa23c9fba", + "sha256:3dcf1978be02153c6a31692d4fbcc2a3f1db9da36039ead23173bc256ee3b91b", + "sha256:4241204e4b36ab5ae466ecec5c4c16527a054c69f99bba20f6f75232a6a534e2", + "sha256:438027a975cc213a47c5d70672e0d29776082155cfae540c4e225716586be75e", + "sha256:43e166ad47ba900f2542a80d83f9fc65fe99eb63ceec4debec160ae729824052", + "sha256:478e9e7b360dfec451daafe286998d4a1eeaecf6d69c427b834ae771cad4b622", + "sha256:4ce8299b481bcb68e5c82002b96e411796b844d72b3e92a3fbedfe8e19813eab", + "sha256:4f86f1f318e56f5cbb282fe61eb84767aee743ebe32c7c0834690ebea50c0a6b", + "sha256:55a23dcd98c858c0db44fc5c04fc7ed81c4b4d33c653a7c45ddaebf6563a2f66", + "sha256:599c87d79cab2a6a2a9df4aefe0455e61e7d2aeede2f8577c1b7c0aec643ee8e", + "sha256:5aa90562bc079c6c290f0512b21768967f9968e4cfea84ea4ff5af5d917016e4", + "sha256:64634ccf9d671c6be242a664a33c4acf12882670b09b3f163cd00a24cffbd74e", + "sha256:667aa2eac9cd0700af1ddb38b7b1ef246d8cf94c85637cbb03d7757ca4c3fdec", + "sha256:6a31d98c0d69776c2576dda4b77b8e0c69ad08e8b539c25c7d0ca0dc19a50d6c", + "sha256:6af4b3f52cc65f8a0bc8b1cd9676f8c21ef3e9132f21fed250f6958bd7223bed", + "sha256:6c8edaea3089bf908dd27da8f5d9e395c5b4dc092dbcce9b65e7156099b4b937", + "sha256:71d72ca5eaaa8d38c8df16b7deb1a2da4f650c41b58bb142f3fb75d5ad4a611f", + "sha256:72f9a942d739f09cd42fffe5dc759928217649f070056f03c70df14f5770acf9", + "sha256:747265448cb57a9f37572a488a57d873fd96bf51e5bb7edb52cfb37124516da4", + "sha256:75ec284328b60a4e91010c1acade0c30584f28a1f345bc8f72fe8b9e46ec6a96", + "sha256:78d0768ee59baa3de0f4adac9e3748b4b1fffc52143caebddfd5ea2961595277", + "sha256:78ee52ecc088c61cce32b2d30a826f929e1708f7b9247dc3b921aec367dc1b23", + "sha256:7be719e4d2ae6c314f72844ba9d69e38dff342bc360379f7c8537c48e23034b7", + "sha256:7e1f4744eea1501404b20b0ac059ff7e3f96a97d3e3f48ce27a139e053bb370b", + "sha256:7e90d6cc4aad2cc1f5e16ed56e46cebf4877c62403a311af20459c15da76fd91", + "sha256:7ebe3416785f65c28f4f9441e916bfc8a54179c8dea73c23023f7086fa601c5d", + "sha256:7f41533d7e3cf9520065f610b41ac1c76bc2161415955fbcead4981b22c7611e", + "sha256:7f5025db12fc6de7bc1104d826d5aee1d172f9ba6ca936bf6474c2148ac336c1", + "sha256:86c963186ca5e50d5c8287b1d1c9d3f8f024cbe343d048c5bd282aec2d8641f2", + "sha256:86ce5fcfc3accf3a07a729779d0b86c5d0309a4764c897d86c11089be61da160", + "sha256:8a14c192c1d724c3acbfb3f10a958c55a2638391319ce8078cb36c02283959b9", + "sha256:8b93785eadaef932e4fe9c6e12ba67beb1b3f1e5495631419c784ab87e975670", + "sha256:8ed1af8692bd8d2a29d702f1a2e6065416d76897d726e45a1775b1444f5928a7", + "sha256:92879bce89f91f4b2416eba4429c7b5ca22c45ef4a499c39f0c5c69257522c7c", + "sha256:94fc0e6621e07d1e91c44e016cc0b189b48db053061cc22d6298a611de8071bb", + "sha256:982487f8931067a32e72d40ab6b47b1628a9c5d344be7f1a4e668fb462d2da42", + "sha256:9862bf828112e19685b76ca499b379338fd4c5c269d897e218b2ae8fcb80139d", + "sha256:99b14dbea2fdb563d8b5a57c9badfcd72083f6006caf8e126b491519c7d64ca8", + "sha256:9c6a5c79b28003543db3ba67d1df336f253a87d3112dac3a51b94f7d48e4c0e1", + "sha256:a19b794f8fe6569472ff77602437ec4430f9b2b9ec7a1105cfd2232f9ba355e6", + "sha256:a306cdd2ad3a7d795d8e617a58c3a2ed0f76c8496fb7621b6cd514eb1532cae8", + "sha256:a3dde6cac75e0b0902778978d3b1646ca9f438654395a362cb21d9ad34b24acf", + "sha256:a874f21f87c485310944b2b2734cd6d318765bcbb7515eead33af9641816506e", + "sha256:a983cca5ed1dd9a35e9e42ebf9f278d344603bfcb174ff99a5815f953925140a", + "sha256:aca48506a9c20f68ee61c87f2008f81f8ee99f8d7f0104bff3c47e2d148f89d9", + "sha256:b2602177668f89b38b9f84b7b3435d0a72511ddef45dc14446811759b82235a1", + "sha256:b3e5fe4538001bb82e2295b8d2a39356a84694c97cb73a566dc36328b9f83b40", + "sha256:b6ca36c12a5120bad343eef193cc0122928c5c7466121da7c20f41160ba00ba2", + "sha256:b89f4477d915ea43b4ceea6756f63f0288941b6443a2b28c69004fe07fde0d0d", + "sha256:b9a9d92f10772d2a181b5ca339dee066ab7d1c9a34ae2421b2a52556e719756f", + "sha256:c99462ffc538717b3e60151dfaf91125f637e801f5ab008f81c402f1dff0cd0f", + "sha256:cb92f9061657287eded380d7dc455bbf115430b3aa4741bdc662d02977e7d0af", + "sha256:cdee837710ef6b56ebd20245b83799fce40b265b3b406e51e8ccc5b85b9099b7", + "sha256:cf10b7d58ae4a1f07fccbf4a0a956d705356fea05fb4c70608bb6fa81d103cda", + "sha256:d15687d7d7f40333bd8266f3814c591c2e2cd263fa2116e314f60d82086e353a", + "sha256:d5c28525c19f5bb1e09511669bb57353d22b94cf8b65f3a8d141c389a55dec95", + "sha256:d5f916acf8afbcab6bacbb376ba7dc61f845367901ecd5e328fc4d4aef2fcab0", + "sha256:dab03ed811ed1c71d700ed08bde8431cf429bbe59e423394f0f4055f1ca0ea60", + "sha256:db453f2da3f59a348f514cfbfeb042393b68720787bbef2b4c6068ea362c8149", + "sha256:de2a0645a923ba57c5527497daf8ec5df69c6eadf869e9cd46e86349146e5975", + "sha256:dea7fcd62915fb150cdc373212141a30037e11b761fbced340e9db3379b892d4", + "sha256:dfcbebdb3c4b6f739a91769aea5ed615023f3c88cb70df812849aef634c25fbe", + "sha256:dfcebb950aa7e667ec226a442722134539e77c575f6cfaa423f24371bb8d2e94", + "sha256:e0641b506486f0b4cd1500a2a65740243e8670a2549bb02bc4556a83af84ae03", + "sha256:e33b0834f1cf779aa839975f9d8755a7c2420510c0fa1e9fa0497de77cd35d2c", + "sha256:e4ace1e220b078c8e48e82c081e35002038657e4b37d403ce940fa679e57113b", + "sha256:e4cf2d5829f6963a5483ec01578ee76d329eb5caf330ecd05b3edd697e7d768a", + "sha256:e574de99d735b3fc8364cba9912c2bec2da78775eba95cbb225ef7dda6acea24", + "sha256:e646c0e282e960345314f42f2cea5e0b5f56938c093541ea6dbf11aec2862391", + "sha256:e8a5ac97ea521d7bde7621d86c30e86b798cdecd985723c4ed737a2aa9e77d0c", + "sha256:eedf97be7bc3dbc8addcef4142f4b4164066df0c6f36397ae4aaed3eb187d8ab", + "sha256:ef633add81832f4b56d3b4c9408b43d530dfca29e68fb1b797dcb861a2c734cd", + "sha256:f27207e8ca3e5e021e2402ba942e5b4c629718e665c81b8b306f3c8b1ddbb786", + "sha256:f85f3843bdb1fe80e8c206fe6eed7a1caeae897e496542cee499c374a85c6e08", + "sha256:f8e81e4b55930e5ffab4a68db1af431629cf2e4066dbdbfef65348b8ab804ea8", + "sha256:f96ae96a060a8072ceff4cfde89d261837b4294a4f28b84a28765470d502ccc6", + "sha256:fd9e98b408384989ea4ab60206b8e100d8687da18b5c813c11e92fd8212a98e0", + "sha256:ffff855100bc066ff2cd3aa4a60bc9534661816b110f0243e59503ec2df38421" ], "markers": "python_version >= '3.7'", - "version": "==2.6.3" + "version": "==2.14.6" + }, + "pyinstrument": { + "hashes": [ + "sha256:0711845e953fce6ab781221aacffa2a66dbc3289f8343e5babd7b2ea34da6c90", + "sha256:07cad2745964c174c65aa75f1bf68a4394d1b4d28f33894837cfd315d1e836f0", + "sha256:0ab30ae75969da99e9a529e21ff497c18fdf958e822753db4ae7ed1e67094040", + "sha256:13cb57e9607545623ebe462345b3d0c4caee0125d2d02267043ece8aca8f4ea0", + "sha256:1d0b76683df2ad5c40eff73607dc5c13828c92fbca36aff1ddf869a3c5a55fa6", + "sha256:2000712f71d693fed2f8a1c1638d37b7919124f367b37976d07128d49f1445eb", + "sha256:205ac2e76bd65d61b9611a9ce03d5f6393e34ec5b41dd38808f25d54e6b3e067", + "sha256:2097f63c66c2bc9678c826b9ff0c25acde3ed455590d9dcac21220673fe74fbf", + "sha256:23e9b4526978432e9999021da9a545992cf2ac3df5ee82db7beb6908fc4c978c", + "sha256:29172ab3d8609fdf821c3f2562dc61e14f1a8ff5306607c32ca743582d3a760e", + "sha256:2cd4ce750c34a0318fc2d6c727cc255e9658d12a5cf3f2d0473f1c27157bdaeb", + "sha256:2dbcaccc9f456ef95557ec501caeb292119c24446d768cb4fb43578b0f3d572c", + "sha256:2e02cf505e932eb8ccf561b7527550a67ec14fcae1fe0e25319b09c9c166e914", + "sha256:37e989c44b51839d0c97466fa2b623638b9470d56d79e329f359f0e8fa6d83db", + "sha256:3f414ddf1161976a40fc0a333000e6a4ad612719eac0b8c9bb73f47153187148", + "sha256:475ac31477f6302e092463896d6a2055f3e6abcd293bad16ff94fc9185308a88", + "sha256:476785cfbc44e8e1b1ad447398aa3deae81a8df4d37eb2d8bbb0c404eff979cd", + "sha256:4d1da8efd974cf9df52ee03edaee2d3875105ddd00de35aa542760f7c612bdf7", + "sha256:507be1ee2f2b0c9fba74d622a272640dd6d1b0c9ec3388b2cdeb97ad1e77125f", + "sha256:5494c5a84fee4309d7d973366ca6b8b9f8ba1d6b254e93b7c506264ef74f2cef", + "sha256:574cfca69150be4ce4461fb224712fbc0722a49b0dc02fa204d02807adf6b5a0", + "sha256:5b7d28582017de35cb64eb4e4fa603e753095108ca03745f5d17295970ee631f", + "sha256:65e62ebfa2cd8fb57eda90006f4505ac4c70da00fc2f05b6d8337d776ea76d41", + "sha256:6c4c56b6eab9004e92ad8a48bb54913fdd71fc8a748ae42a27b9e26041646f8b", + "sha256:6ca95b21f022e995e062b371d1f42d901452bcbedd2c02f036de677119503355", + "sha256:6ffbf56605ef21c2fcb60de2fa74ff81f417d8be0c5002a407e414d6ef6dee43", + "sha256:73476e4bc6e467ac1b2c3c0dd1f0b71c9061d4de14626676adfdfbb14aa342b4", + "sha256:79ae152f8c6a680a188fb3be5e0f360ac05db5bbf410169a6c40851dfaebcce9", + "sha256:7be57db08bd366a37db3aa3a6187941ee21196e8b14975db337ddc7d1490649d", + "sha256:832fb2acef9d53701c1ab546564c45fb70a8770c816374f8dd11420d399103c9", + "sha256:871b131b83e9b1122f2325061c68ed1e861eebcb568c934d2fb193652f077f77", + "sha256:8b45075d9dbbc977dbc7007fb22bb0054c6990fbe91bf48dd80c0b96c6307ba7", + "sha256:8d8515156dd91f5652d13b5fcc87e634f8fe1c07b68d1d0840348cdd50bf5ace", + "sha256:95cee6de08eb45754ef4f602ce52b640d1c535d934a6a8733a974daa095def37", + "sha256:97c9660cdb4bd2a43cf4f3ab52cffd22f3ac9a748d913b750178fb34e5e39e64", + "sha256:9a0ac0f56860398d2628ce389826ce83fb3a557d0c9a2351e8a2eac6eb869983", + "sha256:9be89e7419bcfe8dd6abb0d959d6d9c439c613a4a873514c43d16b48dae697c9", + "sha256:9e160d9c5d20d3e4ef82269e4e8b246ff09bdf37af5fb8cb8ccca97936d95ad6", + "sha256:a18cd234cce4f230f1733807f17a134e64a1f1acabf74a14d27f583cf2b183df", + "sha256:a242f6cac40bc83e1f3002b6b53681846dfba007f366971db0bf21e02dbb1903", + "sha256:a366c6f3dfb11f1739bdc1dee75a01c1563ad0bf4047071e5e77598087df457f", + "sha256:a9045186ff13bc826fef16be53736a85029aae3c6adfe52e666cad00d7ca623b", + "sha256:ac1e1d7e1f1b64054c4eb04eb4869a7a5eef2261440e73943cc1b1bc3c828c18", + "sha256:bd176f297c99035127b264369d2bb97a65255f65f8d4e843836baf55ebb3cee4", + "sha256:c4b7af1d9d6a523cfbfedebcb69202242d5bd0cb89c4e094cc73d5d6e38279bd", + "sha256:c6be327be65d934796558aa9cb0f75ce62ebd207d49ad1854610c97b0579ad47", + "sha256:c7873e8cec92321251fdf894a72b3c78f4c5c20afdd1fef0baf9042ec843bb04", + "sha256:c92cc4924596d6e8f30a16182bbe90893b1572d847ae12652f72b34a9a17c24a", + "sha256:cb81f66f7f94045d723069cf317453d42375de9ff3c69089cf6466b078ac1db4", + "sha256:cee21a2d78187dd8a80f72f5d0f1ddb767b2d9800f8bb4d94b6d11f217c22cdb", + "sha256:d96309df4df10be7b4885797c5f69bb3a89414680ebaec0722d8156fde5268c3", + "sha256:dc37cb988c8854eb42bda2e438aaf553536566657d157c4473cc8aad5692a779", + "sha256:e304cd0723e2b18ada5e63c187abf6d777949454c734f5974d64a0865859f0f4", + "sha256:e7a386392275bdef4a1849712dc5b74f0023483fca14ef93d0ca27d453548982", + "sha256:e9cebd90128a3d2fee36d3ccb665c1b9dce75261061b2046203e45c4a8012d54", + "sha256:f36cb5b644762fb3c86289324bbef17e95f91cd710603ac19444a47f638e8e96", + "sha256:f3d1ad3bc8ebb4db925afa706aa865c4bfb40d52509f143491ac0df2440ee5d2", + "sha256:f4731b27121350f5a983d358d2272fe3df2f538aed058f57217eef7801a89288", + "sha256:f4b48a94d938cae981f6948d9ec603bab2087b178d2095d042d5a48aabaecaab", + "sha256:fb868fbe089036e9f32525a249f4c78b8dc46967612393f204b8234f439c9cc4" + ], + "index": "pypi", + "version": "==4.6.1" }, "pymongo": { "hashes": [ - "sha256:076afa0a4a96ca9f77fec0e4a0d241200b3b3a1766f8d7be9a905ecf59a7416b", - "sha256:08819da7864f9b8d4a95729b2bea5fffed08b63d3b9c15b4fea47de655766cf5", - "sha256:0a1f26bc1f5ce774d99725773901820dfdfd24e875028da4a0252a5b48dcab5c", - "sha256:0f4b125b46fe377984fbaecf2af40ed48b05a4b7676a2ff98999f2016d66b3ec", - "sha256:1240edc1a448d4ada4bf1a0e55550b6292420915292408e59159fd8bbdaf8f63", - "sha256:152259f0f1a60f560323aacf463a3642a65a25557683f49cfa08c8f1ecb2395a", - "sha256:168172ef7856e20ec024fe2a746bfa895c88b32720138e6438fd765ebd2b62dd", - "sha256:1b1d7d9aabd8629a31d63cd106d56cca0e6420f38e50563278b520f385c0d86e", - "sha256:1d40ad09d9f5e719bc6f729cc6b17f31c0b055029719406bd31dde2f72fca7e7", - "sha256:21b953da14549ff62ea4ae20889c71564328958cbdf880c64a92a48dda4c9c53", - "sha256:23cc6d7eb009c688d70da186b8f362d61d5dd1a2c14a45b890bd1e91e9c451f2", - "sha256:2988ef5e6b360b3ff1c6d55c53515499de5f48df31afd9f785d788cdacfbe2d3", - "sha256:2a0aade2b11dc0c326ccd429ee4134d2d47459ff68d449c6d7e01e74651bd255", - "sha256:2b0176f9233a5927084c79ff80b51bd70bfd57e4f3d564f50f80238e797f0c8a", - "sha256:2d4fa1b01fa7e5b7bb8d312e3542e211b320eb7a4e3d8dc884327039d93cb9e0", - "sha256:3236cf89d69679eaeb9119c840f5c7eb388a2110b57af6bb6baf01a1da387c18", - "sha256:33faa786cc907de63f745f587e9879429b46033d7d97a7b84b37f4f8f47b9b32", - "sha256:37df8f6006286a5896d1cbc3efb8471ced42e3568d38e6cb00857277047b0d63", - "sha256:3a7166d57dc74d679caa7743b8ecf7dc3a1235a9fd178654dddb2b2a627ae229", - "sha256:3d79ae3bb1ff041c0db56f138c88ce1dfb0209f3546d8d6e7c3f74944ecd2439", - "sha256:3e33064f1984db412b34d51496f4ea785a9cff621c67de58e09fb28da6468a52", - "sha256:3fa3648e4f1e63ddfe53563ee111079ea3ab35c3b09cd25bc22dadc8269a495f", - "sha256:40d5f6e853ece9bfc01e9129b228df446f49316a4252bb1fbfae5c3c9dedebad", - "sha256:41771b22dd2822540f79a877c391283d4e6368125999a5ec8beee1ce566f3f82", - "sha256:435228d3c16a375274ac8ab9c4f9aef40c5e57ddb8296e20ecec9e2461da1017", - "sha256:44ee985194c426ddf781fa784f31ffa29cb59657b2dba09250a4245431847d73", - "sha256:465fd5b040206f8bce7016b01d7e7f79d2fcd7c2b8e41791be9632a9df1b4999", - "sha256:496c9cbcb4951183d4503a9d7d2c1e3694aab1304262f831d5e1917e60386036", - "sha256:49dce6957598975d8b8d506329d2a3a6c4aee911fa4bbcf5e52ffc6897122950", - "sha256:4c42748ccc451dfcd9cef6c5447a7ab727351fd9747ad431db5ebb18a9b78a4d", - "sha256:505f8519c4c782a61d94a17b0da50be639ec462128fbd10ab0a34889218fdee3", - "sha256:53f2dda54d76a98b43a410498bd12f6034b2a14b6844ca08513733b2b20b7ad8", - "sha256:56320c401f544d762fc35766936178fbceb1d9261cd7b24fbfbc8fb6f67aa8a5", - "sha256:58a63a26a1e3dc481dd3a18d6d9f8bd1d576cd1ffe0d479ba7dd38b0aeb20066", - "sha256:5caee7bd08c3d36ec54617832b44985bd70c4cbd77c5b313de6f7fce0bb34f93", - "sha256:631492573a1bef2f74f9ac0f9d84e0ce422c251644cd81207530af4aa2ee1980", - "sha256:63d8019eee119df308a075b8a7bdb06d4720bf791e2b73d5ab0e7473c115d79c", - "sha256:6422b6763b016f2ef2beedded0e546d6aa6ba87910f9244d86e0ac7690f75c96", - "sha256:681f252e43b3ef054ca9161635f81b730f4d8cadd28b3f2b2004f5a72f853982", - "sha256:6d64878d1659d2a5bdfd0f0a4d79bafe68653c573681495e424ab40d7b6d6d41", - "sha256:74c0da07c04d0781490b2915e7514b1adb265ef22af039a947988c331ee7455b", - "sha256:7591a3beea6a9a4fa3080d27d193b41f631130e3ffa76b88c9ccea123f26dc59", - "sha256:76a262c41c1a7cbb84a3b11976578a7eb8e788c4b7bfbd15c005fb6ca88e6e50", - "sha256:77cfff95c1fafd09e940b3fdcb7b65f11442662fad611d0e69b4dd5d17a81c60", - "sha256:8027c9063579083746147cf401a7072a9fb6829678076cd3deff28bb0e0f50c8", - "sha256:80a167081c75cf66b32f30e2f1eaee9365af935a86dbd76788169911bed9b5d5", - "sha256:840eaf30ccac122df260b6005f9dfae4ac287c498ee91e3e90c56781614ca238", - "sha256:8543253adfaa0b802bfa88386db1009c6ebb7d5684d093ee4edc725007553d21", - "sha256:89b3f2da57a27913d15d2a07d58482f33d0a5b28abd20b8e643ab4d625e36257", - "sha256:8e559116e4128630ad3b7e788e2e5da81cbc2344dee246af44471fa650486a70", - "sha256:9aff6279e405dc953eeb540ab061e72c03cf38119613fce183a8e94f31be608f", - "sha256:9c04b9560872fa9a91251030c488e0a73bce9321a70f991f830c72b3f8115d0d", - "sha256:9d2346b00af524757576cc2406414562cced1d4349c92166a0ee377a2a483a80", - "sha256:a253b765b7cbc4209f1d8ee16c7287c4268d3243070bf72d7eec5aa9dfe2a2c2", - "sha256:a8127437ebc196a6f5e8fddd746bd0903a400dc6b5ae35df672dd1ccc7170a2a", - "sha256:b25f7bea162b3dbec6d33c522097ef81df7c19a9300722fa6853f5b495aecb77", - "sha256:b33c17d9e694b66d7e96977e9e56df19d662031483efe121a24772a44ccbbc7e", - "sha256:b4fe46b58010115514b842c669a0ed9b6a342017b15905653a5b1724ab80917f", - "sha256:b520aafc6cb148bac09ccf532f52cbd31d83acf4d3e5070d84efe3c019a1adbf", - "sha256:b5bbb87fa0511bd313d9a2c90294c88db837667c2bda2ea3fa7a35b59fd93b1f", - "sha256:b6d2a56fc2354bb6378f3634402eec788a8f3facf0b3e7d468db5f2b5a78d763", - "sha256:bbd705d5f3c3d1ff2d169e418bb789ff07ab3c70d567cc6ba6b72b04b9143481", - "sha256:bc5d8c3647b8ae28e4312f1492b8f29deebd31479cd3abaa989090fb1d66db83", - "sha256:c3c3525ea8658ee1192cdddf5faf99b07ebe1eeaa61bf32821126df6d1b8072b", - "sha256:c9a9a39b7cac81dca79fca8c2a6479ef4c7b1aab95fad7544cc0e8fd943595a2", - "sha256:cd4c8d6aa91d3e35016847cbe8d73106e3d1c9a4e6578d38e2c346bfe8edb3ca", - "sha256:cf62da7a4cdec9a4b2981fcbd5e08053edffccf20e845c0b6ec1e77eb7fab61d", - "sha256:d67225f05f6ea27c8dc57f3fa6397c96d09c42af69d46629f71e82e66d33fa4f", - "sha256:dfcd2b9f510411de615ccedd47462dae80e82fdc09fe9ab0f0f32f11cf57eeb5", - "sha256:e1f61355c821e870fb4c17cdb318669cfbcf245a291ce5053b41140870c3e5cc", - "sha256:e249190b018d63c901678053b4a43e797ca78b93fb6d17633e3567d4b3ec6107", - "sha256:e2654d1278384cff75952682d17c718ecc1ad1d6227bb0068fd826ba47d426a5", - "sha256:e57d859b972c75ee44ea2ef4758f12821243e99de814030f69a3decb2aa86807", - "sha256:e5a27f348909235a106a3903fc8e70f573d89b41d723a500869c6569a391cff7", - "sha256:ead4f19d0257a756b21ac2e0e85a37a7245ddec36d3b6008d5bfe416525967dc", - "sha256:f076b779aa3dc179aa3ed861be063a313ed4e48ae9f6a8370a9b1295d4502111", - "sha256:f1bb3a62395ffe835dbef3a1cbff48fbcce709c78bd1f52e896aee990928432b", - "sha256:f2227a08b091bd41df5aadee0a5037673f691e2aa000e1968b1ea2342afc6880", - "sha256:f3754acbd7efc7f1b529039fcffc092a15e1cf045e31f22f6c9c5950c613ec4d", - "sha256:fe48f50fb6348511a3268a893bfd4ab5f263f5ac220782449d03cd05964d1ae7", - "sha256:fff7d17d30b2cd45afd654b3fc117755c5d84506ed25fda386494e4e0a3416e1" + "sha256:00c199e1c593e2c8b033136d7a08f0c376452bac8a896c923fcd6f419e07bdd2", + "sha256:010bc9aa90fd06e5cc52c8fac2c2fd4ef1b5f990d9638548dde178005770a5e8", + "sha256:026a24a36394dc8930cbcb1d19d5eb35205ef3c838a7e619e04bd170713972e7", + "sha256:061598cbc6abe2f382ab64c9caa83faa2f4c51256f732cdd890bcc6e63bfb67e", + "sha256:13552ca505366df74e3e2f0a4f27c363928f3dff0eef9f281eb81af7f29bc3c5", + "sha256:13d613c866f9f07d51180f9a7da54ef491d130f169e999c27e7633abe8619ec9", + "sha256:144a31391a39a390efce0c5ebcaf4bf112114af4384c90163f402cec5ede476b", + "sha256:1461199b07903fc1424709efafe379205bf5f738144b1a50a08b0396357b5abf", + "sha256:154b361dcb358ad377d5d40df41ee35f1cc14c8691b50511547c12404f89b5cb", + "sha256:1c5654bb8bb2bdb10e7a0bc3c193dd8b49a960b9eebc4381ff5a2043f4c3c441", + "sha256:1de3c6faf948f3edd4e738abdb4b76572b4f4fdfc1fed4dad02427e70c5a6219", + "sha256:1ed23b0e2dac6f84f44c8494fbceefe6eb5c35db5c1099f56ab78fc0d94ab3af", + "sha256:1f2b856518bfcfa316c8dae3d7b412aecacf2e8ba30b149f5eb3b63128d703b9", + "sha256:2346450a075625c4d6166b40a013b605a38b6b6168ce2232b192a37fb200d588", + "sha256:262356ea5fcb13d35fb2ab6009d3927bafb9504ef02339338634fffd8a9f1ae4", + "sha256:27b81ecf18031998ad7db53b960d1347f8f29e8b7cb5ea7b4394726468e4295e", + "sha256:2940aa20e9cc328e8ddeacea8b9a6f5ddafe0b087fedad928912e787c65b4909", + "sha256:2d4ccac3053b84a09251da8f5350bb684cbbf8c8c01eda6b5418417d0a8ab198", + "sha256:2dd2f6960ee3c9360bed7fb3c678be0ca2d00f877068556785ec2eb6b73d2414", + "sha256:3071ec998cc3d7b4944377e5f1217c2c44b811fae16f9a495c7a1ce9b42fb038", + "sha256:3094c7d2f820eecabadae76bfec02669567bbdd1730eabce10a5764778564f7b", + "sha256:30b2c9caf3e55c2e323565d1f3b7e7881ab87db16997dc0cbca7c52885ed2347", + "sha256:3177f783ae7e08aaf7b2802e0df4e4b13903520e8380915e6337cdc7a6ff01d8", + "sha256:31dab1f3e1d0cdd57e8df01b645f52d43cc1b653ed3afd535d2891f4fc4f9712", + "sha256:33bb16a07d3cc4e0aea37b242097cd5f7a156312012455c2fa8ca396953b11c4", + "sha256:349093675a2d3759e4fb42b596afffa2b2518c890492563d7905fac503b20daa", + "sha256:39d77d8bbb392fa443831e6d4ae534237b1f4eee6aa186f0cdb4e334ba89536e", + "sha256:3a7f02a58a0c2912734105e05dedbee4f7507e6f1bd132ebad520be0b11d46fd", + "sha256:3b287e814a01deddb59b88549c1e0c87cefacd798d4afc0c8bd6042d1c3d48aa", + "sha256:3c74f4725485f0a7a3862cfd374cc1b740cebe4c133e0c1425984bcdcce0f4bb", + "sha256:3cadf7f4c8e94d8a77874b54a63c80af01f4d48c4b669c8b6867f86a07ba994f", + "sha256:3d18a9b9b858ee140c15c5bfcb3e66e47e2a70a03272c2e72adda2482f76a6ad", + "sha256:3f0e6a6c807fa887a0c51cc24fe7ea51bb9e496fe88f00d7930063372c3664c3", + "sha256:4344c30025210b9fa80ec257b0e0aab5aa1d5cca91daa70d82ab97b482cc038e", + "sha256:4497d49d785482cc1a44a0ddf8830b036a468c088e72a05217f5b60a9e025012", + "sha256:547dc5d7f834b1deefda51aedb11a7af9c51c45e689e44e14aa85d44147c7657", + "sha256:5556e306713e2522e460287615d26c0af0fe5ed9d4f431dad35c6624c5d277e9", + "sha256:55dac73316e7e8c2616ba2e6f62b750918e9e0ae0b2053699d66ca27a7790105", + "sha256:56816e43c92c2fa8c11dc2a686f0ca248bea7902f4a067fa6cbc77853b0f041e", + "sha256:5bd94c503271e79917b27c6e77f7c5474da6930b3fb9e70a12e68c2dff386b9a", + "sha256:5ec31adc2e988fd7db3ab509954791bbc5a452a03c85e45b804b4bfc31fa221d", + "sha256:69247f7a2835fc0984bbf0892e6022e9a36aec70e187fcfe6cae6a373eb8c4de", + "sha256:6a0ae7a48a6ef82ceb98a366948874834b86c84e288dbd55600c1abfc3ac1d88", + "sha256:6a1810c2cbde714decf40f811d1edc0dae45506eb37298fd9d4247b8801509fe", + "sha256:6dcc95f4bb9ed793714b43f4f23a7b0c57e4ef47414162297d6f650213512c19", + "sha256:76013fef1c9cd1cd00d55efde516c154aa169f2bf059b197c263a255ba8a9ddf", + "sha256:77e0df59b1a4994ad30c6d746992ae887f9756a43fc25dec2db515d94cf0222d", + "sha256:7bb0e9049e81def6829d09558ad12d16d0454c26cabe6efc3658e544460688d9", + "sha256:88beb444fb438385e53dc9110852910ec2a22f0eab7dd489e827038fdc19ed8d", + "sha256:8b47ebd89e69fbf33d1c2df79759d7162fc80c7652dacfec136dae1c9b3afac7", + "sha256:8d219b4508f71d762368caec1fc180960569766049bbc4d38174f05e8ef2fe5b", + "sha256:8ec75f35f62571a43e31e7bd11749d974c1b5cd5ea4a8388725d579263c0fdf6", + "sha256:9167e735379ec43d8eafa3fd675bfbb12e2c0464f98960586e9447d2cf2c7a83", + "sha256:9a710c184ba845afb05a6f876edac8f27783ba70e52d5eaf939f121fc13b2f59", + "sha256:9aafd036f6f2e5ad109aec92f8dbfcbe76cff16bad683eb6dd18013739c0b3ae", + "sha256:9c79d597fb3a7c93d7c26924db7497eba06d58f88f58e586aa69b2ad89fee0f8", + "sha256:a2831e05ce0a4df10c4ac5399ef50b9a621f90894c2a4d2945dc5658765514ed", + "sha256:a5e641f931c5cd95b376fd3c59db52770e17bec2bf86ef16cc83b3906c054845", + "sha256:b10d8cda9fc2fcdcfa4a000aa10413a2bf8b575852cd07cb8a595ed09689ca98", + "sha256:b435b13bb8e36be11b75f7384a34eefe487fe87a6267172964628e2b14ecf0a7", + "sha256:b7b1a83ce514700276a46af3d9e481ec381f05b64939effc9065afe18456a6b9", + "sha256:b8729dbf25eb32ad0dc0b9bd5e6a0d0b7e5c2dc8ec06ad171088e1896b522a74", + "sha256:bbed8cccebe1169d45cedf00461b2842652d476d2897fd1c42cf41b635d88746", + "sha256:c258dbacfff1224f13576147df16ce3c02024a0d792fd0323ac01bed5d3c545d", + "sha256:c30a9e06041fbd7a7590693ec5e407aa8737ad91912a1e70176aff92e5c99d20", + "sha256:c91ea3915425bd4111cb1b74511cdc56d1d16a683a48bf2a5a96b6a6c0f297f7", + "sha256:d0355cff58a4ed6d5e5f6b9c3693f52de0784aa0c17119394e2a8e376ce489d4", + "sha256:d483793a384c550c2d12cb794ede294d303b42beff75f3b3081f57196660edaf", + "sha256:d4c2be9760b112b1caf649b4977b81b69893d75aa86caf4f0f398447be871f3c", + "sha256:d8e62d06e90f60ea2a3d463ae51401475568b995bafaffd81767d208d84d7bb1", + "sha256:da08ea09eefa6b960c2dd9a68ec47949235485c623621eb1d6c02b46765322ac", + "sha256:dd1fa413f8b9ba30140de198e4f408ffbba6396864c7554e0867aa7363eb58b2", + "sha256:e2aced6fb2f5261b47d267cb40060b73b6527e64afe54f6497844c9affed5fd0", + "sha256:e438417ce1dc5b758742e12661d800482200b042d03512a8f31f6aaa9137ad40", + "sha256:e470fa4bace5f50076c32f4b3cc182b31303b4fefb9b87f990144515d572820b", + "sha256:eaf2f65190c506def2581219572b9c70b8250615dc918b3b7c218361a51ec42e", + "sha256:ef102a67ede70e1721fe27f75073b5314911dbb9bc27cde0a1c402a11531e7bd", + "sha256:ef801027629c5b511cf2ba13b9be29bfee36ae834b2d95d9877818479cdc99ea", + "sha256:f7acc03a4f1154ba2643edeb13658d08598fe6e490c3dd96a241b94f09801626", + "sha256:f9756f1d25454ba6a3c2f1ef8b7ddec23e5cdeae3dc3c3377243ae37a383db00", + "sha256:ff62ba8ff70f01ab4fe0ae36b2cb0b5d1f42e73dfc81ddf0758cd9f77331ad25", + "sha256:ff925f1cca42e933376d09ddc254598f8c5fcd36efc5cac0118bb36c36217c41" ], "markers": "python_version >= '3.7'", - "version": "==4.5.0" + "version": "==4.6.1" }, "pyproj": { "hashes": [ @@ -1130,113 +1187,121 @@ }, "scikit-learn": { "hashes": [ - "sha256:0ce9233cdf0cdcf0858a5849d306490bf6de71fa7603a3835124e386e62f2311", - "sha256:14e8775eba072ab10866a7e0596bc9906873e22c4c370a651223372eb62de180", - "sha256:1a231cced3ee3fa04756b4a7ab532dc9417acd581a330adff5f2c01ac2831fcf", - "sha256:1ec668ce003a5b3d12d020d2cde0abd64b262ac5f098b5c84cf9657deb9996a8", - "sha256:3153612ff8d36fa4e35ef8b897167119213698ea78f3fd130b4068e6f8d2da5a", - "sha256:4d379f2b34096105a96bd857b88601dffe7389bd55750f6f29aaa37bc6272eb5", - "sha256:52b77cc08bd555969ec5150788ed50276f5ef83abb72e6f469c5b91a0009bbca", - "sha256:58b0c2490eff8355dc26e884487bf8edaccf2ba48d09b194fb2f3a026dd64f9d", - "sha256:66f7bb1fec37d65f4ef85953e1df5d3c98a0f0141d394dcdaead5a6de9170347", - "sha256:6bb9490fdb8e7e00f1354621689187bef3cab289c9b869688f805bf724434755", - "sha256:7d8dee8c1f40eeba49a85fe378bdf70a07bb64aba1a08fda1e0f48d27edfc3e6", - "sha256:8454d57a22d856f1fbf3091bd86f9ebd4bff89088819886dc0c72f47a6c30652", - "sha256:845f81c7ceb4ea6bac64ab1c9f2ce8bef0a84d0f21f3bece2126adcc213dfecd", - "sha256:8d993fb70a1d78c9798b8f2f28705bfbfcd546b661f9e2e67aa85f81052b9c53", - "sha256:a15d964d9eb181c79c190d3dbc2fff7338786bf017e9039571418a1d53dab236", - "sha256:a683394bc3f80b7c312c27f9b14ebea7766b1f0a34faf1a2e9158d80e860ec26", - "sha256:a7135a03af71138669f19bc96e7d0cc8081aed4b3565cc3b131135d65fc642ba", - "sha256:c413c2c850241998168bbb3bd1bb59ff03b1195a53864f0b80ab092071af6028", - "sha256:c6448c37741145b241eeac617028ba6ec2119e1339b1385c9720dae31367f2be", - "sha256:ccbbedae99325628c1d1cbe3916b7ef58a1ce949672d8d39c8b190e10219fd32", - "sha256:f66eddfda9d45dd6cadcd706b65669ce1df84b8549875691b1f403730bdef217" + "sha256:0402638c9a7c219ee52c94cbebc8fcb5eb9fe9c773717965c1f4185588ad3107", + "sha256:0ee107923a623b9f517754ea2f69ea3b62fc898a3641766cb7deb2f2ce450161", + "sha256:1215e5e58e9880b554b01187b8c9390bf4dc4692eedeaf542d3273f4785e342c", + "sha256:15e1e94cc23d04d39da797ee34236ce2375ddea158b10bee3c343647d615581d", + "sha256:18424efee518a1cde7b0b53a422cde2f6625197de6af36da0b57ec502f126157", + "sha256:1d08ada33e955c54355d909b9c06a4789a729977f165b8bae6f225ff0a60ec4a", + "sha256:3271552a5eb16f208a6f7f617b8cc6d1f137b52c8a1ef8edf547db0259b2c9fb", + "sha256:35a22e8015048c628ad099da9df5ab3004cdbf81edc75b396fd0cff8699ac58c", + "sha256:535805c2a01ccb40ca4ab7d081d771aea67e535153e35a1fd99418fcedd1648a", + "sha256:5b2de18d86f630d68fe1f87af690d451388bb186480afc719e5f770590c2ef6c", + "sha256:61a6efd384258789aa89415a410dcdb39a50e19d3d8410bd29be365bcdd512d5", + "sha256:64381066f8aa63c2710e6b56edc9f0894cc7bf59bd71b8ce5613a4559b6145e0", + "sha256:67f37d708f042a9b8d59551cf94d30431e01374e00dc2645fa186059c6c5d78b", + "sha256:6c43290337f7a4b969d207e620658372ba3c1ffb611f8bc2b6f031dc5c6d1d03", + "sha256:6fb6bc98f234fda43163ddbe36df8bcde1d13ee176c6dc9b92bb7d3fc842eb66", + "sha256:763f0ae4b79b0ff9cca0bf3716bcc9915bdacff3cebea15ec79652d1cc4fa5c9", + "sha256:785a2213086b7b1abf037aeadbbd6d67159feb3e30263434139c98425e3dcfcf", + "sha256:8db94cd8a2e038b37a80a04df8783e09caac77cbe052146432e67800e430c028", + "sha256:a19f90f95ba93c1a7f7924906d0576a84da7f3b2282ac3bfb7a08a32801add93", + "sha256:a2f54c76accc15a34bfb9066e6c7a56c1e7235dda5762b990792330b52ccfb05", + "sha256:b8692e395a03a60cd927125eef3a8e3424d86dde9b2370d544f0ea35f78a8073", + "sha256:cb06f8dce3f5ddc5dee1715a9b9f19f20d295bed8e3cd4fa51e1d050347de525", + "sha256:dc9002fc200bed597d5d34e90c752b74df516d592db162f756cc52836b38fe0e", + "sha256:e326c0eb5cf4d6ba40f93776a20e9a7a69524c4db0757e7ce24ba222471ee8a1", + "sha256:ed932ea780517b00dae7431e031faae6b49b20eb6950918eb83bd043237950e0", + "sha256:fc4144a5004a676d5022b798d9e573b05139e77f271253a4703eed295bde0433" ], "index": "pypi", - "version": "==1.3.1" + "version": "==1.3.2" }, "scipy": { "hashes": [ - "sha256:0f3261f14b767b316d7137c66cc4f33a80ea05841b9c87ad83a726205b901423", - "sha256:10eb6af2f751aa3424762948e5352f707b0dece77288206f227864ddf675aca0", - "sha256:1342ca385c673208f32472830c10110a9dcd053cf0c4b7d4cd7026d0335a6c1d", - "sha256:214cdf04bbae7a54784f8431f976704ed607c4bc69ba0d5d5d6a9df84374df76", - "sha256:2b997a5369e2d30c97995dcb29d638701f8000d04df01b8e947f206e5d0ac788", - "sha256:2c91cf049ffb5575917f2a01da1da082fd24ed48120d08a6e7297dfcac771dcd", - "sha256:3aeb87661de987f8ec56fa6950863994cd427209158255a389fc5aea51fa7055", - "sha256:4447ad057d7597476f9862ecbd9285bbf13ba9d73ce25acfa4e4b11c6801b4c9", - "sha256:542a757e2a6ec409e71df3d8fd20127afbbacb1c07990cb23c5870c13953d899", - "sha256:8d9886f44ef8c9e776cb7527fb01455bf4f4a46c455c4682edc2c2cc8cd78562", - "sha256:90d3b1364e751d8214e325c371f0ee0dd38419268bf4888b2ae1040a6b266b2a", - "sha256:95763fbda1206bec41157582bea482f50eb3702c85fffcf6d24394b071c0e87a", - "sha256:ac74b1512d38718fb6a491c439aa7b3605b96b1ed3be6599c17d49d6c60fca18", - "sha256:afdb0d983f6135d50770dd979df50bf1c7f58b5b33e0eb8cf5c73c70600eae1d", - "sha256:b0620240ef445b5ddde52460e6bc3483b7c9c750275369379e5f609a1050911c", - "sha256:b133f237bd8ba73bad51bc12eb4f2d84cbec999753bf25ba58235e9fc2096d80", - "sha256:b29318a5e39bd200ca4381d80b065cdf3076c7d7281c5e36569e99273867f61d", - "sha256:b8425fa963a32936c9773ee3ce44a765d8ff67eed5f4ac81dc1e4a819a238ee9", - "sha256:d2b813bfbe8dec6a75164523de650bad41f4405d35b0fa24c2c28ae07fcefb20", - "sha256:d690e1ca993c8f7ede6d22e5637541217fc6a4d3f78b3672a6fe454dbb7eb9a7", - "sha256:e367904a0fec76433bf3fbf3e85bf60dae8e9e585ffd21898ab1085a29a04d16", - "sha256:ea932570b1c2a30edafca922345854ff2cd20d43cd9123b6dacfdecebfc1a80b", - "sha256:f28f1f6cfeb48339c192efc6275749b2a25a7e49c4d8369a28b6591da02fbc9a", - "sha256:f73102f769ee06041a3aa26b5841359b1a93cc364ce45609657751795e8f4a4a", - "sha256:fa4909c6c20c3d91480533cddbc0e7c6d849e7d9ded692918c76ce5964997898" + "sha256:00150c5eae7b610c32589dda259eacc7c4f1665aedf25d921907f4d08a951b1c", + "sha256:028eccd22e654b3ea01ee63705681ee79933652b2d8f873e7949898dda6d11b6", + "sha256:1b7c3dca977f30a739e0409fb001056484661cb2541a01aba0bb0029f7b68db8", + "sha256:2c6ff6ef9cc27f9b3db93a6f8b38f97387e6e0591600369a297a50a8e96e835d", + "sha256:36750b7733d960d7994888f0d148d31ea3017ac15eef664194b4ef68d36a4a97", + "sha256:530f9ad26440e85766509dbf78edcfe13ffd0ab7fec2560ee5c36ff74d6269ff", + "sha256:5e347b14fe01003d3b78e196e84bd3f48ffe4c8a7b8a1afbcb8f5505cb710993", + "sha256:6550466fbeec7453d7465e74d4f4b19f905642c89a7525571ee91dd7adabb5a3", + "sha256:6df1468153a31cf55ed5ed39647279beb9cfb5d3f84369453b49e4b8502394fd", + "sha256:6e619aba2df228a9b34718efb023966da781e89dd3d21637b27f2e54db0410d7", + "sha256:8fce70f39076a5aa62e92e69a7f62349f9574d8405c0a5de6ed3ef72de07f446", + "sha256:90a2b78e7f5733b9de748f589f09225013685f9b218275257f8a8168ededaeaa", + "sha256:91af76a68eeae0064887a48e25c4e616fa519fa0d38602eda7e0f97d65d57937", + "sha256:933baf588daa8dc9a92c20a0be32f56d43faf3d1a60ab11b3f08c356430f6e56", + "sha256:acf8ed278cc03f5aff035e69cb511741e0418681d25fbbb86ca65429c4f4d9cd", + "sha256:ad669df80528aeca5f557712102538f4f37e503f0c5b9541655016dd0932ca79", + "sha256:b030c6674b9230d37c5c60ab456e2cf12f6784596d15ce8da9365e70896effc4", + "sha256:b9999c008ccf00e8fbcce1236f85ade5c569d13144f77a1946bef8863e8f6eb4", + "sha256:bc9a714581f561af0848e6b69947fda0614915f072dfd14142ed1bfe1b806710", + "sha256:ce7fff2e23ab2cc81ff452a9444c215c28e6305f396b2ba88343a567feec9660", + "sha256:cf00bd2b1b0211888d4dc75656c0412213a8b25e80d73898083f402b50f47e41", + "sha256:d10e45a6c50211fe256da61a11c34927c68f277e03138777bdebedd933712fea", + "sha256:ee410e6de8f88fd5cf6eadd73c135020bfbbbdfcd0f6162c36a7638a1ea8cc65", + "sha256:f313b39a7e94f296025e3cffc2c567618174c0b1dde173960cf23808f9fae4be", + "sha256:f3cd9e7b3c2c1ec26364856f9fbe78695fe631150f94cd1c22228456404cf1ec" ], - "markers": "python_version < '3.13' and python_version >= '3.9'", - "version": "==1.11.2" + "markers": "python_version >= '3.9'", + "version": "==1.11.4" }, "setuptools": { "hashes": [ - "sha256:4ac1475276d2f1c48684874089fefcd83bd7162ddaafb81fac866ba0db282a87", - "sha256:b454a35605876da60632df1a60f736524eb73cc47bbc9f3f1ef1b644de74fd2a" + "sha256:385eb4edd9c9d5c17540511303e39a147ce2fc04bc55289c322b9e5904fe2c05", + "sha256:be1af57fc409f93647f2e8e4573a142ed38724b8cdd389706a867bb4efcf1e78" ], "markers": "python_version >= '3.8'", - "version": "==68.2.2" + "version": "==69.0.3" }, "shapely": { "hashes": [ - "sha256:01224899ff692a62929ef1a3f5fe389043e262698a708ab7569f43a99a48ae82", - "sha256:05c51a29336e604c084fb43ae5dbbfa2c0ef9bd6fedeae0a0d02c7b57a56ba46", - "sha256:09d6c7763b1bee0d0a2b84bb32a4c25c6359ad1ac582a62d8b211e89de986154", - "sha256:193a398d81c97a62fc3634a1a33798a58fd1dcf4aead254d080b273efbb7e3ff", - "sha256:1a34a23d6266ca162499e4a22b79159dc0052f4973d16f16f990baa4d29e58b6", - "sha256:2569a4b91caeef54dd5ae9091ae6f63526d8ca0b376b5bb9fd1a3195d047d7d4", - "sha256:33403b8896e1d98aaa3a52110d828b18985d740cc9f34f198922018b1e0f8afe", - "sha256:3ad81f292fffbd568ae71828e6c387da7eb5384a79db9b4fde14dd9fdeffca9a", - "sha256:3cb256ae0c01b17f7bc68ee2ffdd45aebf42af8992484ea55c29a6151abe4386", - "sha256:45b4833235b90bc87ee26c6537438fa77559d994d2d3be5190dd2e54d31b2820", - "sha256:4641325e065fd3e07d55677849c9ddfd0cf3ee98f96475126942e746d55b17c8", - "sha256:502e0a607f1dcc6dee0125aeee886379be5242c854500ea5fd2e7ac076b9ce6d", - "sha256:66a6b1a3e72ece97fc85536a281476f9b7794de2e646ca8a4517e2e3c1446893", - "sha256:70a18fc7d6418e5aea76ac55dce33f98e75bd413c6eb39cfed6a1ba36469d7d4", - "sha256:7d3bbeefd8a6a1a1017265d2d36f8ff2d79d0162d8c141aa0d37a87063525656", - "sha256:83a8ec0ee0192b6e3feee9f6a499d1377e9c295af74d7f81ecba5a42a6b195b7", - "sha256:865bc3d7cc0ea63189d11a0b1120d1307ed7a64720a8bfa5be2fde5fc6d0d33f", - "sha256:90cfa4144ff189a3c3de62e2f3669283c98fb760cfa2e82ff70df40f11cadb39", - "sha256:91575d97fd67391b85686573d758896ed2fc7476321c9d2e2b0c398b628b961c", - "sha256:9a6ac34c16f4d5d3c174c76c9d7614ec8fe735f8f82b6cc97a46b54f386a86bf", - "sha256:a529218e72a3dbdc83676198e610485fdfa31178f4be5b519a8ae12ea688db14", - "sha256:a70a614791ff65f5e283feed747e1cc3d9e6c6ba91556e640636bbb0a1e32a71", - "sha256:ac1dfc397475d1de485e76de0c3c91cc9d79bd39012a84bb0f5e8a199fc17bef", - "sha256:b06d031bc64149e340448fea25eee01360a58936c89985cf584134171e05863f", - "sha256:b4f0711cc83734c6fad94fc8d4ec30f3d52c1787b17d9dca261dc841d4731c64", - "sha256:b50c401b64883e61556a90b89948297f1714dbac29243d17ed9284a47e6dd731", - "sha256:b519cf3726ddb6c67f6a951d1bb1d29691111eaa67ea19ddca4d454fbe35949c", - "sha256:bca57b683e3d94d0919e2f31e4d70fdfbb7059650ef1b431d9f4e045690edcd5", - "sha256:c43755d2c46b75a7b74ac6226d2cc9fa2a76c3263c5ae70c195c6fb4e7b08e79", - "sha256:c7eed1fb3008a8a4a56425334b7eb82651a51f9e9a9c2f72844a2fb394f38a6c", - "sha256:c8b0d834b11be97d5ab2b4dceada20ae8e07bcccbc0f55d71df6729965f406ad", - "sha256:ce88ec79df55430e37178a191ad8df45cae90b0f6972d46d867bf6ebbb58cc4d", - "sha256:d173d24e85e51510e658fb108513d5bc11e3fd2820db6b1bd0522266ddd11f51", - "sha256:d8f55f355be7821dade839df785a49dc9f16d1af363134d07eb11e9207e0b189", - "sha256:da71de5bf552d83dcc21b78cc0020e86f8d0feea43e202110973987ffa781c21", - "sha256:e55698e0ed95a70fe9ff9a23c763acfe0bf335b02df12142f74e4543095e9a9b", - "sha256:f32a748703e7bf6e92dfa3d2936b2fbfe76f8ce5f756e24f49ef72d17d26ad02", - "sha256:f470a130d6ddb05b810fc1776d918659407f8d025b7f56d2742a596b6dffa6c7" + "sha256:03e63a99dfe6bd3beb8d5f41ec2086585bb969991d603f9aeac335ad396a06d4", + "sha256:0521d76d1e8af01e712db71da9096b484f081e539d4f4a8c97342e7971d5e1b4", + "sha256:06f193091a7c6112fc08dfd195a1e3846a64306f890b151fa8c63b3e3624202c", + "sha256:084b023dae8ad3d5b98acee9d3bf098fdf688eb0bb9b1401e8b075f6a627b611", + "sha256:1713cc04c171baffc5b259ba8531c58acc2a301707b7f021d88a15ed090649e7", + "sha256:1f217d28ecb48e593beae20a0082a95bd9898d82d14b8fcb497edf6bff9a44d7", + "sha256:2d217e56ae067e87b4e1731d0dc62eebe887ced729ba5c2d4590e9e3e9fdbd88", + "sha256:34eac2337cbd67650248761b140d2535855d21b969d76d76123317882d3a0c1a", + "sha256:36480e32c434d168cdf2f5e9862c84aaf4d714a43a8465ae3ce8ff327f0affb7", + "sha256:394e5085b49334fd5b94fa89c086edfb39c3ecab7f669e8b2a4298b9d523b3a5", + "sha256:42997ac806e4583dad51c80a32d38570fd9a3d4778f5e2c98f9090aa7db0fe91", + "sha256:45ac6906cff0765455a7b49c1670af6e230c419507c13e2f75db638c8fc6f3bd", + "sha256:4ef753200cbffd4f652efb2c528c5474e5a14341a473994d90ad0606522a46a2", + "sha256:5324be299d4c533ecfcfd43424dfd12f9428fd6f12cda38a4316da001d6ef0ea", + "sha256:5b0c052709c8a257c93b0d4943b0b7a3035f87e2d6a8ac9407b6a992d206422f", + "sha256:6a21353d28209fb0d8cc083e08ca53c52666e0d8a1f9bbe23b6063967d89ed24", + "sha256:6ca8cffbe84ddde8f52b297b53f8e0687bd31141abb2c373fd8a9f032df415d6", + "sha256:72b5997272ae8c25f0fd5b3b967b3237e87fab7978b8d6cd5fa748770f0c5d68", + "sha256:737dba15011e5a9b54a8302f1748b62daa207c9bc06f820cd0ad32a041f1c6f2", + "sha256:78128357a0cee573257a0c2c388d4b7bf13cb7dbe5b3fe5d26d45ebbe2a39e25", + "sha256:794affd80ca0f2c536fc948a3afa90bd8fb61ebe37fe873483ae818e7f21def4", + "sha256:7e92e7c255f89f5cdf777690313311f422aa8ada9a3205b187113274e0135cd8", + "sha256:87dc2be34ac3a3a4a319b963c507ac06682978a5e6c93d71917618b14f13066e", + "sha256:94ac128ae2ab4edd0bffcd4e566411ea7bdc738aeaf92c32a8a836abad725f9f", + "sha256:a5533a925d8e211d07636ffc2fdd9a7f9f13d54686d00577eeb11d16f00be9c4", + "sha256:a9a41ff4323fc9d6257759c26eb1cf3a61ebc7e611e024e6091f42977303fd3a", + "sha256:b8eb0a92f7b8c74f9d8fdd1b40d395113f59bd8132ca1348ebcc1f5aece94b96", + "sha256:baa14fc27771e180c06b499a0a7ba697c7988c7b2b6cba9a929a19a4d2762de3", + "sha256:be46d5509b9251dd9087768eaf35a71360de6afac82ce87c636990a0871aa18b", + "sha256:c6fd29fbd9cd76350bd5cc14c49de394a31770aed02d74203e23b928f3d2f1aa", + "sha256:ccfd5fa10a37e67dbafc601c1ddbcbbfef70d34c3f6b0efc866ddbdb55893a6c", + "sha256:d41a116fcad58048d7143ddb01285e1a8780df6dc1f56c3b1e1b7f12ed296651", + "sha256:dc9342fc82e374130db86a955c3c4525bfbf315a248af8277a913f30911bed9e", + "sha256:dea9a0651333cf96ef5bb2035044e3ad6a54f87d90e50fe4c2636debf1b77abc", + "sha256:e7c95d3379ae3abb74058938a9fcbc478c6b2e28d20dace38f8b5c587dde90aa", + "sha256:e7d897e6bdc6bc64f7f65155dbbb30e49acaabbd0d9266b9b4041f87d6e52b3a", + "sha256:ea84d1cdbcf31e619d672b53c4532f06253894185ee7acb8ceb78f5f33cbe033", + "sha256:ed1e99702125e7baccf401830a3b94d810d5c70b329b765fe93451fe14cf565b", + "sha256:eebe544df5c018134f3c23b6515877f7e4cd72851f88a8d0c18464f414d141a2", + "sha256:fa3ee28f5e63a130ec5af4dc3c4cb9c21c5788bb13c15e89190d163b14f9fb89", + "sha256:fd3ad17b64466a033848c26cb5b509625c87d07dcf39a1541461cacdb8f7e91c" ], "index": "pypi", - "version": "==2.0.1" + "version": "==2.0.2" }, "six": { "hashes": [ @@ -1288,19 +1353,19 @@ }, "typing-extensions": { "hashes": [ - "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0", - "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef" + "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783", + "sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd" ], "markers": "python_version >= '3.8'", - "version": "==4.8.0" + "version": "==4.9.0" }, "uvicorn": { "hashes": [ - "sha256:1f9be6558f01239d4fdf22ef8126c39cb1ad0addf76c40e760549d2c2f43ab53", - "sha256:4d3cc12d7727ba72b64d12d3cc7743124074c0a69f7b201512fc50c3e3f1569a" + "sha256:6dddbad1d7ee0f5140aba5ec138ddc9612c5109399903828b4874c9937f009c2", + "sha256:ce107f5d9bd02b4636001a77a4e74aab5e1e2b146868ebbad565237145af444c" ], "index": "pypi", - "version": "==0.23.2" + "version": "==0.25.0" }, "xmltodict": { "hashes": [ @@ -1322,11 +1387,11 @@ }, "pycodestyle": { "hashes": [ - "sha256:259bcc17857d8a8b3b4a2327324b79e5f020a13c16074670f9c8c8f872ea76d0", - "sha256:5d1013ba8dc7895b548be5afb05740ca82454fd899971563d2ef625d090326f8" + "sha256:41ba0e7afc9752dfb53ced5489e89f8186be00e599e712660695b7a75ff2663f", + "sha256:44fe31000b2d866f2e41841b18528a505fbd7fef9017b04eff4e2648a0fadc67" ], "markers": "python_version >= '3.8'", - "version": "==2.11.0" + "version": "==2.11.1" } } } diff --git a/api/v1/countries.py b/api/v1/countries.py index 2e655c4..188d4df 100644 --- a/api/v1/countries.py +++ b/api/v1/countries.py @@ -4,7 +4,7 @@ import anyio from anyio.streams.memory import MemoryObjectSendStream from fastapi import APIRouter, Path, Request, Response -from shapely.geometry import Point, mapping +from shapely.geometry import mapping from middlewares.cache_middleware import configure_cache from models.country import Country @@ -21,7 +21,12 @@ async def _count_aed_in_country(country: Country, aed_state: AEDState, send_stre @router.get('/names') @configure_cache(timedelta(hours=1), stale=timedelta(days=7)) -async def get_names(request: Request, country_state: CountryStateDep, aed_state: AEDStateDep): +async def get_names( + request: Request, + country_state: CountryStateDep, + aed_state: AEDStateDep, + language: str | None = None, +): countries = await country_state.get_all_countries() send_stream, receive_stream = anyio.create_memory_object_stream() @@ -34,24 +39,39 @@ async def get_names(request: Request, country_state: CountryStateDep, aed_state: for _ in range(len(countries)): country, count = await receive_stream.receive() country_count_map[country.name] = count + + def limit_country_names(names: dict[str, str]): + if language and (name := names.get(language)): + return {language: name} + return names + return [ { 'country_code': country.code, - 'country_names': country.names, + 'country_names': limit_country_names(country.names), 'feature_count': country_count_map[country.name], 'data_path': f'/api/v1/countries/{country.code}.geojson', - } for country in countries - ] + [{ - 'country_code': 'WORLD', - 'country_names': {'default': 'World'}, - 'feature_count': sum(country_count_map.values()), - 'data_path': '/api/v1/countries/WORLD.geojson', - }] + } + for country in countries + ] + [ + { + 'country_code': 'WORLD', + 'country_names': {'default': 'World'}, + 'feature_count': sum(country_count_map.values()), + 'data_path': '/api/v1/countries/WORLD.geojson', + } + ] @router.get('/{country_code}.geojson') @configure_cache(timedelta(hours=1), stale=timedelta(seconds=0)) -async def get_geojson(request: Request, response: Response, country_code: Annotated[str, Path(min_length=2, max_length=5)], country_state: CountryStateDep, aed_state: AEDStateDep): +async def get_geojson( + request: Request, + response: Response, + country_code: Annotated[str, Path(min_length=2, max_length=5)], + country_state: CountryStateDep, + aed_state: AEDStateDep, +): if country_code == 'WORLD': aeds = await aed_state.get_all_aeds() else: @@ -64,12 +84,9 @@ async def get_geojson(request: Request, response: Response, country_code: Annota 'features': [ { 'type': 'Feature', - 'geometry': mapping(Point(*aed.position)), - 'properties': { - '@osm_type': 'node', - '@osm_id': int(aed.id), - **aed.tags - } - } for aed in aeds - ] + 'geometry': mapping(aed.position.shapely), + 'properties': {'@osm_type': 'node', '@osm_id': int(aed.id), **aed.tags}, + } + for aed in aeds + ], } diff --git a/api/v1/node.py b/api/v1/node.py index 9c815a8..d1b2654 100644 --- a/api/v1/node.py +++ b/api/v1/node.py @@ -47,10 +47,10 @@ async def get_node(node_id: str, aed_state: AEDStateDep, photo_state: PhotoState # TODO: support other image sources if ( - (image_url := aed.tags.get('image', '')) and - (photo_id_match := photo_id_re.search(image_url)) and - (photo_id := photo_id_match.group('id')) and - (photo_info := await photo_state.get_photo_by_id(photo_id)) + (image_url := aed.tags.get('image', '')) + and (photo_id_match := photo_id_re.search(image_url)) + and (photo_id := photo_id_match.group('id')) + and (photo_info := await photo_state.get_photo_by_id(photo_id)) ): photo_dict = { '@photo_id': photo_info.id, @@ -67,14 +67,16 @@ async def get_node(node_id: str, aed_state: AEDStateDep, photo_state: PhotoState 'copyright': 'OpenStreetMap and contributors', 'attribution': 'https://www.openstreetmap.org/copyright', 'license': 'https://opendatacommons.org/licenses/odbl/1-0/', - 'elements': [{ - **photo_dict, - **timezone_dict, - 'type': 'node', - 'id': int(aed.id), - 'lat': aed.position.lat, - 'lon': aed.position.lon, - 'tags': aed.tags, - 'version': 0, - }] + 'elements': [ + { + **photo_dict, + **timezone_dict, + 'type': 'node', + 'id': int(aed.id), + 'lat': aed.position.lat, + 'lon': aed.position.lon, + 'tags': aed.tags, + 'version': 0, + } + ], } diff --git a/api/v1/photos.py b/api/v1/photos.py index bc6c7dd..4af971a 100644 --- a/api/v1/photos.py +++ b/api/v1/photos.py @@ -1,11 +1,9 @@ -import traceback from datetime import UTC, datetime, timedelta from typing import Annotated import magic import orjson -from fastapi import (APIRouter, File, Form, HTTPException, Request, Response, - UploadFile) +from fastapi import APIRouter, File, Form, HTTPException, Request, Response, UploadFile from fastapi.responses import FileResponse from feedgen.feed import FeedGenerator @@ -32,7 +30,15 @@ async def view(request: Request, id: str, photo_state: PhotoStateDep) -> FileRes @router.post('/upload') -async def upload(request: Request, node_id: Annotated[str, Form()], file_license: Annotated[str, Form()], file: Annotated[UploadFile, File()], oauth2_credentials: Annotated[str, Form()], aed_state: AEDStateDep, photo_state: PhotoStateDep) -> bool: +async def upload( + request: Request, + node_id: Annotated[str, Form()], + file_license: Annotated[str, Form()], + file: Annotated[UploadFile, File()], + oauth2_credentials: Annotated[str, Form()], + aed_state: AEDStateDep, + photo_state: PhotoStateDep, +) -> bool: file_license = file_license.upper() accept_licenses = ('CC0',) @@ -50,8 +56,8 @@ async def upload(request: Request, node_id: Annotated[str, Form()], file_license try: oauth2_credentials_ = orjson.loads(oauth2_credentials) - except Exception: - raise HTTPException(400, 'OAuth2 credentials must be a JSON object') + except Exception as e: + raise HTTPException(400, 'OAuth2 credentials must be a JSON object') from e if 'access_token' not in oauth2_credentials_: raise HTTPException(400, 'OAuth2 credentials must contain an access_token field') @@ -75,22 +81,32 @@ async def upload(request: Request, node_id: Annotated[str, Form()], file_license node_xml = await osm.get_node_xml(node_id) - osm_change = update_node_tags_osm_change(node_xml, { - 'image': photo_url, - 'image:license': file_license, - }) + osm_change = update_node_tags_osm_change( + node_xml, + { + 'image': photo_url, + 'image:license': file_license, + }, + ) await osm.upload_osm_change(osm_change) return True @router.post('/report') -async def report(id: Annotated[str, Form()], photo_report_state: PhotoReportStateDep) -> bool: +async def report( + id: Annotated[str, Form()], + photo_report_state: PhotoReportStateDep, +) -> bool: return await photo_report_state.report_by_photo_id(id) @router.get('/report/rss.xml') -async def report_rss(request: Request, photo_state: PhotoStateDep, photo_report_state: PhotoReportStateDep) -> Response: +async def report_rss( + request: Request, + photo_state: PhotoStateDep, + photo_report_state: PhotoReportStateDep, +) -> Response: fg = FeedGenerator() fg.title('AED Photo Reports') fg.description('This feed contains a list of recent AED photo reports') @@ -105,10 +121,15 @@ async def report_rss(request: Request, photo_state: PhotoStateDep, photo_report_ fe = fg.add_entry(order='append') fe.id(report.id) fe.title('🚨 Received photo report') - fe.content('
'.join(( - f'File name: {info.path.name}', - f'Node: https://osm.org/node/{info.node_id}', - )), type='CDATA') + fe.content( + '
'.join( + ( + f'File name: {info.path.name}', + f'Node: https://osm.org/node/{info.node_id}', + ) + ), + type='CDATA', + ) fe.link(href=upgrade_https(f'{request.base_url}api/v1/photos/view/{report.photo_id}.webp')) fe.published(datetime.utcfromtimestamp(report.timestamp).astimezone(tz=UTC)) diff --git a/api/v1/tile.py b/api/v1/tile.py index b75e343..ac0a7be 100644 --- a/api/v1/tile.py +++ b/api/v1/tile.py @@ -1,25 +1,30 @@ -import math +from collections.abc import Sequence from itertools import chain -from typing import Annotated, Sequence +from typing import Annotated import anyio import mapbox_vector_tile as mvt import numpy as np from anyio.streams.memory import MemoryObjectSendStream -from fastapi import APIRouter, Path, Query, Response -from numba import njit -from shapely.geometry import Point +from fastapi import APIRouter, Path, Response from shapely.ops import transform -from config import (DEFAULT_CACHE_MAX_AGE, MVT_EXTENT, MVT_TRANSFORMER, - TILE_AEDS_CACHE_STALE, TILE_COUNTRIES_CACHE_MAX_AGE, - TILE_COUNTRIES_CACHE_STALE, TILE_COUNTRIES_MAX_Z, - TILE_MAX_Z, TILE_MIN_Z) +from config import ( + DEFAULT_CACHE_MAX_AGE, + MVT_EXTENT, + MVT_TRANSFORMER, + TILE_AEDS_CACHE_STALE, + TILE_COUNTRIES_CACHE_MAX_AGE, + TILE_COUNTRIES_CACHE_STALE, + TILE_COUNTRIES_MAX_Z, + TILE_MAX_Z, + TILE_MIN_Z, +) +from cython_lib.geo_utils import tile_to_bbox from middlewares.cache_middleware import make_cache_control from models.aed import AED from models.bbox import BBox from models.country import Country -from models.lonlat import LonLat from states.aed_state import AEDState, AEDStateDep from states.country_state import CountryState, CountryStateDep from utils import abbreviate, print_run_time @@ -27,21 +32,6 @@ router = APIRouter() -@njit(fastmath=True) -def _tile_to_lonlat(z: int, x: int, y: int) -> tuple[float, float]: - n = 2.0 ** z - lon_deg = x / n * 360.0 - 180.0 - lat_rad = math.atan(math.sinh(math.pi * (1 - 2 * y / n))) - lat_deg = math.degrees(lat_rad) - return lon_deg, lat_deg - - -def _tile_to_bbox(z: int, x: int, y: int) -> BBox: - p1_lon, p1_lat = _tile_to_lonlat(z, x, y) - p2_lon, p2_lat = _tile_to_lonlat(z, x + 1, y + 1) - return BBox(LonLat(p1_lon, p2_lat), LonLat(p2_lon, p1_lat)) - - async def _count_aed_in_country(country: Country, aed_state: AEDState, send_stream: MemoryObjectSendStream) -> None: count = await aed_state.count_aeds_by_country_code(country.code) await send_stream.send((country, count)) @@ -67,17 +57,18 @@ def _mvt_encode(bbox: BBox, data: Sequence[dict]) -> bytes: for feature in chain.from_iterable(d['features'] for d in data): feature['geometry'] = transform( func=lambda x, y: _mvt_rescale(x, y, x_min, y_min, x_span, y_span), - geom=feature['geometry']) + geom=feature['geometry'], + ) with print_run_time('Encoding MVT'): return mvt.encode(data, default_options={'extents': MVT_EXTENT}) -async def _get_tile_country(z: int, bbox: BBox, lang: str, country_state: CountryState, aed_state: AEDState) -> bytes: +async def _get_tile_country(z: int, bbox: BBox, country_state: CountryState, aed_state: AEDState) -> bytes: with print_run_time('Querying countries'): countries = await country_state.get_countries_within(bbox) - simplify_tol = 0.5 / 2 ** z if z < TILE_MAX_Z else None + simplify_tol = 0.5 / 2**z if z < TILE_MAX_Z else None geometries = (country.geometry.simplify(simplify_tol, preserve_topology=False) for country in countries) send_stream, receive_stream = anyio.create_memory_object_stream() @@ -92,77 +83,88 @@ async def _get_tile_country(z: int, bbox: BBox, lang: str, country_state: Countr country, count = await receive_stream.receive() country_count_map[country.name] = (count, abbreviate(count)) - return _mvt_encode(bbox, [{ - 'name': 'countries', - 'features': [ + return _mvt_encode( + bbox, + [ { - 'geometry': geometry, - 'properties': { - 'country_name': country.get_name(lang), - 'country_code': country.code, - 'point_count': country_count_map[country.name][0], - 'point_count_abbreviated': country_count_map[country.name][1], - }, - } for country, geometry in zip(countries, geometries) - ], - }, { - 'name': 'defibrillators', - 'features': [ + 'name': 'countries', + 'features': [ + { + 'geometry': geometry, + 'properties': {}, + } + for geometry in geometries + ], + }, { - 'geometry': Point(*country.label.position), - 'properties': { - 'country_name': country.get_name(lang), - 'country_code': country.code, - 'point_count': country_count_map[country.name][0], - 'point_count_abbreviated': country_count_map[country.name][1], - }, - } for country in countries - ] - }]) + 'name': 'defibrillators', + 'features': [ + { + 'geometry': country.label.position.shapely, + 'properties': { + 'country_name': country.name, + 'country_code': country.code, + 'point_count': country_count_map[country.name][0], + 'point_count_abbreviated': country_count_map[country.name][1], + }, + } + for country in countries + ], + }, + ], + ) async def _get_tile_aed(z: int, bbox: BBox, aed_state: AEDState) -> bytes: - group_eps = 9.8 / 2 ** z if z < TILE_MAX_Z else None + group_eps = 9.8 / 2**z if z < TILE_MAX_Z else None aeds = await aed_state.get_aeds_within(bbox.extend(0.5), group_eps) - return _mvt_encode(bbox, [{ - 'name': 'defibrillators', - 'features': [ + return _mvt_encode( + bbox, + [ { - 'geometry': Point(*aed.position), - 'properties': { - 'node_id': int(aed.id), - 'access': aed.access, - }, - } if isinstance(aed, AED) else { - 'geometry': Point(*aed.position), - 'properties': { - 'point_count': aed.count, - 'point_count_abbreviated': abbreviate(aed.count), - 'access': aed.access, - }, - } for aed in aeds - ] - }]) + 'name': 'defibrillators', + 'features': [ + { + 'geometry': aed.position.shapely, + 'properties': { + 'node_id': int(aed.id), + 'access': aed.access, + }, + } + if isinstance(aed, AED) + else { + 'geometry': aed.position.shapely, + 'properties': { + 'point_count': aed.count, + 'point_count_abbreviated': abbreviate(aed.count), + 'access': aed.access, + }, + } + for aed in aeds + ], + } + ], + ) @router.get('/tile/{z}/{x}/{y}.mvt') async def get_tile( - z: Annotated[int, Path(ge=TILE_MIN_Z, le=TILE_MAX_Z)], - x: Annotated[int, Path(ge=0)], - y: Annotated[int, Path(ge=0)], - country_state: CountryStateDep, - aed_state: AEDStateDep, - lang: Annotated[str, Query(min_length=2, max_length=2)] = 'default'): - bbox = _tile_to_bbox(z, x, y) + z: Annotated[int, Path(ge=TILE_MIN_Z, le=TILE_MAX_Z)], + x: Annotated[int, Path(ge=0)], + y: Annotated[int, Path(ge=0)], + country_state: CountryStateDep, + aed_state: AEDStateDep, +): + bbox = tile_to_bbox(z, x, y) assert bbox.p1.lon <= bbox.p2.lon, f'{bbox.p1.lon=} <= {bbox.p2.lon=}' assert bbox.p1.lat <= bbox.p2.lat, f'{bbox.p1.lat=} <= {bbox.p2.lat=}' if z <= TILE_COUNTRIES_MAX_Z: - bytes = await _get_tile_country(z, bbox, lang, country_state, aed_state) + content = await _get_tile_country(z, bbox, country_state, aed_state) headers = {'Cache-Control': make_cache_control(TILE_COUNTRIES_CACHE_MAX_AGE, TILE_COUNTRIES_CACHE_STALE)} else: - bytes = await _get_tile_aed(z, bbox, aed_state) + content = await _get_tile_aed(z, bbox, aed_state) headers = {'Cache-Control': make_cache_control(DEFAULT_CACHE_MAX_AGE, TILE_AEDS_CACHE_STALE)} - return Response(bytes, headers=headers, media_type='application/vnd.mapbox-vector-tile') + return Response(content, headers=headers, media_type='application/vnd.mapbox-vector-tile') diff --git a/config.py b/config.py index 7d0e023..cff523a 100644 --- a/config.py +++ b/config.py @@ -18,7 +18,9 @@ OVERPASS_API_URL = 'https://overpass-api.de/api/interpreter' OPENSTREETMAP_API_URL = os.getenv('OPENSTREETMAP_API_URL', 'https://api.openstreetmap.org/api/0.6/') REPLICATION_URL = 'https://planet.openstreetmap.org/replication/minute/' -COUNTRIES_GEOJSON_URL = 'https://raw.githubusercontent.com/Zaczero/osm-countries-geojson/main/geojson/osm-countries-0-01.geojson.br' +COUNTRIES_GEOJSON_URL = ( + 'https://raw.githubusercontent.com/Zaczero/osm-countries-geojson/main/geojson/osm-countries-0-01.geojson.br' +) DEFAULT_CACHE_MAX_AGE = timedelta(minutes=1) @@ -74,22 +76,30 @@ async def startup_setup() -> None: await DATA_DIR.mkdir(exist_ok=True) await PHOTOS_DIR.mkdir(exist_ok=True) - await COUNTRY_COLLECTION.create_indexes([ - IndexModel([('geometry', pymongo.GEOSPHERE)]), - ]) - - await AED_COLLECTION.create_indexes([ - IndexModel([('id', pymongo.ASCENDING)], unique=True), - IndexModel([('country_codes', pymongo.ASCENDING)]), - IndexModel([('position', pymongo.GEOSPHERE)]), - ]) - - await PHOTO_COLLECTION.create_indexes([ - IndexModel([('id', pymongo.ASCENDING)], unique=True), - IndexModel([('node_id', pymongo.ASCENDING), ('timestamp', pymongo.DESCENDING)]), - ]) - - await PHOTO_REPORT_COLLECTION.create_indexes([ - IndexModel([('photo_id', pymongo.ASCENDING)], unique=True), - IndexModel([('timestamp', pymongo.DESCENDING)]), - ]) + await COUNTRY_COLLECTION.create_indexes( + [ + IndexModel([('geometry', pymongo.GEOSPHERE)]), + ] + ) + + await AED_COLLECTION.create_indexes( + [ + IndexModel([('id', pymongo.ASCENDING)], unique=True), + IndexModel([('country_codes', pymongo.ASCENDING)]), + IndexModel([('position', pymongo.GEOSPHERE)]), + ] + ) + + await PHOTO_COLLECTION.create_indexes( + [ + IndexModel([('id', pymongo.ASCENDING)], unique=True), + IndexModel([('node_id', pymongo.ASCENDING), ('timestamp', pymongo.DESCENDING)]), + ] + ) + + await PHOTO_REPORT_COLLECTION.create_indexes( + [ + IndexModel([('photo_id', pymongo.ASCENDING)], unique=True), + IndexModel([('timestamp', pymongo.DESCENDING)]), + ] + ) diff --git a/cython_lib/geo_utils.py b/cython_lib/geo_utils.py new file mode 100644 index 0000000..6d2eaba --- /dev/null +++ b/cython_lib/geo_utils.py @@ -0,0 +1,33 @@ +import cython + +from models.bbox import BBox +from models.lonlat import LonLat + +if cython.compiled: + from cython.cimports.libc.math import atan, pi, sinh + + print(f'{__name__}: 🐇 compiled') +else: + from math import atan, pi, sinh + + print(f'{__name__}: 🐌 not compiled') + + +@cython.cfunc +def _degrees(radians: cython.double) -> cython.double: + return radians * 180 / pi + + +@cython.cfunc +def _tile_to_lonlat(z: cython.int, x: cython.int, y: cython.int) -> tuple[cython.double, cython.double]: + n: cython.double = 2**z + lon_deg: cython.double = x / n * 360.0 - 180.0 + lat_rad: cython.double = atan(sinh(pi * (1 - 2 * y / n))) + lat_deg: cython.double = _degrees(lat_rad) + return lon_deg, lat_deg + + +def tile_to_bbox(z: cython.int, x: cython.int, y: cython.int) -> BBox: + p1_lon, p1_lat = _tile_to_lonlat(z, x, y) + p2_lon, p2_lat = _tile_to_lonlat(z, x + 1, y + 1) + return BBox(LonLat(p1_lon, p2_lat), LonLat(p2_lon, p1_lat)) diff --git a/default.nix b/default.nix index fc69311..8a61308 100644 --- a/default.nix +++ b/default.nix @@ -1,10 +1,14 @@ -{ pkgs ? import { } }: +{ pkgsnix ? import ./pkgs.nix +, pkgs ? pkgsnix.pkgs +, unstable ? pkgsnix.unstable +}: with pkgs; let envTag = builtins.getEnv "TAG"; shell = import ./shell.nix { inherit pkgs; + inherit unstable; isDocker = true; }; @@ -31,11 +35,11 @@ dockerTools.buildLayeredImage { cp "${./.}"/LICENSE . cp "${./.}"/Makefile . cp "${./.}"/*.py . - mkdir -p api/v1 middlewares models states - cp "${./api/v1}"/*.py api/v1 - cp "${./middlewares}"/*.py middlewares - cp "${./models}"/*.py models - cp "${./states}"/*.py states + cp -r "${./.}"/api . + cp -r "${./.}"/cython_lib . + cp -r "${./.}"/middlewares . + cp -r "${./.}"/models . + cp -r "${./.}"/states . ${shell.shellHook} ''; diff --git a/docker-compose.yml b/docker-compose.yml index 0f0afbf..eec49b4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -56,7 +56,7 @@ services: MONGO_HOST: db volumes: - - /mnt/data/aed/${TAG:-dev}/photos:/app/data/photos + - /mnt/data/${TAG:-dev}/photos:/app/data/photos cache: image: varnish:alpine diff --git a/main.py b/main.py index 7f0adc2..1bb31cb 100644 --- a/main.py +++ b/main.py @@ -1,57 +1,57 @@ +from contextlib import asynccontextmanager from datetime import timedelta import anyio from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.gzip import GZipMiddleware +from starlette.middleware.base import BaseHTTPMiddleware import api.v1.api as api from config import DEFAULT_CACHE_MAX_AGE, DEFAULT_CACHE_STALE, startup_setup from middlewares.cache_middleware import CacheMiddleware -from middlewares.version_middleware import VersionMiddleware +from middlewares.profiler_middleware import profiler_middleware +from middlewares.version_middleware import version_middleware from orjson_response import CustomORJSONResponse from states.aed_state import get_aed_state from states.country_state import get_country_state from states.worker_state import WorkerStateEnum, get_worker_state -app = FastAPI(default_response_class=CustomORJSONResponse) -app.include_router(api.router, prefix='/api/v1') -app.add_middleware(VersionMiddleware) -app.add_middleware( - CacheMiddleware, - max_age=DEFAULT_CACHE_MAX_AGE, - stale=DEFAULT_CACHE_STALE -) -app.add_middleware( - CORSMiddleware, - allow_origins=['*'], - allow_methods=['GET'], - max_age=int(timedelta(days=1).total_seconds()) -) -app.add_middleware(GZipMiddleware, compresslevel=6) - -app_tg = anyio.create_task_group() - -@app.on_event('startup') -async def startup(): +@asynccontextmanager +async def lifespan(app: FastAPI): worker_state = get_worker_state() await worker_state.ainit() if worker_state.is_primary: await startup_setup() - await app_tg.__aenter__() async with anyio.create_task_group() as tg: - tg.start_soon(app_tg.start, get_country_state().update_db_task) - tg.start_soon(app_tg.start, get_aed_state().update_db_task) - await worker_state.set_state(WorkerStateEnum.RUNNING) + await tg.start(get_country_state().update_db_task) + await tg.start(get_aed_state().update_db_task) + + await worker_state.set_state(WorkerStateEnum.RUNNING) + yield + + # on shutdown, always abort the tasks + tg.cancel_scope.cancel() else: await worker_state.wait_for_state(WorkerStateEnum.RUNNING) + yield -@app.on_event('shutdown') -async def shutdown(): - worker_state = get_worker_state() - - if worker_state.is_primary: - await app_tg.cancel_scope.cancel() +app = FastAPI(lifespan=lifespan, default_response_class=CustomORJSONResponse) +app.include_router(api.router, prefix='/api/v1') +app.add_middleware(BaseHTTPMiddleware, dispatch=profiler_middleware) +app.add_middleware(BaseHTTPMiddleware, dispatch=version_middleware) +app.add_middleware( + CacheMiddleware, + max_age=DEFAULT_CACHE_MAX_AGE, + stale=DEFAULT_CACHE_STALE, +) +app.add_middleware( + CORSMiddleware, + allow_origins=['*'], + allow_methods=['GET'], + max_age=int(timedelta(days=1).total_seconds()), +) +app.add_middleware(GZipMiddleware, compresslevel=6) diff --git a/middlewares/cache_middleware.py b/middlewares/cache_middleware.py index 347f6cd..e71779b 100644 --- a/middlewares/cache_middleware.py +++ b/middlewares/cache_middleware.py @@ -44,5 +44,7 @@ async def wrapper(*args, **kwargs): request.state.max_age = max_age request.state.stale = stale return await func(*args, **kwargs) + return wrapper + return decorator diff --git a/middlewares/profiler_middleware.py b/middlewares/profiler_middleware.py new file mode 100644 index 0000000..19f1b2e --- /dev/null +++ b/middlewares/profiler_middleware.py @@ -0,0 +1,16 @@ +from fastapi import Request +from pyinstrument import Profiler +from starlette.responses import HTMLResponse + + +# https://pyinstrument.readthedocs.io/en/latest/guide.html#profile-a-web-request-in-fastapi +async def profiler_middleware(request: Request, call_next): + profiling = request.query_params.get('profile', False) + if profiling: + profiler = Profiler() + profiler.start() + await call_next(request) + profiler.stop() + return HTMLResponse(profiler.output_html()) + else: + return await call_next(request) diff --git a/middlewares/version_middleware.py b/middlewares/version_middleware.py index 47564e8..718c979 100644 --- a/middlewares/version_middleware.py +++ b/middlewares/version_middleware.py @@ -1,11 +1,9 @@ from fastapi import Request -from starlette.middleware.base import BaseHTTPMiddleware from config import VERSION -class VersionMiddleware(BaseHTTPMiddleware): - async def dispatch(self, request: Request, call_next): - response = await call_next(request) - response.headers['X-Version'] = VERSION - return response +async def version_middleware(request: Request, call_next): + response = await call_next(request) + response.headers['X-Version'] = VERSION + return response diff --git a/models/aed_group.py b/models/aed_group.py index dec71f8..58f75a3 100644 --- a/models/aed_group.py +++ b/models/aed_group.py @@ -1,6 +1,5 @@ +from collections.abc import Iterable from dataclasses import dataclass -from math import inf -from typing import Iterable from models.lonlat import LonLat @@ -23,13 +22,13 @@ def decide_access(accesses: Iterable[str]) -> str: 'no': 5, } - min_access = '', inf + min_access = '', float('inf') for access in accesses: if access == 'yes': return 'yes' # early stopping - tier = tiered.get(access, inf) + tier = tiered.get(access, float('inf')) if tier < min_access[1]: min_access = access, tier diff --git a/models/bbox.py b/models/bbox.py index 210ffba..89d0716 100644 --- a/models/bbox.py +++ b/models/bbox.py @@ -1,5 +1,6 @@ +from collections.abc import Sequence from itertools import chain -from typing import NamedTuple, Self, Sequence +from typing import NamedTuple, Self from shapely.geometry import Polygon @@ -21,9 +22,7 @@ def extend(self, percentage: float) -> Self: new_p2_lon = max(-180, min(180, self.p2.lon + lon_delta)) new_p2_lat = max(-90, min(90, self.p2.lat + lat_delta)) - return BBox( - LonLat(new_p1_lon, new_p1_lat), - LonLat(new_p2_lon, new_p2_lat)) + return BBox(LonLat(new_p1_lon, new_p1_lat), LonLat(new_p2_lon, new_p2_lat)) @classmethod def from_tuple(cls, bbox: tuple[float, float, float, float]) -> Self: @@ -34,13 +33,15 @@ def to_tuple(self) -> tuple[float, float, float, float]: def to_polygon(self, *, nodes_per_edge: int = 2) -> Polygon: if nodes_per_edge <= 2: - return Polygon([ - (self.p1.lon, self.p1.lat), - (self.p2.lon, self.p1.lat), - (self.p2.lon, self.p2.lat), - (self.p1.lon, self.p2.lat), - (self.p1.lon, self.p1.lat) - ]) + return Polygon( + [ + (self.p1.lon, self.p1.lat), + (self.p2.lon, self.p1.lat), + (self.p2.lon, self.p2.lat), + (self.p1.lon, self.p2.lat), + (self.p1.lon, self.p1.lat), + ] + ) x_interval = (self.p2.lon - self.p1.lon) / (nodes_per_edge - 1) y_interval = (self.p2.lat - self.p1.lat) / (nodes_per_edge - 1) @@ -54,8 +55,6 @@ def to_polygon(self, *, nodes_per_edge: int = 2) -> Polygon: def correct_for_dateline(self) -> Sequence[Self]: if self.p1.lon > self.p2.lon: - return ( - BBox(self.p1, LonLat(180, self.p2.lat)), - BBox(LonLat(-180, self.p1.lat), self.p2)) + return (BBox(self.p1, LonLat(180, self.p2.lat)), BBox(LonLat(-180, self.p1.lat), self.p2)) else: return (self,) diff --git a/models/country.py b/models/country.py index 46675f2..9e9b0c1 100644 --- a/models/country.py +++ b/models/country.py @@ -1,6 +1,6 @@ from dataclasses import dataclass -from shapely.geometry import MultiPolygon, Polygon +from shapely.geometry.base import BaseGeometry from models.lonlat import LonLat @@ -14,7 +14,7 @@ class CountryLabel: class Country: names: dict[str, str] code: str - geometry: MultiPolygon | Polygon + geometry: BaseGeometry label: CountryLabel @property diff --git a/models/lonlat.py b/models/lonlat.py index de3e1e9..8836254 100644 --- a/models/lonlat.py +++ b/models/lonlat.py @@ -1,5 +1,7 @@ from dataclasses import dataclass +from shapely import Point + @dataclass(frozen=True, slots=True) class LonLat: @@ -8,3 +10,7 @@ class LonLat: def __iter__(self): return iter((self.lon, self.lat)) + + @property + def shapely(self) -> Point: + return Point(self.lon, self.lat) diff --git a/models/osm_country.py b/models/osm_country.py index 797b08f..cb60c9e 100644 --- a/models/osm_country.py +++ b/models/osm_country.py @@ -1,10 +1,11 @@ from typing import NamedTuple -from shapely.geometry import MultiPolygon, Point, Polygon +from shapely.geometry import Point +from shapely.geometry.base import BaseGeometry class OSMCountry(NamedTuple): tags: dict[str, str] timestamp: float representative_point: Point - geometry: Polygon | MultiPolygon + geometry: BaseGeometry diff --git a/openstreetmap.py b/openstreetmap.py index 1caadf5..75c90da 100644 --- a/openstreetmap.py +++ b/openstreetmap.py @@ -3,8 +3,7 @@ import xmltodict from authlib.integrations.httpx_client import OAuth2Auth -from config import (CHANGESET_ID_PLACEHOLDER, DEFAULT_CHANGESET_TAGS, - OPENSTREETMAP_API_URL) +from config import CHANGESET_ID_PLACEHOLDER, DEFAULT_CHANGESET_TAGS, OPENSTREETMAP_API_URL from utils import get_http_client, retry_exponential from xmltodict_postprocessor import xmltodict_postprocessor @@ -44,21 +43,39 @@ async def get_node_xml(self, node_id: str) -> dict | None: )['osm']['node'] async def upload_osm_change(self, osm_change: str) -> str: - changeset = xmltodict.unparse({'osm': {'changeset': {'tag': [ - {'@k': k, '@v': v} - for k, v in DEFAULT_CHANGESET_TAGS.items() - ]}}}) - - r = await self._http.put('/changeset/create', content=changeset, headers={ - 'Content-Type': 'text/xml; charset=utf-8'}, follow_redirects=False) + changeset = xmltodict.unparse( + { + 'osm': { + 'changeset': { + 'tag': [ + { + '@k': k, + '@v': v, + } + for k, v in DEFAULT_CHANGESET_TAGS.items() + ] + } + } + } + ) + + r = await self._http.put( + '/changeset/create', + content=changeset, + headers={'Content-Type': 'text/xml; charset=utf-8'}, + follow_redirects=False, + ) r.raise_for_status() changeset_id = r.text osm_change = osm_change.replace(CHANGESET_ID_PLACEHOLDER, changeset_id) print(f'🌐 Changeset: https://www.openstreetmap.org/changeset/{changeset_id}') - upload_resp = await self._http.post(f'/changeset/{changeset_id}/upload', content=osm_change, headers={ - 'Content-Type': 'text/xml; charset=utf-8'}) + upload_resp = await self._http.post( + f'/changeset/{changeset_id}/upload', + content=osm_change, + headers={'Content-Type': 'text/xml; charset=utf-8'}, + ) r = await self._http.put(f'/changeset/{changeset_id}/close') r.raise_for_status() diff --git a/osm_countries.py b/osm_countries.py index ceb6abd..dd0800b 100644 --- a/osm_countries.py +++ b/osm_countries.py @@ -1,4 +1,4 @@ -from typing import Sequence +from collections.abc import Sequence import brotli import orjson @@ -24,11 +24,13 @@ async def get_osm_countries() -> Sequence[OSMCountry]: props = feature['properties'] geometry = feature['geometry'] - result.append(OSMCountry( - tags=props['tags'], - timestamp=props['timestamp'], - representative_point=shape(props['representative_point']), - geometry=shape(geometry) - )) + result.append( + OSMCountry( + tags=props['tags'], + timestamp=props['timestamp'], + representative_point=shape(props['representative_point']), + geometry=shape(geometry), + ) + ) return tuple(result) diff --git a/overpass.py b/overpass.py index d555180..fc82bad 100644 --- a/overpass.py +++ b/overpass.py @@ -1,11 +1,8 @@ -from datetime import UTC, datetime, timedelta -from typing import Iterable, Sequence - -import xmltodict +from collections.abc import Iterable, Sequence +from datetime import UTC, datetime from config import OVERPASS_API_URL from utils import get_http_client, retry_exponential -from xmltodict_postprocessor import xmltodict_postprocessor def _extract_center(elements: Iterable[dict]) -> None: @@ -36,17 +33,18 @@ async def query_overpass(query: str, *, timeout: int, must_return: bool = False) query = f'[out:json][timeout:{timeout}]{join}{query}' async with get_http_client() as http: - r = await http.post( - OVERPASS_API_URL, - data={'data': query}, - timeout=timeout * 2) + r = await http.post(OVERPASS_API_URL, data={'data': query}, timeout=timeout * 2) r.raise_for_status() data = r.json() - data_timestamp = datetime \ - .strptime(data['osm3s']['timestamp_osm_base'], '%Y-%m-%dT%H:%M:%SZ') \ - .replace(tzinfo=UTC) \ + data_timestamp = ( + datetime.strptime( + data['osm3s']['timestamp_osm_base'], + '%Y-%m-%dT%H:%M:%SZ', + ) + .replace(tzinfo=UTC) .timestamp() + ) if must_return and not data['elements']: raise Exception('No elements returned') diff --git a/pkgs.nix b/pkgs.nix new file mode 100644 index 0000000..673f2e3 --- /dev/null +++ b/pkgs.nix @@ -0,0 +1,5 @@ +{ + # check latest hashes at https://status.nixos.org/ + pkgs = import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/4d644e746a64e03cae79645287b1f7d19145f152.tar.gz") { }; + unstable = import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/d6863cbcbbb80e71cecfc03356db1cda38919523.tar.gz") { }; +} diff --git a/planet_diffs.py b/planet_diffs.py index df56b14..f375b1a 100644 --- a/planet_diffs.py +++ b/planet_diffs.py @@ -1,10 +1,9 @@ import gzip import re +from collections.abc import Sequence from datetime import UTC, datetime -from heapq import heappush from itertools import chain from operator import itemgetter -from typing import Sequence import anyio import xmltodict @@ -18,7 +17,7 @@ def _format_sequence_number(sequence_number: int) -> str: result = f'{sequence_number:09d}' - result = '/'.join(result[i:i + 3] for i in range(0, 9, 3)) + result = '/'.join(result[i : i + 3] for i in range(0, 9, 3)) return result @@ -59,9 +58,11 @@ async def _get_planet_diff(http: AsyncClient, sequence_number: int, send_stream: xml_gz = r.content xml = gzip.decompress(xml_gz).decode() xml = _format_actions(xml) - actions: list[dict] = xmltodict.parse(xml, - postprocessor=xmltodict_postprocessor, - force_list=('action', 'node', 'way', 'relation', 'member', 'tag', 'nd'))['osmChange']['action'] + actions: list[dict] = xmltodict.parse( + xml, + postprocessor=xmltodict_postprocessor, + force_list=('action', 'node', 'way', 'relation', 'member', 'tag', 'nd'), + )['osmChange']['action'] node_actions = [] diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..1e716d6 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,113 @@ +[tool.ruff] +# Exclude a variety of commonly ignored directories. +exclude = [ + ".bzr", + ".direnv", + ".eggs", + ".git", + ".git-rewrite", + ".hg", + ".mypy_cache", + ".nox", + ".pants.d", + ".pytype", + ".ruff_cache", + ".svn", + ".tox", + ".venv", + "__pypackages__", + "_build", + "buck-out", + "build", + "dist", + "node_modules", + "venv", +] + +indent-width = 4 +line-length = 120 +target-version = "py311" + +[tool.ruff.lint] +ignore = [ + "ARG001", # unused argument + "S101", # assert statements + "S108", # hardcoded temp file +] +select = [ + # see https://docs.astral.sh/ruff/rules/ for rules documentation + "A", # flake8-builtins + "ARG", # flake8-unused-arguments + "ASYNC", # flake8-async + "B", # flake8-bugbear + # "COM", # flake8-commas + "C4", # flake8-comprehensions + "E4", # pycodestyle + "E7", + "E9", + "F", # pyflakes + # "FBT", # flake8-boolean-trap + "FLY", # flynt + # "FURB", # refurb (preview) + "G", # flake8-logging-format + "I", # isort + "INT", # flake8-gettext + # "LOG", # flake8-logging (preview) + "N", # pep8-naming + "NPY", # numpy + "UP", # pyupgrade + "Q", # flake8-quotes + "PERF", # perflint + "PGH", # pygrep-hooks + "PIE", # flake8-pie + # "PL", # pylint + "PT", # flake8-pytest-style + "PTH", # flake8-use-pathlib + "PYI", # flake8-pyi + "RSE", # flake8-raise + "RUF", # ruff + "S", # flake8-bandit + "SIM", # flake8-simplify + "SLF", # flake8-self + "SLOT", # flake8-slots + "T10", # flake8-debugger + # "T20", # flake8-print + # "TRY", # tryceratops + "YTT", # flake8-2020 +] + +# Allow fix for all enabled rules (when `--fix`) is provided. +fixable = ["ALL"] +unfixable = [] + +# Allow unused variables when underscore-prefixed. +dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" + +[tool.ruff.format] +quote-style = "single" + +# Like Black, indent with spaces, rather than tabs. +indent-style = "space" + +# Like Black, respect magic trailing commas. +skip-magic-trailing-comma = false + +# Like Black, automatically detect the appropriate line ending. +line-ending = "lf" + +[tool.ruff.lint.flake8-builtins] +builtins-ignorelist = ["id", "open", "type", "filter", "format"] + +[tool.ruff.lint.flake8-gettext] +extend-function-names = ["pgettext", "npgettext"] + +[tool.ruff.lint.flake8-quotes] +docstring-quotes = "double" +inline-quotes = "single" +multiline-quotes = "double" + +[tool.ruff.lint.pep8-naming] +extend-ignore-names = ["ET"] + +[tool.ruff.lint.pylint] +max-args = 10 diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..488a4c8 --- /dev/null +++ b/setup.py @@ -0,0 +1,31 @@ +import Cython.Compiler.Options as Options +from Cython.Build import cythonize +from setuptools import Extension, setup + +Options.docstrings = False +Options.annotate = True + +setup( + ext_modules=cythonize( + [ + Extension( + '*', + ['cython_lib/*.py'], + extra_compile_args=[ + '-march=x86-64', + '-ffast-math', + '-fopenmp', + '-flto=auto', + ], + extra_link_args=[ + '-fopenmp', + '-flto=auto', + ], + ), + ], + compiler_directives={ + # https://cython.readthedocs.io/en/latest/src/userguide/source_files_and_compilation.html#compiler-directives + 'language_level': 3, + }, + ), +) diff --git a/shell.nix b/shell.nix index 7d22ca2..2b1fc65 100644 --- a/shell.nix +++ b/shell.nix @@ -1,4 +1,6 @@ -{ pkgs ? import { } +{ pkgsnix ? import ./pkgs.nix +, pkgs ? pkgsnix.pkgs +, unstable ? pkgsnix.unstable , isDocker ? false }: @@ -11,8 +13,8 @@ with pkgs; let devBuildInputs = [ gnumake - gnused pipenv + ruff ]; commonShellHook = '' @@ -22,6 +24,7 @@ with pkgs; let export LD_LIBRARY_PATH="${lib.makeLibraryPath commonBuildInputs}" export PIPENV_VENV_IN_PROJECT=1 export PIPENV_VERBOSITY=-1 + [ ! -e .venv/bin/python ] && [ -h .venv/bin/python ] && rm -r .venv [ ! -f .venv/bin/activate ] && pipenv sync --dev case $- in *i*) exec pipenv shell --fancy;; esac ''; diff --git a/states/aed_state.py b/states/aed_state.py index 6469dc6..2866945 100644 --- a/states/aed_state.py +++ b/states/aed_state.py @@ -1,5 +1,6 @@ +from collections.abc import Iterable, Sequence from time import time -from typing import Annotated, Counter, Iterable, NoReturn, Sequence +from typing import Annotated, NoReturn import anyio from asyncache import cached @@ -11,8 +12,7 @@ from sklearn.cluster import Birch from tqdm import tqdm -from config import (AED_COLLECTION, AED_REBUILD_THRESHOLD, AED_UPDATE_DELAY, - VERSION_TIMESTAMP) +from config import AED_COLLECTION, AED_REBUILD_THRESHOLD, AED_UPDATE_DELAY from models.aed import AED from models.aed_group import AEDGroup from models.bbox import BBox @@ -23,10 +23,7 @@ from transaction import Transaction from utils import as_dict, print_run_time, retry_exponential -_QUERY = ( - 'node[emergency=defibrillator];' - 'out body qt;' -) +_AED_QUERY = 'node[emergency=defibrillator];out body qt;' async def _should_update_db() -> tuple[bool, float]: @@ -51,35 +48,41 @@ def _is_defibrillator(tags: dict[str, str]) -> bool: async def _assign_country_codes(aeds: Sequence[AED]) -> None: from states.country_state import get_country_state + country_state = get_country_state() - bulk_write_args = [] if len(aeds) < 100: + bulk_write_args = [] for aed in aeds: countries = await country_state.get_countries_within(aed.position) - country_codes = tuple(set(c.code for c in countries)) - bulk_write_args.append( - UpdateOne( - {'id': aed.id}, - {'$set': {'country_codes': country_codes}})) + country_codes = tuple({c.code for c in countries}) + bulk_write_args.append(UpdateOne({'id': aed.id}, {'$set': {'country_codes': country_codes}})) else: countries = await country_state.get_all_countries() id_codes_map = {aed.id: set() for aed in aeds} for country in tqdm(countries, desc='📫 Iterating over countries'): - async for c in AED_COLLECTION.find({ - '$and': [ - {'id': {'$in': tuple(id_codes_map)}}, - {'position': {'$geoIntersects': {'$geometry': mapping(country.geometry)}}}, - ] - }): + async for c in AED_COLLECTION.find( + { + '$and': [ + {'id': {'$in': tuple(id_codes_map)}}, + {'position': {'$geoIntersects': {'$geometry': mapping(country.geometry)}}}, + ] + } + ): id_codes_map[c['id']].add(country.code) - for aed in aeds: - bulk_write_args.append( - UpdateOne( - {'id': aed.id}, - {'$set': {'country_codes': tuple(id_codes_map[aed.id])}})) + bulk_write_args = [ + UpdateOne( + {'id': aed.id}, + { + '$set': { + 'country_codes': tuple(id_codes_map[aed.id]), + } + }, + ) + for aed in aeds + ] if bulk_write_args: await AED_COLLECTION.bulk_write(bulk_write_args, ordered=False) @@ -89,16 +92,12 @@ def _process_overpass_node(node: dict) -> AED: tags = node.get('tags', {}) is_valid = _is_defibrillator(tags) assert is_valid, 'Unexpected non-defibrillator node' - return AED( - id=str(node['id']), - position=LonLat(node['lon'], node['lat']), - country_codes=None, - tags=tags) + return AED(id=str(node['id']), position=LonLat(node['lon'], node['lat']), country_codes=None, tags=tags) async def _update_db_snapshot() -> None: print('🩺 Updating aed database (overpass)...') - elements, data_timestamp = await query_overpass(_QUERY, timeout=3600, must_return=True) + elements, data_timestamp = await query_overpass(_AED_QUERY, timeout=3600, must_return=True) aeds = tuple(_process_overpass_node(e) for e in elements) insert_many_arg = tuple(as_dict(aed) for aed in aeds) @@ -108,7 +107,7 @@ async def _update_db_snapshot() -> None: await set_state_doc('aed', {'update_timestamp': data_timestamp}, session=s) if aeds: - print(f'🩺 Updating country codes') + print('🩺 Updating country codes') await _assign_country_codes(aeds) print(f'🩺 Update complete: ={len(insert_many_arg)}') @@ -129,7 +128,8 @@ def _process_create_or_modify(node: dict) -> AED | str: id=node_id, position=LonLat(float(node['@lon']), float(node['@lat'])), country_codes=None, - tags=node_tags) + tags=node_tags, + ) else: return node_id @@ -163,13 +163,8 @@ async def _update_db_diffs(last_update: float) -> None: else: remove_ids.add(result) - bulk_write_arg = [] - - for aed in aeds: - bulk_write_arg.append(ReplaceOne({'id': aed.id}, as_dict(aed), upsert=True)) - - for remove_id in remove_ids: - bulk_write_arg.append(DeleteOne({'id': remove_id})) + bulk_write_arg = [ReplaceOne({'id': aed.id}, as_dict(aed), upsert=True) for aed in aeds] + bulk_write_arg += [DeleteOne({'id': remove_id}) for remove_id in remove_ids] # keep transaction as short as possible: avoid doing any computation inside async with Transaction() as s: @@ -177,7 +172,7 @@ async def _update_db_diffs(last_update: float) -> None: await set_state_doc('aed', {'update_timestamp': data_timestamp}, session=s) if aeds: - print(f'🩺 Updating country codes') + print('🩺 Updating country codes') await _assign_country_codes(aeds) print(f'🩺 Update complete: +{len(aeds)} -{len(remove_ids)}') @@ -224,7 +219,7 @@ async def get_all_aeds(self, filter: dict | None = None) -> Sequence[AED]: result = [] async for c in cursor: - result.append(from_dict(AED, c)) + result.append(from_dict(AED, c)) # noqa: PERF401 return tuple(result) @@ -235,13 +230,7 @@ async def get_aeds_within(self, bbox: BBox, group_eps: float | None) -> Sequence return await self.get_aeds_within_geom(bbox.to_polygon(), group_eps) async def get_aeds_within_geom(self, geometry, group_eps: float | None) -> Sequence[AED | AEDGroup]: - aeds = await self.get_all_aeds({ - 'position': { - '$geoIntersects': { - '$geometry': mapping(geometry) - } - } - }) + aeds = await self.get_all_aeds({'position': {'$geoIntersects': {'$geometry': mapping(geometry)}}}) if len(aeds) <= 1 or group_eps is None: return aeds @@ -256,10 +245,10 @@ async def get_aeds_within_geom(self, geometry, group_eps: float | None) -> Seque result: list[AED | AEDGroup] = [] cluster_groups: tuple[list[AED]] = tuple([] for _ in range(len(model.subcluster_centers_))) - for aed, cluster in zip(aeds, clusters): + for aed, cluster in zip(aeds, clusters, strict=True): cluster_groups[cluster].append(aed) - for group, center in zip(cluster_groups, model.subcluster_centers_): + for group, center in zip(cluster_groups, model.subcluster_centers_, strict=True): if len(group) == 0: continue @@ -267,10 +256,13 @@ async def get_aeds_within_geom(self, geometry, group_eps: float | None) -> Seque result.append(group[0]) continue - result.append(AEDGroup( - position=LonLat(center[0], center[1]), - count=len(group), - access=AEDGroup.decide_access(aed.access for aed in group))) + result.append( + AEDGroup( + position=LonLat(center[0], center[1]), + count=len(group), + access=AEDGroup.decide_access(aed.access for aed in group), + ) + ) return tuple(result) diff --git a/states/country_state.py b/states/country_state.py index 8ed97f7..5db0de1 100644 --- a/states/country_state.py +++ b/states/country_state.py @@ -1,13 +1,13 @@ -from math import inf +from collections.abc import Sequence from time import time -from typing import Annotated, NoReturn, Sequence +from typing import Annotated, NoReturn import anyio from dacite import from_dict from fastapi import Depends from shapely.geometry import Point, mapping, shape -from config import COUNTRY_COLLECTION, COUNTRY_UPDATE_DELAY, VERSION_TIMESTAMP +from config import COUNTRY_COLLECTION, COUNTRY_UPDATE_DELAY from models.bbox import BBox from models.country import Country, CountryLabel from models.lonlat import LonLat @@ -79,7 +79,7 @@ async def _update_db() -> None: print('🗺️ Updating country database...') osm_countries = await get_osm_countries() - data_timestamp = osm_countries[0].timestamp if osm_countries else -inf + data_timestamp = osm_countries[0].timestamp if osm_countries else float('-inf') if data_timestamp <= update_timestamp: print('🗺️ Nothing to update') @@ -110,6 +110,7 @@ async def _update_db() -> None: print('🗺️ Updating country codes') from states.aed_state import get_aed_state + aed_state = get_aed_state() await aed_state.update_country_codes() @@ -136,21 +137,24 @@ async def get_all_countries(self, filter: dict | None = None) -> Sequence[Countr result = [] async for c in cursor: - result.append(from_dict(Country, {**c, 'geometry': shape(c['geometry'])})) + result.append(from_dict(Country, {**c, 'geometry': shape(c['geometry'])})) # noqa: PERF401 return tuple(result) async def get_countries_within(self, bbox_or_pos: BBox | LonLat) -> Sequence[Country]: - return await self.get_all_countries({ - 'geometry': { - '$geoIntersects': { - '$geometry': mapping( - bbox_or_pos.to_polygon(nodes_per_edge=8) - if isinstance(bbox_or_pos, BBox) else - Point(bbox_or_pos.lon, bbox_or_pos.lat)) + return await self.get_all_countries( + { + 'geometry': { + '$geoIntersects': { + '$geometry': mapping( + bbox_or_pos.to_polygon(nodes_per_edge=8) + if isinstance(bbox_or_pos, BBox) + else Point(bbox_or_pos.lon, bbox_or_pos.lat) + ) + } } } - }) + ) _instance = CountryState() diff --git a/states/photo_report_state.py b/states/photo_report_state.py index 560da0e..86d36a5 100644 --- a/states/photo_report_state.py +++ b/states/photo_report_state.py @@ -1,8 +1,8 @@ import secrets +from collections.abc import Sequence from time import time -from typing import Annotated, Sequence +from typing import Annotated -import anyio import pymongo from dacite import from_dict from fastapi import Depends @@ -24,33 +24,36 @@ async def report_by_photo_id(self, photo_id: str) -> bool: if await PHOTO_REPORT_COLLECTION.find_one({'photo_id': photo_id}, projection={'_id': False}): return False # already reported - await PHOTO_REPORT_COLLECTION.insert_one(as_dict(PhotoReport( - id=secrets.token_urlsafe(16), - photo_id=photo_id, - timestamp=time(), - ))) + await PHOTO_REPORT_COLLECTION.insert_one( + as_dict( + PhotoReport( + id=secrets.token_urlsafe(16), + photo_id=photo_id, + timestamp=time(), + ) + ) + ) return True async def get_recent_reports(self, count: int = 10) -> Sequence[PhotoReport]: - cursor = PHOTO_REPORT_COLLECTION \ - .find(projection={'_id': False}) \ - .sort('timestamp', pymongo.DESCENDING) \ - .limit(count) + cursor = ( + PHOTO_REPORT_COLLECTION.find(projection={'_id': False}).sort('timestamp', pymongo.DESCENDING).limit(count) + ) result = [] async for c in cursor: - result.append(from_dict(PhotoReport, c)) + result.append(from_dict(PhotoReport, c)) # noqa: PERF401 return tuple(result) -_instance=PhotoReportState() +_instance = PhotoReportState() def get_photo_report_state() -> PhotoReportState: return _instance -PhotoReportStateDep=Annotated[PhotoReportState, Depends(get_photo_report_state)] +PhotoReportStateDep = Annotated[PhotoReportState, Depends(get_photo_report_state)] diff --git a/states/photo_state.py b/states/photo_state.py index 5a61f0c..5f21a3f 100644 --- a/states/photo_state.py +++ b/states/photo_state.py @@ -91,9 +91,10 @@ async def get_photo_by_id(self, id: str, *, check_file: bool = True) -> PhotoInf return info async def get_photo_by_node_id(self, node_id: str) -> PhotoInfo | None: - cursor = PHOTO_COLLECTION \ - .find({'node_id': node_id}, projection={'_id': False}) \ - .sort('timestamp', pymongo.DESCENDING) + cursor = PHOTO_COLLECTION.find( + {'node_id': node_id}, + projection={'_id': False}, + ).sort('timestamp', pymongo.DESCENDING) async for c in cursor: info = from_dict(PhotoInfo, c) diff --git a/utils.py b/utils.py index 7cf9949..430dc75 100644 --- a/utils.py +++ b/utils.py @@ -1,15 +1,14 @@ import functools import time import traceback +from collections.abc import Generator from contextlib import contextmanager from dataclasses import asdict from datetime import timedelta -from math import atan2, cos, inf, pi, radians, sin, sqrt -from typing import Any, Generator +from typing import Any import anyio import httpx -from numba import njit from shapely.geometry import mapping from config import USER_AGENT @@ -32,10 +31,7 @@ def print_run_time(message: str | list) -> Generator[None, None, None]: def retry_exponential(timeout: timedelta | None, *, start: float = 1): - if timeout is None: - timeout_seconds = inf - else: - timeout_seconds = timeout.total_seconds() + timeout_seconds = float('inf') if timeout is None else timeout.total_seconds() def decorator(func): @functools.wraps(func) @@ -55,6 +51,7 @@ async def wrapper(*args, **kwargs): sleep = min(sleep * 2, 4 * 3600) # max 4 hours return wrapper + return decorator @@ -91,47 +88,3 @@ def as_dict(data) -> dict: d[k] = mapping(v) return d - - -EARTH_RADIUS = 6371000 -CIRCUMFERENCE = 2 * pi * EARTH_RADIUS - - -@njit(fastmath=True) -def meters_to_lat(meters: float) -> float: - return meters / (CIRCUMFERENCE / 360) - - -@njit(fastmath=True) -def meters_to_lon(meters: float, lat: float) -> float: - return meters / ((CIRCUMFERENCE / 360) * cos(radians(lat))) - - -@njit(fastmath=True) -def lat_to_meters(lat: float) -> float: - return lat * (CIRCUMFERENCE / 360) - - -@njit(fastmath=True) -def lon_to_meters(lon: float, lat: float) -> float: - return lon * ((CIRCUMFERENCE / 360) * cos(radians(lat))) - - -@njit(fastmath=True) -def radians_tuple(p: tuple[float, float]) -> tuple[float, float]: - return (radians(p[0]), radians(p[1])) - - -@njit(fastmath=True) -def haversine_distance(p1: tuple[float, float], p2: tuple[float, float]) -> float: - p1_lat, p1_lon = radians_tuple(p1) - p2_lat, p2_lon = radians_tuple(p2) - - dlat = p2_lat - p1_lat - dlon = p2_lon - p1_lon - - a = sin(dlat / 2)**2 + cos(p1_lat) * cos(p2_lat) * sin(dlon / 2)**2 - c = 2 * atan2(sqrt(a), sqrt(1 - a)) - - # distance in meters - return c * EARTH_RADIUS