From 02ac4d4eef3f18a9870e83b4d06c61b1fcefd174 Mon Sep 17 00:00:00 2001 From: MarcelGeo Date: Mon, 28 Sep 2026 13:14:33 +0200 Subject: [PATCH 01/20] Upgrade FE to fix security: - vite to 6.x version from 5 needs to be checked --- web-app/package.json | 6 +- web-app/packages/admin-app/package.json | 2 +- web-app/packages/admin-lib/package.json | 4 +- .../admin-lib/src/modules/admin/store.ts | 8 +- web-app/packages/admin-lib/vite.config.ts | 4 +- web-app/packages/app/package.json | 2 +- web-app/packages/lib/package.json | 2 +- web-app/packages/lib/vite.config.ts | 4 +- web-app/yarn.lock | 911 ++++++++++-------- 9 files changed, 511 insertions(+), 432 deletions(-) diff --git a/web-app/package.json b/web-app/package.json index 241a0eed..87c208c4 100755 --- a/web-app/package.json +++ b/web-app/package.json @@ -44,7 +44,7 @@ "@esbuild-plugins/node-modules-polyfill": "^0.2.2", "@typescript-eslint/eslint-plugin": "^8.11.0", "@typescript-eslint/parser": "^8.11.0", - "@vitejs/plugin-vue": "^5.1.4", + "@vitejs/plugin-vue": "^5.2.4", "@vue/eslint-config-typescript": "^13.0.0", "agent-base": "^6.0.2", "autoprefixer": "^10.4.23", @@ -65,8 +65,8 @@ "tsc-alias": "^1.8.6", "typescript": "^5.6.3", "unplugin-vue-components": "^0.27.1", - "vite": "^5.4.21", - "vite-plugin-static-copy": "^2.0.0", + "vite": "^6.4.3", + "vite-plugin-static-copy": "^2.3.2", "vue-tsc": "^2.1.6" }, "engines": { diff --git a/web-app/packages/admin-app/package.json b/web-app/packages/admin-app/package.json index 08fea4d7..bced0fa1 100644 --- a/web-app/packages/admin-app/package.json +++ b/web-app/packages/admin-app/package.json @@ -19,7 +19,7 @@ }, "dependencies": { "@tabler/icons-webfont": "^2.42.0", - "axios": "^0.30.0", + "axios": "^0.34.0", "lodash": "^4.17.21", "pinia": "^2.1.7", "primeflex": "^3.3.1", diff --git a/web-app/packages/admin-lib/package.json b/web-app/packages/admin-lib/package.json index 5cae27b4..4cd61fea 100644 --- a/web-app/packages/admin-lib/package.json +++ b/web-app/packages/admin-lib/package.json @@ -40,13 +40,13 @@ "lint": "eslint . --ext .js,.vue,.ts" }, "dependencies": { - "axios": "^0.30.0", + "axios": "^0.34.0", "axios-retry": "^3.2.4", "lodash": "^4.17.21", "pinia": "^2.1.7", "primeflex": "^3.3.1", "primevue": "3.43.0", - "universal-cookie": "^4.0.4", + "universal-cookie": "^7.2.2", "vue": "3.5.12" }, "peerDependencies": { diff --git a/web-app/packages/admin-lib/src/modules/admin/store.ts b/web-app/packages/admin-lib/src/modules/admin/store.ts index 5bf5c5fa..e30837fc 100644 --- a/web-app/packages/admin-lib/src/modules/admin/store.ts +++ b/web-app/packages/admin-lib/src/modules/admin/store.ts @@ -229,7 +229,10 @@ export const useAdminStore = defineStore('adminModule', { }, async getCheckUpdateFromCookies() { - const currentCheckForUpdatesCookie = cookies.get('checkUpdates') + // doNotParse keeps raw 'true' / 'false' strings (universal-cookie >= 7 parses JSON by default) + const currentCheckForUpdatesCookie = cookies.get('checkUpdates', { + doNotParse: true + }) await this.setCheckUpdatesToCookies({ value: currentCheckForUpdatesCookie === undefined @@ -248,7 +251,8 @@ export const useAdminStore = defineStore('adminModule', { async getServerConfiguredCookies() { const currentHideServerConfiguredBannerCookie = cookies.get( - COOKIES_HIDE_SERVER_CONFIGURED_BANNER + COOKIES_HIDE_SERVER_CONFIGURED_BANNER, + { doNotParse: true } ) if (currentHideServerConfiguredBannerCookie === 'true') { this.setIsServerConfigHidden(true) diff --git a/web-app/packages/admin-lib/vite.config.ts b/web-app/packages/admin-lib/vite.config.ts index a7089e0d..2974d7a2 100644 --- a/web-app/packages/admin-lib/vite.config.ts +++ b/web-app/packages/admin-lib/vite.config.ts @@ -44,7 +44,9 @@ export default defineConfig(({ mode }) => ({ entry: resolve(__dirname, 'src/main.ts'), name: 'admin-lib', // the proper extensions will be added - fileName: 'admin-lib' + fileName: 'admin-lib', + // keep Vite 5 name, apps import dist/style.css + cssFileName: 'style' }, rollupOptions: { // make sure to externalize deps that shouldn't be bundled diff --git a/web-app/packages/app/package.json b/web-app/packages/app/package.json index 43de8339..4b79d758 100644 --- a/web-app/packages/app/package.json +++ b/web-app/packages/app/package.json @@ -19,7 +19,7 @@ }, "dependencies": { "@tabler/icons-webfont": "^2.42.0", - "axios": "^0.30.0", + "axios": "^0.34.0", "lodash": "^4.17.21", "pinia": "^2.1.7", "primeflex": "^3.3.1", diff --git a/web-app/packages/lib/package.json b/web-app/packages/lib/package.json index 101c4cc2..7d4e3557 100644 --- a/web-app/packages/lib/package.json +++ b/web-app/packages/lib/package.json @@ -38,7 +38,7 @@ "lint": "eslint . --ext .js,.vue,.ts" }, "dependencies": { - "axios": "^0.30.0", + "axios": "^0.34.0", "axios-retry": "^3.2.4", "crypto-js": "^4.2.0", "date-fns": "^2.28.0", diff --git a/web-app/packages/lib/vite.config.ts b/web-app/packages/lib/vite.config.ts index a11d3825..50e700fb 100644 --- a/web-app/packages/lib/vite.config.ts +++ b/web-app/packages/lib/vite.config.ts @@ -53,7 +53,9 @@ export default defineConfig({ formats: ['es'], entry: resolve(__dirname, 'src/main.ts'), name: 'lib', - fileName: 'lib' + fileName: 'lib', + // keep Vite 5 name, apps import dist/style.css + cssFileName: 'style' }, rollupOptions: { external: ['vue', 'pinia', ...Object.keys(packageJson.dependencies)], diff --git a/web-app/yarn.lock b/web-app/yarn.lock index 7f31032c..39882bc0 100644 --- a/web-app/yarn.lock +++ b/web-app/yarn.lock @@ -24,19 +24,10 @@ dependencies: "@babel/types" "^7.25.9" -"@babel/runtime@^7.15.4": - version "7.21.0" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.0.tgz#5b55c9d394e5fcf304909a8b00c07dc217b56673" - integrity sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw== - dependencies: - regenerator-runtime "^0.13.11" - -"@babel/runtime@^7.21.0": - version "7.22.3" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.3.tgz#0a7fce51d43adbf0f7b517a71f4c3aaca92ebcbb" - integrity sha512-XsDuspWKLUsxwCp6r7EhsExHtYfbe5oAGQ19kqngTdCPUoPQzOPdUbD/pB9PJiwb2ptYKQDjSJT3R6dC+EPqfQ== - dependencies: - regenerator-runtime "^0.13.11" +"@babel/runtime@^7.15.4", "@babel/runtime@^7.21.0": + version "7.29.7" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.29.7.tgz#12022450c45a4da6d8d8287b18a4ff2ddb23f768" + integrity sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw== "@babel/types@^7.25.9": version "7.25.9" @@ -59,120 +50,135 @@ escape-string-regexp "^4.0.0" rollup-plugin-node-polyfills "^0.2.1" -"@esbuild/aix-ppc64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz#c7184a326533fcdf1b8ee0733e21c713b975575f" - integrity sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ== - -"@esbuild/android-arm64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz#09d9b4357780da9ea3a7dfb833a1f1ff439b4052" - integrity sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A== - -"@esbuild/android-arm@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz#9b04384fb771926dfa6d7ad04324ecb2ab9b2e28" - integrity sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg== - -"@esbuild/android-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz#29918ec2db754cedcb6c1b04de8cd6547af6461e" - integrity sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA== - -"@esbuild/darwin-arm64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz#e495b539660e51690f3928af50a76fb0a6ccff2a" - integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ== - -"@esbuild/darwin-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz#c13838fa57372839abdddc91d71542ceea2e1e22" - integrity sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw== - -"@esbuild/freebsd-arm64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz#646b989aa20bf89fd071dd5dbfad69a3542e550e" - integrity sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g== - -"@esbuild/freebsd-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz#aa615cfc80af954d3458906e38ca22c18cf5c261" - integrity sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ== - -"@esbuild/linux-arm64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz#70ac6fa14f5cb7e1f7f887bcffb680ad09922b5b" - integrity sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q== - -"@esbuild/linux-arm@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz#fc6fd11a8aca56c1f6f3894f2bea0479f8f626b9" - integrity sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA== - -"@esbuild/linux-ia32@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz#3271f53b3f93e3d093d518d1649d6d68d346ede2" - integrity sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg== - -"@esbuild/linux-loong64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz#ed62e04238c57026aea831c5a130b73c0f9f26df" - integrity sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg== - -"@esbuild/linux-mips64el@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz#e79b8eb48bf3b106fadec1ac8240fb97b4e64cbe" - integrity sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg== - -"@esbuild/linux-ppc64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz#5f2203860a143b9919d383ef7573521fb154c3e4" - integrity sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w== - -"@esbuild/linux-riscv64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz#07bcafd99322d5af62f618cb9e6a9b7f4bb825dc" - integrity sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA== - -"@esbuild/linux-s390x@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz#b7ccf686751d6a3e44b8627ababc8be3ef62d8de" - integrity sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A== - -"@esbuild/linux-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz#6d8f0c768e070e64309af8004bb94e68ab2bb3b0" - integrity sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ== - -"@esbuild/netbsd-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz#bbe430f60d378ecb88decb219c602667387a6047" - integrity sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg== - -"@esbuild/openbsd-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz#99d1cf2937279560d2104821f5ccce220cb2af70" - integrity sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow== - -"@esbuild/sunos-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz#08741512c10d529566baba837b4fe052c8f3487b" - integrity sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg== - -"@esbuild/win32-arm64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz#675b7385398411240735016144ab2e99a60fc75d" - integrity sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A== - -"@esbuild/win32-ia32@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz#1bfc3ce98aa6ca9a0969e4d2af72144c59c1193b" - integrity sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA== - -"@esbuild/win32-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz#acad351d582d157bb145535db2a6ff53dd514b5c" - integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw== +"@esbuild/aix-ppc64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz#80fcbe36130e58b7670511e888b8e88a259ed76c" + integrity sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA== + +"@esbuild/android-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz#8aa4965f8d0a7982dc21734bf6601323a66da752" + integrity sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg== + +"@esbuild/android-arm@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.12.tgz#300712101f7f50f1d2627a162e6e09b109b6767a" + integrity sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg== + +"@esbuild/android-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.12.tgz#87dfb27161202bdc958ef48bb61b09c758faee16" + integrity sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg== + +"@esbuild/darwin-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz#79197898ec1ff745d21c071e1c7cc3c802f0c1fd" + integrity sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg== + +"@esbuild/darwin-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz#146400a8562133f45c4d2eadcf37ddd09718079e" + integrity sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA== + +"@esbuild/freebsd-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz#1c5f9ba7206e158fd2b24c59fa2d2c8bb47ca0fe" + integrity sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg== + +"@esbuild/freebsd-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz#ea631f4a36beaac4b9279fa0fcc6ca29eaeeb2b3" + integrity sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ== + +"@esbuild/linux-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz#e1066bce58394f1b1141deec8557a5f0a22f5977" + integrity sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ== + +"@esbuild/linux-arm@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz#452cd66b20932d08bdc53a8b61c0e30baf4348b9" + integrity sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw== + +"@esbuild/linux-ia32@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz#b24f8acc45bcf54192c7f2f3be1b53e6551eafe0" + integrity sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA== + +"@esbuild/linux-loong64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz#f9cfffa7fc8322571fbc4c8b3268caf15bd81ad0" + integrity sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng== + +"@esbuild/linux-mips64el@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz#575a14bd74644ffab891adc7d7e60d275296f2cd" + integrity sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw== + +"@esbuild/linux-ppc64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz#75b99c70a95fbd5f7739d7692befe60601591869" + integrity sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA== + +"@esbuild/linux-riscv64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz#2e3259440321a44e79ddf7535c325057da875cd6" + integrity sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w== + +"@esbuild/linux-s390x@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz#17676cabbfe5928da5b2a0d6df5d58cd08db2663" + integrity sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg== + +"@esbuild/linux-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz#0583775685ca82066d04c3507f09524d3cd7a306" + integrity sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw== + +"@esbuild/netbsd-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz#f04c4049cb2e252fe96b16fed90f70746b13f4a4" + integrity sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg== + +"@esbuild/netbsd-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz#77da0d0a0d826d7c921eea3d40292548b258a076" + integrity sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ== + +"@esbuild/openbsd-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz#6296f5867aedef28a81b22ab2009c786a952dccd" + integrity sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A== + +"@esbuild/openbsd-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz#f8d23303360e27b16cf065b23bbff43c14142679" + integrity sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw== + +"@esbuild/openharmony-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz#49e0b768744a3924be0d7fd97dd6ce9b2923d88d" + integrity sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg== + +"@esbuild/sunos-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz#a6ed7d6778d67e528c81fb165b23f4911b9b13d6" + integrity sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w== + +"@esbuild/win32-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz#9ac14c378e1b653af17d08e7d3ce34caef587323" + integrity sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg== + +"@esbuild/win32-ia32@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz#918942dcbbb35cc14fca39afb91b5e6a3d127267" + integrity sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ== + +"@esbuild/win32-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz#9bdad8176be7811ad148d1f8772359041f46c6c5" + integrity sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA== "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": version "4.4.0" @@ -230,6 +236,11 @@ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== +"@napi-rs/lzma-linux-x64-gnu@1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@napi-rs/lzma-linux-x64-gnu/-/lzma-linux-x64-gnu-1.5.1.tgz#e57d4306966078662038094fb38eb9146dc3aea9" + integrity sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ== + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -260,85 +271,130 @@ estree-walker "^2.0.2" picomatch "^4.0.2" -"@rollup/rollup-android-arm-eabi@4.24.0": - version "4.24.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.0.tgz#1661ff5ea9beb362795304cb916049aba7ac9c54" - integrity sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA== - -"@rollup/rollup-android-arm64@4.24.0": - version "4.24.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.0.tgz#2ffaa91f1b55a0082b8a722525741aadcbd3971e" - integrity sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA== - -"@rollup/rollup-darwin-arm64@4.24.0": - version "4.24.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.0.tgz#627007221b24b8cc3063703eee0b9177edf49c1f" - integrity sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA== - -"@rollup/rollup-darwin-x64@4.24.0": - version "4.24.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.0.tgz#0605506142b9e796c370d59c5984ae95b9758724" - integrity sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ== - -"@rollup/rollup-linux-arm-gnueabihf@4.24.0": - version "4.24.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.0.tgz#62dfd196d4b10c0c2db833897164d2d319ee0cbb" - integrity sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA== - -"@rollup/rollup-linux-arm-musleabihf@4.24.0": - version "4.24.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.0.tgz#53ce72aeb982f1f34b58b380baafaf6a240fddb3" - integrity sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw== - -"@rollup/rollup-linux-arm64-gnu@4.24.0": - version "4.24.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.0.tgz#1632990f62a75c74f43e4b14ab3597d7ed416496" - integrity sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA== - -"@rollup/rollup-linux-arm64-musl@4.24.0": - version "4.24.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.0.tgz#8c03a996efb41e257b414b2e0560b7a21f2d9065" - integrity sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw== - -"@rollup/rollup-linux-powerpc64le-gnu@4.24.0": - version "4.24.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.0.tgz#5b98729628d5bcc8f7f37b58b04d6845f85c7b5d" - integrity sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw== - -"@rollup/rollup-linux-riscv64-gnu@4.24.0": - version "4.24.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.0.tgz#48e42e41f4cabf3573cfefcb448599c512e22983" - integrity sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg== - -"@rollup/rollup-linux-s390x-gnu@4.24.0": - version "4.24.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.0.tgz#e0b4f9a966872cb7d3e21b9e412a4b7efd7f0b58" - integrity sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g== - -"@rollup/rollup-linux-x64-gnu@4.24.0": - version "4.24.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.0.tgz#78144741993100f47bd3da72fce215e077ae036b" - integrity sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A== - -"@rollup/rollup-linux-x64-musl@4.24.0": - version "4.24.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.0.tgz#d9fe32971883cd1bd858336bd33a1c3ca6146127" - integrity sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ== - -"@rollup/rollup-win32-arm64-msvc@4.24.0": - version "4.24.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.0.tgz#71fa3ea369316db703a909c790743972e98afae5" - integrity sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ== - -"@rollup/rollup-win32-ia32-msvc@4.24.0": - version "4.24.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.0.tgz#653f5989a60658e17d7576a3996deb3902e342e2" - integrity sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ== - -"@rollup/rollup-win32-x64-msvc@4.24.0": - version "4.24.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.0.tgz#0574d7e87b44ee8511d08cc7f914bcb802b70818" - integrity sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw== +"@rollup/rollup-android-arm-eabi@4.63.5": + version "4.63.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.63.5.tgz#7bb325dcd3430b3d7af484099beed53808b1a5a8" + integrity sha512-J25QJU+B78T4FhhBsNpLJyVWOi31mwtpcMwywHmOKH65Q9IWGA81gPj+dnwlhU8wktVriYE+tFAaQgrnJRzAZg== + +"@rollup/rollup-android-arm64@4.63.5": + version "4.63.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.63.5.tgz#67004291958ef28d2964fc9b6a28356fe54f43a7" + integrity sha512-LDopB3zuZM5Ux9TT2luNEBJW/tYbGU2g1d+VpKk6I+gSKDb+/7sYE6M225gRQt4RbMX6MSwMsVR/phdjVUgRLg== + +"@rollup/rollup-darwin-arm64@4.63.5": + version "4.63.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.63.5.tgz#4716ffe09f8c5b98e283a52cd792b3de2b71676b" + integrity sha512-wlJEERGfeuHeBavCL2qVnNacOK43NDoZM4sjkeRPymd04OAE9T1zBqDJgmZ+CIsPTYKwdzpUC8vmOw84dwY4Tg== + +"@rollup/rollup-darwin-x64@4.63.5": + version "4.63.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.63.5.tgz#2963c46403c7ff0dd733bfddc0896764a01b5b7e" + integrity sha512-4nJJGg5jbo2wwPP4JP+LfEBA3bvP8rU9CLuhp7jWvq9sxEyhjQFTFdrqi+/dHEin/pd8jpT0vcehIpnZtmEdcQ== + +"@rollup/rollup-freebsd-arm64@4.63.5": + version "4.63.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.63.5.tgz#29ae00b822102724aebee73bd093137c28317a78" + integrity sha512-DrZbyCDF1hneuO6jRbvZ2D7+PIBM6yIwYnJpg2vIk58T+wuFpiaGZrfUr59lDWw45bg+IrpTGLPiNi/Fk4w3Cg== + +"@rollup/rollup-freebsd-x64@4.63.5": + version "4.63.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.63.5.tgz#15184a119e4cb040cc293f7213186ec6d0b412a8" + integrity sha512-gqfUVMJMB3mehqywxp6hTBFfgtMQykZY19+cfiaYP0toIJLb/1DZRJHVkQQGP13W4TAwfZDWeg1qBcheTRioXQ== + +"@rollup/rollup-linux-arm-gnueabihf@4.63.5": + version "4.63.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.63.5.tgz#b9bce0674655718695b985dde1eba89cdc592bb1" + integrity sha512-CFmhpvAwzSaWMlN3VN7UtmoTihlZNzoP0juQib5TQRnYUyDV8dXeWOp29sobWAT6gXl/hQgAClLlEiYozQG3OQ== + +"@rollup/rollup-linux-arm-musleabihf@4.63.5": + version "4.63.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.63.5.tgz#381f678b487fb02331fca2dfe2d0ecab173504b0" + integrity sha512-Uc9H8eXCOayV6JLTH5bXKMId6qbhNHa818/BgYjm4jrlq3vZquC9cqyvHBw17xy5Mnj5f+I3gFK5JcEf3hSqrw== + +"@rollup/rollup-linux-arm64-gnu@4.63.5": + version "4.63.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.63.5.tgz#fff99e3aff1ad28fe8506c6fd6e845c7b2848243" + integrity sha512-VcPr/szv/1BFw112Kt//fxulXt/JPqzzidU84iW68L2DdjnOO8QFUv2zTSYBEPHD6movBD4z+bbr5y60GYM7Jw== + +"@rollup/rollup-linux-arm64-musl@4.63.5": + version "4.63.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.63.5.tgz#09256328fe580cc8a029265416ff59be1dfe0161" + integrity sha512-BnxtJ5/91BrIHYIkGrmjz/lbMhqEHt1dPFqIxIFR+jPn0xVc/oUSCtIT089zfp5ufwGDlYz2UC+Fe1SRBpYFbQ== + +"@rollup/rollup-linux-loong64-gnu@4.63.5": + version "4.63.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.63.5.tgz#dfa073286e662ab77ac7ee842fd676433b8d7fd3" + integrity sha512-LrYcHZwF+fAMNKHYTOQ5osWM4AZF7YF6D+XtsjDyEvljtt11twc+zHVXBLNEjxVSUnKYsOhvVz4Z213eW02COQ== + +"@rollup/rollup-linux-loong64-musl@4.63.5": + version "4.63.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.63.5.tgz#2f1209655544f6d15b77da8d24ec28bc8bbc667b" + integrity sha512-nj7QKQePAAUpCpJHtg0pR0W/b92A9NO17JS3BAQmHDn/yhmkir2p8llrKY9TOhleKIaSzy1JhxS3T9FVld6coA== + +"@rollup/rollup-linux-ppc64-gnu@4.63.5": + version "4.63.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.63.5.tgz#e667444abc500697017089bcc8ce32059e4642a1" + integrity sha512-5ylkX6dWMeBKge9nTU+Rxfb+ZfaCIJ9lRqIFaK0eAMcWp7OJbYnLveLgXmm0VrvuLKb8qIK+mHyH0qu88RM+iA== + +"@rollup/rollup-linux-ppc64-musl@4.63.5": + version "4.63.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.63.5.tgz#326d503e7bcd6267936f512c793acc04235b8a6f" + integrity sha512-oHK4ZHYFDKjZviK34I+NwgfbGxgI7ztrNxj2hPTSSNFgeq1a/lEd7dHV2fdGAuTH4Iym3RHJg+vAbWaWG4B7Zg== + +"@rollup/rollup-linux-riscv64-gnu@4.63.5": + version "4.63.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.63.5.tgz#8e33fc5a52b24b943b011b77d89e52cdbc1b2008" + integrity sha512-UcetmHZ6XOXuUByiKZyQmb55ZPr0LABr3Ec/HB9wKZn6CEAFWZkE+hsJErJ9hbPBC7nI0dKuELx7CoV6IM7TMg== + +"@rollup/rollup-linux-riscv64-musl@4.63.5": + version "4.63.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.63.5.tgz#e4dfed2661b104ac1327252517239defd2c2d78f" + integrity sha512-C5CmDPQBtvjVo8cgQsBs+w6WB0JLkiixhgi6hVLV11hERWdn/p0XcPU2OUcZzac9BPOFq7SbaHFa8r3SWEysCQ== + +"@rollup/rollup-linux-s390x-gnu@4.63.5": + version "4.63.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.63.5.tgz#498ded2128f25f098397d7df61033fc9d2aa7305" + integrity sha512-lHVQHJFKsuuxLMi3MQO9XVL8Tje3JR82CzB+QDKC5NWBcsIWuwsn9uIM5e3lBhI+fF1/s63qnyYqsg65+8rV/w== + +"@rollup/rollup-linux-x64-gnu@4.63.5": + version "4.63.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.63.5.tgz#246449b1aa0ba3b9dda84e236547a814f87123cc" + integrity sha512-3W9bTFcQNJn71cSJVM9RKIiZOy8DO/XLDii8Uv/Pm6WKqDRj7JV3ZfuXIEfyuy5LXpIzAbB/1M4Ukp9GKNa7nA== + +"@rollup/rollup-linux-x64-musl@4.63.5": + version "4.63.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.63.5.tgz#c69d3758b6ef054762af9c5c828b5d8e5a246d24" + integrity sha512-VDC7rRJlee/scpki96GZ27Omf6yU87s1YXwVTpjE5841faVlDYYT565rgfmoR1U0sqL7z5ivQSDjcsF6VRXyBA== + +"@rollup/rollup-openbsd-x64@4.63.5": + version "4.63.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.63.5.tgz#52f3baf28fcf841884b976aac44110e68afd115e" + integrity sha512-z86Ok2p4pTdv5xqCKZsTooO7yBEiaJR/HzU3Wx8RmWsPoLppnMKROhJusQob8B3IE1ghC343kUW9rC2r+Wf3ig== + +"@rollup/rollup-openharmony-arm64@4.63.5": + version "4.63.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.63.5.tgz#a0ecc18c2c4505e962aa47102cbfaa57ad45f946" + integrity sha512-IzQmj+xXwQFGhMAMKMQVXkMwMZN3TqkJgAE0nSsqvVwWWciP4AIPMmWRqOQ2GfX7TUDZr+xqGFcBS36CRPGw0g== + +"@rollup/rollup-win32-arm64-msvc@4.63.5": + version "4.63.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.63.5.tgz#eaf0156b1f51f57900ca4072eef3d96bba4b6d68" + integrity sha512-F6qpTaPc9bwBH85kjy0/BLmLSW1uv7AoOXCoRIkg2arlgCYlWYcAbiMkvZuAcaWk9TpCRG//okznLAqLGshkMw== + +"@rollup/rollup-win32-ia32-msvc@4.63.5": + version "4.63.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.63.5.tgz#4cc3fd8848c066a4b96a38537966db9e0ffbb4cf" + integrity sha512-igoDsTFhhwECBeGbUuLeIk7t8Y1apa+cs6mDWpx2EZ0ch7oEQgzHbFUXN9euoHekCAQzXdXApAGkV6jznS7tWw== + +"@rollup/rollup-win32-x64-gnu@4.63.5": + version "4.63.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.63.5.tgz#0930078a2556dab95e2d67bcb52299e9f38e9328" + integrity sha512-U3teMeMbXFmaM5D+OTJpsOXd+wV/qftIeYF9kBKL4v73641qyJmoXFtA28DQLsnmlyayEsTe72xpLHrArq6vHw== + +"@rollup/rollup-win32-x64-msvc@4.63.5": + version "4.63.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.63.5.tgz#66e1eb4e47e993314699bfd03eaa54e36790e8d9" + integrity sha512-ypfC34F3RKXvCXBglGqGMsUSMKlgwd1HX9AOAlx9RoZZ6GaI42YHVeKpzg3JG+wpBUJYTG+NNZhqbDWL8tBZkw== "@rtsao/scc@^1.1.0": version "1.1.0" @@ -357,15 +413,15 @@ resolved "https://registry.yarnpkg.com/@tabler/icons/-/icons-2.42.0.tgz#306a444d18c6cf2966ee9d30262d41da4746fb01" integrity sha512-ynV4iaC1c1mUhuAr9HRaoq8KrWYmZ0bJEpOh7qTBE+OfdDsdvQUe+0S7FW+DHkJ4RuxQMdO8djrZK7HrUw9YMA== -"@types/cookie@^0.3.3": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.3.3.tgz#85bc74ba782fb7aa3a514d11767832b0e3bc6803" - integrity sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow== +"@types/cookie@^0.6.0": + version "0.6.0" + resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.6.0.tgz#eac397f28bf1d6ae0ae081363eca2f425bedf0d5" + integrity sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA== -"@types/estree@1.0.6": - version "1.0.6" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50" - integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== +"@types/estree@1.0.9": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.9.tgz#cf3f0e876d7bee15a93ab925b82bf570a3904a24" + integrity sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg== "@types/estree@^1.0.0": version "1.0.0" @@ -544,10 +600,10 @@ resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== -"@vitejs/plugin-vue@^5.1.4": - version "5.1.4" - resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-5.1.4.tgz#72b8b705cfce36b00b59af196195146e356500c4" - integrity sha512-N2XSI2n3sQqp5w7Y/AN/L2XDjBIRGqXko+eDp42sydYSBeJuSm5a1sLf8zakmo8u7tA8NmBgoDLA1HeOESjp9A== +"@vitejs/plugin-vue@^5.2.4": + version "5.2.4" + resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz#9e8a512eb174bfc2a333ba959bbf9de428d89ad8" + integrity sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA== "@volar/language-core@2.4.6", "@volar/language-core@~2.4.1": version "2.4.6" @@ -857,10 +913,10 @@ axios-retry@^3.2.4: "@babel/runtime" "^7.15.4" is-retry-allowed "^2.2.0" -axios@^0.30.0: - version "0.30.2" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.30.2.tgz#256d3a8ee765cc27188d08b8b545a5f5a0c77dad" - integrity sha512-0pE4RQ4UQi1jKY6p7u6i1Tkzqmu+d+/tHS7Q7rKunWLB9WyilBTpHHpXzPNMDj5hTbK0B0PTLSz07yqMBiF6xg== +axios@^0.34.0: + version "0.34.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.34.0.tgz#8ecc4e5d865e3f36c9dc432ee490a88e8dd009c2" + integrity sha512-CkOmqy7BaT4VC9+wRUmSM3LVwCkKK3UYc7koEqIHWRpOTJypwdNctaVOgnOjhHP3599Ubq2K8KqYwfC7c8NdPQ== dependencies: follow-redirects "^1.15.4" form-data "^4.0.4" @@ -871,10 +927,10 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -baseline-browser-mapping@^2.9.0: - version "2.9.15" - resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.9.15.tgz#6baaa0069883f50a99cdb31b56646491f47c05d7" - integrity sha512-kX8h7K2srmDyYnXRIppo4AH/wYgzWVCs+eKr3RusRSQ5PvRYoEFmR/I0PbdTjKFAoKqp5+kbxnNTFO9jOfSVJg== +baseline-browser-mapping@^2.11.25: + version "2.11.26" + resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.11.26.tgz#01bf6774efb3fbb9de20afc6b923ab85c7d230a6" + integrity sha512-GLQdD3y6UF8iVuMJl5fHgE4jdn/ua7n+toKfLgNlg3BqQtOZjpy68T8Tup8/wGWZCDlm7KMg7tPb4MPn7oN0TQ== binary-extensions@^2.0.0: version "2.2.0" @@ -887,37 +943,37 @@ boolbase@^1.0.0: integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + version "1.1.21" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.21.tgz#edf4fab5c64d051aea5a8def49aba1c7522279f3" + integrity sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw== dependencies: balanced-match "^1.0.0" concat-map "0.0.1" -brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== +brace-expansion@^2.0.1, brace-expansion@^2.0.2: + version "2.1.7" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.1.7.tgz#14ea3836731823bb24740225ea43b941b436f9d1" + integrity sha512-uZbew1NqdmPDTMJ8ah1y+b+9QEJrfkXFk3RcTQw3X0jW/xRUvFKsg1CfQdSYGdTbXZWExtU3J3ccxtnfw1Fi0g== dependencies: balanced-match "^1.0.0" braces@^3.0.2, braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== dependencies: - fill-range "^7.0.1" + fill-range "^7.1.1" browserslist@^4.28.1: - version "4.28.1" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.28.1.tgz#7f534594628c53c63101079e27e40de490456a95" - integrity sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA== + version "4.29.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.29.1.tgz#f723071987a4f094177d94e01f6dc6e7493b972c" + integrity sha512-AUdjuRyCNGUYtqpqfTmWyM4fXay8yIQhmLnvYe/THMGfT9B/34X7xQd3ifKxwyNPPpowVBjLb+64BN9Rn1mizw== dependencies: - baseline-browser-mapping "^2.9.0" - caniuse-lite "^1.0.30001759" - electron-to-chromium "^1.5.263" - node-releases "^2.0.27" - update-browserslist-db "^1.2.0" + baseline-browser-mapping "^2.11.25" + caniuse-lite "^1.0.30001810" + electron-to-chromium "^1.5.438" + node-releases "^2.0.57" + update-browserslist-db "^1.3.3" call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: version "1.0.2" @@ -951,11 +1007,16 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -caniuse-lite@^1.0.30001759, caniuse-lite@^1.0.30001760: +caniuse-lite@^1.0.30001760: version "1.0.30001765" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001765.tgz#4a78d8a797fd4124ebaab2043df942eb091648ee" integrity sha512-LWcNtSyZrakjECqmpP4qdg0MMGdN368D7X8XvvAqOcqMv0RxnlqVKZl2V6/mBR68oYMxOZPLw/gO7DuisMHUvQ== +caniuse-lite@^1.0.30001810: + version "1.0.30001812" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001812.tgz#55b32ed819d120b384149a4f9fd59d179ce008f9" + integrity sha512-qN+QNNBr93TCmFrmte0bBCjSDMuRvt78VlHT99qIGPszm4QsqCX8lnyWUFkHi8B7ZBAPq8SH+UqyXNy/odMdng== + chalk@^2.4.1: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -1078,10 +1139,10 @@ confbox@^0.1.8: resolved "https://registry.yarnpkg.com/confbox/-/confbox-0.1.8.tgz#820d73d3b3c82d9bd910652c5d4d599ef8ff8b06" integrity sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w== -cookie@^0.4.0: - version "0.4.2" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" - integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== +cookie@^0.7.2: + version "0.7.2" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.2.tgz#556369c472a2ba910f2979891b526b3436237ed7" + integrity sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w== cross-spawn@^6.0.5: version "6.0.5" @@ -1249,10 +1310,10 @@ dunder-proto@^1.0.1: es-errors "^1.3.0" gopd "^1.2.0" -electron-to-chromium@^1.5.263: - version "1.5.267" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz#5d84f2df8cdb6bfe7e873706bb21bd4bfb574dc7" - integrity sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw== +electron-to-chromium@^1.5.438: + version "1.5.439" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.439.tgz#d14ad21f157ee83b77d1e46fc031776eec9013c9" + integrity sha512-qu6QIPXhsb+CRcAiTMNjR4A1y/7tCYKkKjr5CZXRVih6qkDf79peZ2BpEU3qoDBNCRrcy3Mra3X9nG5oruuA7Q== emoji-regex@^8.0.0: version "8.0.0" @@ -1444,34 +1505,37 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" -esbuild@^0.21.3: - version "0.21.5" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.21.5.tgz#9ca301b120922959b766360d8ac830da0d02997d" - integrity sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw== +esbuild@^0.25.0: + version "0.25.12" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.12.tgz#97a1d041f4ab00c2fce2f838d2b9969a2d2a97a5" + integrity sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg== optionalDependencies: - "@esbuild/aix-ppc64" "0.21.5" - "@esbuild/android-arm" "0.21.5" - "@esbuild/android-arm64" "0.21.5" - "@esbuild/android-x64" "0.21.5" - "@esbuild/darwin-arm64" "0.21.5" - "@esbuild/darwin-x64" "0.21.5" - "@esbuild/freebsd-arm64" "0.21.5" - "@esbuild/freebsd-x64" "0.21.5" - "@esbuild/linux-arm" "0.21.5" - "@esbuild/linux-arm64" "0.21.5" - "@esbuild/linux-ia32" "0.21.5" - "@esbuild/linux-loong64" "0.21.5" - "@esbuild/linux-mips64el" "0.21.5" - "@esbuild/linux-ppc64" "0.21.5" - "@esbuild/linux-riscv64" "0.21.5" - "@esbuild/linux-s390x" "0.21.5" - "@esbuild/linux-x64" "0.21.5" - "@esbuild/netbsd-x64" "0.21.5" - "@esbuild/openbsd-x64" "0.21.5" - "@esbuild/sunos-x64" "0.21.5" - "@esbuild/win32-arm64" "0.21.5" - "@esbuild/win32-ia32" "0.21.5" - "@esbuild/win32-x64" "0.21.5" + "@esbuild/aix-ppc64" "0.25.12" + "@esbuild/android-arm" "0.25.12" + "@esbuild/android-arm64" "0.25.12" + "@esbuild/android-x64" "0.25.12" + "@esbuild/darwin-arm64" "0.25.12" + "@esbuild/darwin-x64" "0.25.12" + "@esbuild/freebsd-arm64" "0.25.12" + "@esbuild/freebsd-x64" "0.25.12" + "@esbuild/linux-arm" "0.25.12" + "@esbuild/linux-arm64" "0.25.12" + "@esbuild/linux-ia32" "0.25.12" + "@esbuild/linux-loong64" "0.25.12" + "@esbuild/linux-mips64el" "0.25.12" + "@esbuild/linux-ppc64" "0.25.12" + "@esbuild/linux-riscv64" "0.25.12" + "@esbuild/linux-s390x" "0.25.12" + "@esbuild/linux-x64" "0.25.12" + "@esbuild/netbsd-arm64" "0.25.12" + "@esbuild/netbsd-x64" "0.25.12" + "@esbuild/openbsd-arm64" "0.25.12" + "@esbuild/openbsd-x64" "0.25.12" + "@esbuild/openharmony-arm64" "0.25.12" + "@esbuild/sunos-x64" "0.25.12" + "@esbuild/win32-arm64" "0.25.12" + "@esbuild/win32-ia32" "0.25.12" + "@esbuild/win32-x64" "0.25.12" escalade@^3.1.1: version "3.1.1" @@ -1773,6 +1837,11 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" +fdir@^6.4.4, fdir@^6.5.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.5.0.tgz#ed2ab967a331ade62f18d077dae192684d50d350" + integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg== + file-entry-cache@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" @@ -1785,10 +1854,10 @@ file-saver@^2.0.5: resolved "https://registry.yarnpkg.com/file-saver/-/file-saver-2.0.5.tgz#d61cfe2ce059f414d899e9dd6d4107ee25670c38" integrity sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA== -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== dependencies: to-regex-range "^5.0.1" @@ -1809,14 +1878,14 @@ flat-cache@^3.0.4: rimraf "^3.0.2" flatted@^3.1.0: - version "3.2.7" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" - integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== + version "3.4.4" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.4.4.tgz#aeeca2a506303f0cee61c59e6c9f2a88d2f29fc6" + integrity sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q== follow-redirects@^1.15.4: - version "1.15.11" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.11.tgz#777d73d72a92f8ec4d2e410eb47352a56b8e8340" - integrity sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ== + version "1.16.0" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.16.0.tgz#28474a159d3b9d11ef62050a14ed60e4df6d61bc" + integrity sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw== for-each@^0.3.3: version "0.3.3" @@ -1826,15 +1895,15 @@ for-each@^0.3.3: is-callable "^1.1.3" form-data@^4.0.4: - version "4.0.5" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.5.tgz#b49e48858045ff4cbf6b03e1805cebcad3679053" - integrity sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w== + version "4.0.6" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.6.tgz#28e864e1b786dbebb68db1f452f9635278665827" + integrity sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ== dependencies: asynckit "^0.4.0" combined-stream "^1.0.8" es-set-tostringtag "^2.1.0" - hasown "^2.0.2" - mime-types "^2.1.12" + hasown "^2.0.4" + mime-types "^2.1.35" fraction.js@^5.3.4: version "5.3.4" @@ -2135,6 +2204,13 @@ hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2: dependencies: function-bind "^1.1.2" +hasown@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.4.tgz#8c62d8cb90beb2aad5d0a5b67581ad9854c3f003" + integrity sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A== + dependencies: + function-bind "^1.1.2" + he@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" @@ -2156,9 +2232,9 @@ ignore@^5.3.1: integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== immutable@^4.0.0: - version "4.3.7" - resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.7.tgz#c70145fc90d89fb02021e65c84eb0226e4e5a381" - integrity sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw== + version "4.3.9" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.9.tgz#c98349e05e9c6e2a4d8fe88ac0b363e0d536b544" + integrity sha512-ObHy4YN7ycwZOUCLI1/6svfyAFu7vL8RhAvVu/bh/RZW9EPlOyDaQ9jDQWCtdqzaXUjgXZCW1migtHE7YI7UGQ== import-fresh@^3.2.1: version "3.3.0" @@ -2402,9 +2478,9 @@ isexe@^2.0.0: integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + version "4.3.2" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.3.2.tgz#8e44fb14a2643c59726bb15787b5f1512cb3d3fb" + integrity sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA== dependencies: argparse "^2.0.1" @@ -2478,9 +2554,9 @@ lodash.merge@^4.6.2: integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== lodash@^4.17.21: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + version "4.18.1" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.18.1.tgz#ff2b66c1f6326d59513de2407bf881439812771c" + integrity sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q== lru-cache@^6.0.0: version "6.0.0" @@ -2531,7 +2607,7 @@ mime-db@1.52.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-types@^2.1.12: +mime-types@^2.1.35: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== @@ -2539,25 +2615,25 @@ mime-types@^2.1.12: mime-db "1.52.0" minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + version "3.1.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.5.tgz#580c88f8d5445f2bd6aa8f3cadefa0de79fbd69e" + integrity sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w== dependencies: brace-expansion "^1.1.7" minimatch@^5.0.1: - version "5.1.6" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" - integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== + version "5.1.9" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.9.tgz#1293ef15db0098b394540e8f9f744f9fda8dee4b" + integrity sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw== dependencies: brace-expansion "^2.0.1" minimatch@^9.0.3, minimatch@^9.0.4, minimatch@^9.0.5: - version "9.0.5" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" - integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + version "9.0.9" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.9.tgz#9b0cb9fcb78087f6fd7eababe2511c4d3d60574e" + integrity sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg== dependencies: - brace-expansion "^2.0.1" + brace-expansion "^2.0.2" minimist@^1.2.0, minimist@^1.2.6: version "1.2.8" @@ -2594,10 +2670,10 @@ mylas@^2.1.9: resolved "https://registry.yarnpkg.com/mylas/-/mylas-2.1.13.tgz#1e23b37d58fdcc76e15d8a5ed23f9ae9fc0cbdf4" integrity sha512-+MrqnJRtxdF+xngFfUUkIMQrUUL0KsxbADUkn23Z/4ibGg192Q+z+CQyiYwvWTsYjJygmMR8+w3ZDa98Zh6ESg== -nanoid@^3.3.7: - version "3.3.7" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" - integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== +nanoid@^3.3.18: + version "3.3.19" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.19.tgz#336d4aa4bcd4fb24d2cddede7ffeae40bec03f0a" + integrity sha512-Y2tUNy4ouw6tq5oDSKeQYGOyhkUBhNOcGV/02KC+6kd9eDGqdZd++mjMiIDilrBYvjEnCYvVtsuHCuP+okSfug== natural-compare@^1.4.0: version "1.4.0" @@ -2609,10 +2685,10 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== -node-releases@^2.0.27: - version "2.0.27" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.27.tgz#eedca519205cf20f650f61d56b070db111231e4e" - integrity sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA== +node-releases@^2.0.57: + version "2.0.57" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.57.tgz#47827d34b86a98b4b7afacc1222878c286b6ef2d" + integrity sha512-kQK9LGGFiHtrWiNhZtA7Qbw17AQz+dmsEKODRIVTXA9+e5MS/2gZEBhYJt13GrAz5/IOZKddH/0Z3TP/Zgo+yw== normalize-package-data@^2.3.2: version "2.5.0" @@ -2747,6 +2823,11 @@ p-locate@^5.0.0: dependencies: p-limit "^3.0.2" +p-map@^7.0.3: + version "7.0.8" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-7.0.8.tgz#e2ce27eff78cd934a78908a3cede58330a3a5543" + integrity sha512-MitaVsCuCFIvOLLPIU7NnfrZvS9H9h7kwMUkDo+T2pEISaJD48IV9S8iIdXB7PsvvdxyYcsSTTrr90XKsbulNw== + parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -2814,20 +2895,20 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picocolors@^1.1.0, picocolors@^1.1.1: +picocolors@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + version "2.3.2" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.2.tgz#5a942915e26b372dc0f0e6753149a16e6b1c5601" + integrity sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA== -picomatch@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab" - integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== +picomatch@^4.0.2, picomatch@^4.0.4: + version "4.0.7" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.7.tgz#6313360034ccb36b3dc61ecbdff78121f90fe21f" + integrity sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA== pidtree@^0.3.0: version "0.3.1" @@ -2868,18 +2949,10 @@ possible-typed-array-names@^1.0.0: resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f" integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q== -postcss-selector-parser@^6.0.15: - version "6.1.2" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz#27ecb41fb0e3b6ba7a1ec84fff347f734c7929de" - integrity sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg== - dependencies: - cssesc "^3.0.0" - util-deprecate "^1.0.2" - -postcss-selector-parser@^6.0.7: - version "6.0.15" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz#11cc2b21eebc0b99ea374ffb9887174855a01535" - integrity sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw== +postcss-selector-parser@^6.0.15, postcss-selector-parser@^6.0.7: + version "6.1.4" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.1.4.tgz#fdec4ca80f5781bd216ca9bf89a2a0fccfffa5f0" + integrity sha512-bIoJLOmjCO1S9XdY/DcnR5hJxvrDir1PbGChrzXG3vw0/FOliy/fA3dmdhQ441kah4gKv+TwckGzex6wNS5cnQ== dependencies: cssesc "^3.0.0" util-deprecate "^1.0.2" @@ -2889,22 +2962,13 @@ postcss-value-parser@^4.2.0: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== -postcss@^8.4.4: - version "8.4.33" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.33.tgz#1378e859c9f69bf6f638b990a0212f43e2aaa742" - integrity sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg== +postcss@^8.4.4, postcss@^8.4.47, postcss@^8.5.3: + version "8.5.28" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.28.tgz#da4563a99a06e62d6c1cd1acae363224bcaed6e9" + integrity sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A== dependencies: - nanoid "^3.3.7" - picocolors "^1.0.0" - source-map-js "^1.0.2" - -postcss@^8.4.43, postcss@^8.4.47: - version "8.4.47" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.47.tgz#5bf6c9a010f3e724c503bf03ef7947dcb0fea365" - integrity sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ== - dependencies: - nanoid "^3.3.7" - picocolors "^1.1.0" + nanoid "^3.3.18" + picocolors "^1.1.1" source-map-js "^1.2.1" prelude-ls@^1.2.1: @@ -2980,11 +3044,6 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" -regenerator-runtime@^0.13.11: - version "0.13.11" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" - integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== - regexp.prototype.flags@^1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" @@ -3072,29 +3131,39 @@ rollup-pluginutils@^2.8.1: dependencies: estree-walker "^0.6.1" -rollup@^4.20.0: - version "4.24.0" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.24.0.tgz#c14a3576f20622ea6a5c9cad7caca5e6e9555d05" - integrity sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg== +rollup@^4.34.9: + version "4.63.5" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.63.5.tgz#f3f4686d0874a544ce5497380f132d8b675b4e59" + integrity sha512-KRWwmNLlPw5M7HcdYfm15oBv9n9LPtjzpzCIxS/phwqvPyxHSoKX6Y2YU3pxSPfy0CLquVgsx/j/hBi6OvH1Nw== dependencies: - "@types/estree" "1.0.6" + "@types/estree" "1.0.9" optionalDependencies: - "@rollup/rollup-android-arm-eabi" "4.24.0" - "@rollup/rollup-android-arm64" "4.24.0" - "@rollup/rollup-darwin-arm64" "4.24.0" - "@rollup/rollup-darwin-x64" "4.24.0" - "@rollup/rollup-linux-arm-gnueabihf" "4.24.0" - "@rollup/rollup-linux-arm-musleabihf" "4.24.0" - "@rollup/rollup-linux-arm64-gnu" "4.24.0" - "@rollup/rollup-linux-arm64-musl" "4.24.0" - "@rollup/rollup-linux-powerpc64le-gnu" "4.24.0" - "@rollup/rollup-linux-riscv64-gnu" "4.24.0" - "@rollup/rollup-linux-s390x-gnu" "4.24.0" - "@rollup/rollup-linux-x64-gnu" "4.24.0" - "@rollup/rollup-linux-x64-musl" "4.24.0" - "@rollup/rollup-win32-arm64-msvc" "4.24.0" - "@rollup/rollup-win32-ia32-msvc" "4.24.0" - "@rollup/rollup-win32-x64-msvc" "4.24.0" + "@napi-rs/lzma-linux-x64-gnu" "1.5.1" + "@rollup/rollup-android-arm-eabi" "4.63.5" + "@rollup/rollup-android-arm64" "4.63.5" + "@rollup/rollup-darwin-arm64" "4.63.5" + "@rollup/rollup-darwin-x64" "4.63.5" + "@rollup/rollup-freebsd-arm64" "4.63.5" + "@rollup/rollup-freebsd-x64" "4.63.5" + "@rollup/rollup-linux-arm-gnueabihf" "4.63.5" + "@rollup/rollup-linux-arm-musleabihf" "4.63.5" + "@rollup/rollup-linux-arm64-gnu" "4.63.5" + "@rollup/rollup-linux-arm64-musl" "4.63.5" + "@rollup/rollup-linux-loong64-gnu" "4.63.5" + "@rollup/rollup-linux-loong64-musl" "4.63.5" + "@rollup/rollup-linux-ppc64-gnu" "4.63.5" + "@rollup/rollup-linux-ppc64-musl" "4.63.5" + "@rollup/rollup-linux-riscv64-gnu" "4.63.5" + "@rollup/rollup-linux-riscv64-musl" "4.63.5" + "@rollup/rollup-linux-s390x-gnu" "4.63.5" + "@rollup/rollup-linux-x64-gnu" "4.63.5" + "@rollup/rollup-linux-x64-musl" "4.63.5" + "@rollup/rollup-openbsd-x64" "4.63.5" + "@rollup/rollup-openharmony-arm64" "4.63.5" + "@rollup/rollup-win32-arm64-msvc" "4.63.5" + "@rollup/rollup-win32-ia32-msvc" "4.63.5" + "@rollup/rollup-win32-x64-gnu" "4.63.5" + "@rollup/rollup-win32-x64-msvc" "4.63.5" fsevents "~2.3.2" run-parallel@^1.1.9: @@ -3221,15 +3290,10 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -shell-quote@^1.6.1: - version "1.8.0" - resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.0.tgz#20d078d0eaf71d54f43bd2ba14a1b5b9bfa5c8ba" - integrity sha512-QHsz8GgQIGKlRi24yFc6a6lN69Idnx634w49ay6+jA5yFh7a1UY+4Rp6HPx/L/1zcEDPEij8cIsiqR6bQsE5VQ== - -shell-quote@^1.8.0: - version "1.8.1" - resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.1.tgz#6dbf4db75515ad5bac63b4f1894c3a154c766680" - integrity sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA== +shell-quote@^1.6.1, shell-quote@^1.8.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.10.0.tgz#482033e192e4f5c07151521ffa03400ec71b1b0f" + integrity sha512-w1aiOKwKuRgtwAReIIj89puqg+I7GvX4IbLrvmhXbzQsj1+Zwi4VO3+fa6ZF91TWSjIxoEkKnMeHcLEODK5ZXA== side-channel@^1.0.4: version "1.0.4" @@ -3250,11 +3314,6 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== -source-map-js@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" - integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== - source-map-js@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" @@ -3408,6 +3467,14 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== +tinyglobby@^0.2.13: + version "0.2.17" + resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.17.tgz#562a9a6c9eb2b3b123d39719f9af5bb44fcd7631" + integrity sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g== + dependencies: + fdir "^6.5.0" + picomatch "^4.0.4" + to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -3537,13 +3604,13 @@ unbox-primitive@^1.0.2: has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" -universal-cookie@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/universal-cookie/-/universal-cookie-4.0.4.tgz#06e8b3625bf9af049569ef97109b4bb226ad798d" - integrity sha512-lbRVHoOMtItjWbM7TwDLdl8wug7izB0tq3/YVKhT/ahB4VDvWMyvnADfnJI8y6fSvsjh51Ix7lTGC6Tn4rMPhw== +universal-cookie@^7.2.2: + version "7.2.2" + resolved "https://registry.yarnpkg.com/universal-cookie/-/universal-cookie-7.2.2.tgz#93ae9ec55baab89b24300473543170bb8112773c" + integrity sha512-fMiOcS3TmzP2x5QV26pIH3mvhexLIT0HmPa3V7Q7knRfT9HG6kTwq02HZGLPw0sAOXrAmotElGRvTLCMbJsvxQ== dependencies: - "@types/cookie" "^0.3.3" - cookie "^0.4.0" + "@types/cookie" "^0.6.0" + cookie "^0.7.2" universalify@^2.0.0: version "2.0.0" @@ -3574,10 +3641,10 @@ unplugin@^1.12.1: acorn "^8.12.1" webpack-virtual-modules "^0.6.2" -update-browserslist-db@^1.2.0: - version "1.2.3" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz#64d76db58713136acbeb4c49114366cc6cc2e80d" - integrity sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w== +update-browserslist-db@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.3.3.tgz#197e21fb2561fa89f8b94fad605a2b296a18993a" + integrity sha512-pJ2sYawQS0R/WI928Gj5GlPhTGzbMelq0+4INtSYNDV9ErKJcX6xjGWkoG/VnB3dpUm00zALaqkrUD77pO5TDQ== dependencies: escalade "^3.2.0" picocolors "^1.1.1" @@ -3602,24 +3669,28 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" -vite-plugin-static-copy@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/vite-plugin-static-copy/-/vite-plugin-static-copy-2.0.0.tgz#064a0792290992629dcfbc740b9fcddcaba4798f" - integrity sha512-b/quFjTUa/RY9t3geIyeeT2GtWEoRI0GawYFFjys5iMLGgVP638NTGu0RoMjwmi8MoZZ3BQw4OQvb1GpVcXZDA== +vite-plugin-static-copy@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/vite-plugin-static-copy/-/vite-plugin-static-copy-2.3.2.tgz#1b6be634c21541d6363dd72ab7870b1ce14bfa53" + integrity sha512-iwrrf+JupY4b9stBttRWzGHzZbeMjAHBhkrn67MNACXJVjEMRpCI10Q3AkxdBkl45IHaTfw/CNVevzQhP7yTwg== dependencies: chokidar "^3.5.3" fast-glob "^3.2.11" fs-extra "^11.1.0" + p-map "^7.0.3" picocolors "^1.0.0" -vite@^5.4.21: - version "5.4.21" - resolved "https://registry.yarnpkg.com/vite/-/vite-5.4.21.tgz#84a4f7c5d860b071676d39ba513c0d598fdc7027" - integrity sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw== +vite@^6.4.3: + version "6.4.3" + resolved "https://registry.yarnpkg.com/vite/-/vite-6.4.3.tgz#85a164db7ce706f2a776812efa2b340f1721858e" + integrity sha512-NTKlcQjlAK7MlQoyb6LgaqHc8sso/pVyUJYWMws3jg21uTJw/LddqIFPcPqP6PzpgbIcZyKI85sFE4HBrQDA8A== dependencies: - esbuild "^0.21.3" - postcss "^8.4.43" - rollup "^4.20.0" + esbuild "^0.25.0" + fdir "^6.4.4" + picomatch "^4.0.2" + postcss "^8.5.3" + rollup "^4.34.9" + tinyglobby "^0.2.13" optionalDependencies: fsevents "~2.3.3" From 2eae99f8439203463b376a9d0733d5a9d620d316 Mon Sep 17 00:00:00 2001 From: Martin Varga Date: Tue, 29 Sep 2026 10:20:04 +0200 Subject: [PATCH 02/20] Fix inconsistent error code For existing version we must return ProjectVersionExists not an generic upload error. Stale upload and processed tmp files should be removed as well. --- server/mergin/sync/public_api_v2_controller.py | 5 ++--- server/mergin/tests/test_public_api_v2.py | 8 ++++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/server/mergin/sync/public_api_v2_controller.py b/server/mergin/sync/public_api_v2_controller.py index e90c0a99..6dc54dbd 100644 --- a/server/mergin/sync/public_api_v2_controller.py +++ b/server/mergin/sync/public_api_v2_controller.py @@ -351,9 +351,8 @@ def create_project_version(id): if ProjectVersion.query.filter_by( project_id=project.id, name=next_version ).count(): - return UploadError( - error=f"Version {v_next_version} already exists" - ).response(409) + upload.clear() + return ProjectVersionExists(version, next_version).response(409) move_to_tmp(version_dir) try: diff --git a/server/mergin/tests/test_public_api_v2.py b/server/mergin/tests/test_public_api_v2.py index f9b2cf73..d44516d1 100644 --- a/server/mergin/tests/test_public_api_v2.py +++ b/server/mergin/tests/test_public_api_v2.py @@ -1108,6 +1108,14 @@ def test_create_version_failures(client): response = client.post(f"v2/projects/{project.id}/versions", json=data) assert response.status_code == 409 + # target version already exists on server (both on disk and in db), upload is released + with patch.object(Project, "next_version", return_value=1): + response = client.post(f"v2/projects/{project.id}/versions", json=data) + assert response.status_code == 409 + assert response.json["code"] == ProjectVersionExists.code + assert not Upload.query.filter_by(project_id=project.id).first() + assert project.latest_version == 1 + def test_create_version_permanent_error_takes_priority(client): """Permanent errors (e.g. storage limit) must be reported before a From 80c58aa5014ca8812d6eeea8df629ea3d647e060 Mon Sep 17 00:00:00 2001 From: Martin Varga Date: Tue, 29 Sep 2026 13:22:47 +0200 Subject: [PATCH 03/20] Make password reset tokens single-use Bind each token to a random nonce stored on the user. Requesting a reset rotates the nonce, revoking older links; any password change clears it, so a link works once and dies on a logged-in password change. Co-Authored-By: Claude Opus 5.5 --- deployment/community/.env.template | 2 + deployment/enterprise/.env.template | 2 + server/mergin/auth/app.py | 58 ++++++++++-- server/mergin/auth/config.py | 3 + server/mergin/auth/controller.py | 26 ++++-- server/mergin/auth/listeners.py | 3 +- server/mergin/auth/models.py | 4 + server/mergin/tests/test_audit_events.py | 22 ++++- server/mergin/tests/test_auth.py | 91 ++++++++++++++++--- .../c4e7b1d9a2f3_add_password_reset_nonce.py | 28 ++++++ 10 files changed, 204 insertions(+), 35 deletions(-) create mode 100644 server/migrations/community/c4e7b1d9a2f3_add_password_reset_nonce.py diff --git a/deployment/community/.env.template b/deployment/community/.env.template index e786e52f..55842c36 100644 --- a/deployment/community/.env.template +++ b/deployment/community/.env.template @@ -57,6 +57,8 @@ SECRET_KEY=fixme #BEARER_TOKEN_EXPIRATION=3600 * 12 # in seconds +#PASSWORD_RESET_TOKEN_EXPIRATION=600 # in seconds + #SECURITY_BEARER_SALT=NODEFAULT SECURITY_BEARER_SALT=fixme diff --git a/deployment/enterprise/.env.template b/deployment/enterprise/.env.template index a11aa575..1efb6e6a 100644 --- a/deployment/enterprise/.env.template +++ b/deployment/enterprise/.env.template @@ -62,6 +62,8 @@ SECRET_KEY=fixme #BEARER_TOKEN_EXPIRATION=3600 * 12 # in seconds +#PASSWORD_RESET_TOKEN_EXPIRATION=600 # in seconds + #SECURITY_BEARER_SALT=NODEFAULT SECURITY_BEARER_SALT=fixme diff --git a/server/mergin/auth/app.py b/server/mergin/auth/app.py index 638ec2ff..643de9b9 100644 --- a/server/mergin/auth/app.py +++ b/server/mergin/auth/app.py @@ -4,6 +4,7 @@ import functools import logging +import secrets from typing import Optional from blinker import signal from flask import current_app, render_template, Flask @@ -159,15 +160,30 @@ def send_confirmation_email(app, user, url, template, header, **kwargs): Send confirmation email from selected template with customizable email subject and confirmation URL. Optional kwargs are passed to render_template method if needed for particular template. """ - from ..celery import send_email_async + token = generate_confirmation_token( + app, user.email, app.config["SECURITY_EMAIL_SALT"] + ) + _send_token_email(app, user, f"{url}/{token}", template, header, **kwargs) + - salt = ( - app.config["SECURITY_EMAIL_SALT"] - if url == "confirm-email" - else app.config["SECURITY_PASSWORD_SALT"] +def send_password_reset_email(app: Flask, user: User) -> None: + """Issue a new single-use password reset token (revoking any previous one) and email it.""" + from ..app import db + + token = generate_password_reset_token(app, user) + db.session.commit() + _send_token_email( + app, + user, + f"change-password/{token}", + "email/password_reset.html", + "Password reset", ) - token = generate_confirmation_token(app, user.email, salt) - confirm_url = f"{url}/{token}" + + +def _send_token_email(app, user, confirm_url, template, header, **kwargs): + from ..celery import send_email_async + html = render_template( template, subject=header, confirm_url=confirm_url, user=user, **kwargs ) @@ -180,6 +196,34 @@ def send_confirmation_email(app, user, url, template, header, **kwargs): send_email_async.delay(**email_data) +def generate_password_reset_token(app: Flask, user: User) -> str: + """Sign a reset token bound to a fresh nonce stored on the user. + + Rotating the nonce revokes previously issued tokens; any password change clears it. + """ + user.password_reset_nonce = secrets.token_urlsafe(32) + serializer = URLSafeTimedSerializer(app.config["SECRET_KEY"]) + payload = {"email": user.email, "nonce": user.password_reset_nonce} + return serializer.dumps(payload, salt=app.config["SECURITY_PASSWORD_SALT"]) + + +def confirm_password_reset_token(token: str) -> Optional[dict]: + """Return a signed, unexpired reset token payload, or None. The nonce still has to be checked against the user.""" + serializer = URLSafeTimedSerializer(current_app.config["SECRET_KEY"]) + try: + payload = serializer.loads( + token, + salt=current_app.config["SECURITY_PASSWORD_SALT"], + max_age=current_app.config["PASSWORD_RESET_TOKEN_EXPIRATION"], + ) + except BadData: + return None + # tokens issued before nonces were introduced carried only the email + if not isinstance(payload, dict): + return None + return payload + + def generate_unlock_token(app: Flask, user: User) -> str: """Sign a token binding the current lock episode (email + locked_until) to the user.""" serializer = URLSafeTimedSerializer(app.config["SECRET_KEY"]) diff --git a/server/mergin/auth/config.py b/server/mergin/auth/config.py index 9b9c5c50..a4f34447 100644 --- a/server/mergin/auth/config.py +++ b/server/mergin/auth/config.py @@ -13,6 +13,9 @@ class Configuration(object): BEARER_TOKEN_EXPIRATION = config( "BEARER_TOKEN_EXPIRATION", default=3600 * 12, cast=int ) # in seconds + PASSWORD_RESET_TOKEN_EXPIRATION = config( + "PASSWORD_RESET_TOKEN_EXPIRATION", default=600, cast=int + ) # in seconds ACCOUNT_EXPIRATION = config("ACCOUNT_EXPIRATION", default=5, cast=int) # in days BCRYPT_LOG_ROUNDS = config("BCRYPT_LOG_ROUNDS", default=12, cast=int) # Comma-separated "attempts:seconds" pairs, e.g. "5:300,10:3600" diff --git a/server/mergin/auth/controller.py b/server/mergin/auth/controller.py index 9994a65a..38bc7865 100644 --- a/server/mergin/auth/controller.py +++ b/server/mergin/auth/controller.py @@ -16,7 +16,9 @@ auth_required, authenticate, send_confirmation_email, + send_password_reset_email, confirm_token, + confirm_password_reset_token, generate_confirmation_token, confirm_unlock_token, user_created, @@ -380,19 +382,13 @@ def password_reset(): # pylint: disable=W0613,W0612 target_email=form.email.data.strip(), ) if user and user.active and user.can_edit_profile: - send_confirmation_email( - current_app, - user, - "change-password", - "email/password_reset.html", - "Password reset", - ) + send_password_reset_email(current_app, user) return "", 200 def confirm_new_password(token): # pylint: disable=W0613,W0612 - email = confirm_token(token, salt=current_app.config["SECURITY_PASSWORD_SALT"]) - if not email: + payload = confirm_password_reset_token(token) + if not payload: emit( AuthEventType.USER_PASSWORD_RESET_FAILED, **request_context(), @@ -402,6 +398,7 @@ def confirm_new_password(token): # pylint: disable=W0613,W0612 ) abort(400, "Invalid token") + email = payload["email"] user = User.query.filter_by(email=email).first() if not user: emit( @@ -412,6 +409,16 @@ def confirm_new_password(token): # pylint: disable=W0613,W0612 reason="user_not_found", ) abort(404) + # token was already used, superseded by a newer one or revoked by a password change + if user.password_reset_nonce != payload["nonce"]: + emit( + AuthEventType.USER_PASSWORD_RESET_FAILED, + **request_context(), + target_user_id=user.id, + target_email=user.email, + reason="token_revoked", + ) + abort(400, "Invalid token") if not user.active: emit( AuthEventType.USER_PASSWORD_RESET_FAILED, @@ -433,6 +440,7 @@ def confirm_new_password(token): # pylint: disable=W0613,W0612 form = UserPasswordForm.from_json(request.json) if form.validate(): + # also clears the reset nonce, making the token single-use user.assign_password(form.password.data) user.reset_lockout() db.session.add(user) diff --git a/server/mergin/auth/listeners.py b/server/mergin/auth/listeners.py index bd1444d6..6f4d3172 100644 --- a/server/mergin/auth/listeners.py +++ b/server/mergin/auth/listeners.py @@ -13,7 +13,7 @@ from .models import User # Fields excluded from user.updated audit events: -# - sensitive values that must never appear in logs (passwd) +# - sensitive values that must never appear in logs (passwd, password_reset_nonce) # - high-frequency operational fields (last_signed_in, registration_date) # - lifecycle state fields covered by dedicated events (active, inactive_since) # - is_admin covered by the dedicated user.admin_panel_access.changed event @@ -22,6 +22,7 @@ _EXCLUDED_FROM_USER_UPDATED = frozenset( { "passwd", + "password_reset_nonce", "last_signed_in", "registration_date", "active", diff --git a/server/mergin/auth/models.py b/server/mergin/auth/models.py index e160dde5..96decb37 100644 --- a/server/mergin/auth/models.py +++ b/server/mergin/auth/models.py @@ -51,6 +51,8 @@ class User(db.Model): ) last_signed_in = db.Column(db.DateTime(), nullable=True) locked_until = db.Column(db.DateTime(), nullable=True) + # nonce of the only valid password reset token, cleared on any password change + password_reset_nonce = db.Column(db.String(64), nullable=True) receive_notifications = db.Column( db.Boolean, default=True, nullable=False, index=True ) @@ -89,6 +91,7 @@ def assign_password(self, password): if password else None ) + self.password_reset_nonce = None def needs_rehash(self): """Return True if the stored hash was generated with a different cost factor than configured.""" @@ -267,6 +270,7 @@ def anonymize(self): self.username = del_str self.email = None self.passwd = None + self.password_reset_nonce = None self.first_name = None self.last_name = None db.session.commit() diff --git a/server/mergin/tests/test_audit_events.py b/server/mergin/tests/test_audit_events.py index 4c6b9f13..eb4a5044 100644 --- a/server/mergin/tests/test_audit_events.py +++ b/server/mergin/tests/test_audit_events.py @@ -12,7 +12,10 @@ from flask import current_app from ..app import db -from ..auth.app import generate_confirmation_token, generate_unlock_token +from ..auth.app import ( + generate_password_reset_token, + generate_unlock_token, +) from ..auth.events import AuthEventType from ..auth.models import User from ..sync.events import SyncEventType @@ -82,9 +85,10 @@ def test_user_password_changed(client, audit_capture): def test_user_password_reset(app, client, audit_capture): user = User.query.filter_by(username=DEFAULT_USER[0]).first() - token = generate_confirmation_token( - app, user.email, app.config["SECURITY_PASSWORD_SALT"] - ) + token = generate_password_reset_token(app, user) + db.session.commit() + # the nonce is a secret - storing it must not emit user.updated + assert len(audit_capture.of_type(AuthEventType.USER_UPDATED)) == 0 client.post( f"/app/auth/reset-password/{token}", @@ -94,6 +98,16 @@ def test_user_password_reset(app, client, audit_capture): e = audit_capture.one(AuthEventType.USER_PASSWORD_RESET_COMPLETED) assert e.target_user_id == user.id assert e.metadata["target_email"] == user.email + assert len(audit_capture.of_type(AuthEventType.USER_UPDATED)) == 0 + + # reusing the token is rejected + client.post( + f"/app/auth/reset-password/{token}", + json={"password": "NewPass#456", "confirm": "NewPass#456"}, + ) + e = audit_capture.one(AuthEventType.USER_PASSWORD_RESET_FAILED) + assert e.target_user_id == user.id + assert e.metadata["reason"] == "token_revoked" def test_user_created(audit_capture): diff --git a/server/mergin/tests/test_auth.py b/server/mergin/tests/test_auth.py index 6bb3d934..815da3c1 100644 --- a/server/mergin/tests/test_auth.py +++ b/server/mergin/tests/test_auth.py @@ -17,6 +17,7 @@ from ..auth.app import ( generate_confirmation_token, confirm_token, + generate_password_reset_token, generate_unlock_token, ) from ..auth.models import User, LoginHistory @@ -578,9 +579,8 @@ def test_confirm_email(app, client): def test_confirm_password(app, client): user = User.query.filter_by(username="mergin").first() - token = generate_confirmation_token( - app, user.email, app.config["SECURITY_PASSWORD_SALT"] - ) + token = generate_password_reset_token(app, user) + db.session.commit() form_data = {"password": "ilovemergin#0", "confirm": "ilovemergin#0"} @@ -607,8 +607,8 @@ def test_confirm_password(app, client): resp = client.post( url_for( "/.mergin_auth_controller_confirm_new_password", - token=generate_confirmation_token( - app, "tests@mergin.com", app.config["SECURITY_PASSWORD_SALT"] + token=generate_password_reset_token( + app, SimpleNamespace(email="tests@mergin.com") ), ), data=json.dumps(form_data), @@ -622,14 +622,10 @@ def test_confirm_password(app, client): ) user.active = False db.session.add(user) + token = generate_password_reset_token(app, user) db.session.commit() resp = client.post( - url_for( - "/.mergin_auth_controller_confirm_new_password", - token=generate_confirmation_token( - app, "tests@mergin.com", app.config["SECURITY_PASSWORD_SALT"] - ), - ) + url_for("/.mergin_auth_controller_confirm_new_password", token=token) ) assert resp.status_code == 400 @@ -648,9 +644,8 @@ def test_confirm_password_clears_lockout(send_email_mock, app, client): ) assert user.is_locked_out() - token = generate_confirmation_token( - app, user.email, app.config["SECURITY_PASSWORD_SALT"] - ) + token = generate_password_reset_token(app, user) + db.session.commit() resp = client.post( url_for("/.mergin_auth_controller_confirm_new_password", token=token), data=json.dumps({"password": "newpass#1", "confirm": "newpass#1"}), @@ -678,6 +673,74 @@ def test_confirm_password_clears_lockout(send_email_mock, app, client): assert not user.is_locked_out() +def _confirm_new_password(client, token, password="newpass#1"): + return client.post( + url_for("/.mergin_auth_controller_confirm_new_password", token=token), + data=json.dumps({"password": password, "confirm": password}), + headers=json_headers, + ) + + +@patch("mergin.celery.send_email_async.apply_async") +def test_reset_password_token_single_use(send_email_mock, app, client): + """Reset link is one-off, only the latest link is valid and a regular password change revokes it.""" + user = add_user("resetuser", "oldpassword") + + # used token cannot be reused + token = generate_password_reset_token(app, user) + db.session.commit() + assert _confirm_new_password(client, token).status_code == 200 + assert user.password_reset_nonce is None + assert _confirm_new_password(client, token, "another#1").status_code == 400 + assert user.check_password("newpass#1") + + # requesting a new link revokes the older one + old_token = generate_password_reset_token(app, user) + db.session.commit() + resp = client.post( + url_for("/.mergin_auth_controller_password_reset"), + json={"email": user.email}, + ) + assert resp.status_code == 200 + assert send_email_mock.call_count == 1 + email_html = send_email_mock.call_args.args[1]["html"] + assert old_token not in email_html + assert _confirm_new_password(client, old_token).status_code == 400 + new_token = email_html.split("change-password/")[1].split('"')[0] + assert _confirm_new_password(client, new_token, "latest#1").status_code == 200 + + # regular password change revokes outstanding link + token = generate_password_reset_token(app, user) + db.session.commit() + login(client, user.username, "latest#1") + resp = client.post( + url_for("/.mergin_auth_controller_change_password"), + json={ + "old_password": "latest#1", + "password": "changed#1", + "confirm": "changed#1", + }, + ) + assert resp.status_code == 200 + assert _confirm_new_password(client, token).status_code == 400 + assert user.check_password("changed#1") + + +def test_reset_password_token_expired_or_legacy(app, client): + user = add_user("resetuser", "oldpassword") + token = generate_password_reset_token(app, user) + db.session.commit() + with patch.dict(app.config, {"PASSWORD_RESET_TOKEN_EXPIRATION": -1}): + assert _confirm_new_password(client, token).status_code == 400 + + # token format from before nonces were introduced (email only) is rejected + legacy_token = generate_confirmation_token( + app, user.email, app.config["SECURITY_PASSWORD_SALT"] + ) + assert _confirm_new_password(client, legacy_token).status_code == 400 + assert user.check_password("oldpassword") + + # reset password tests: success, no email, not-existing user (200 - masked) test_reset_data = [ ({"email": "mergin@mergin.com"}, 200), diff --git a/server/migrations/community/c4e7b1d9a2f3_add_password_reset_nonce.py b/server/migrations/community/c4e7b1d9a2f3_add_password_reset_nonce.py new file mode 100644 index 00000000..48e77cd1 --- /dev/null +++ b/server/migrations/community/c4e7b1d9a2f3_add_password_reset_nonce.py @@ -0,0 +1,28 @@ +"""Add password_reset_nonce to user table + +Revision ID: c4e7b1d9a2f3 +Revises: 7a095270b252 +Create Date: 2026-09-29 00:00:00.000000 + +""" + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = "c4e7b1d9a2f3" +down_revision = "7a095270b252" +branch_labels = None +depends_on = None + + +def upgrade(): + op.add_column( + "user", + sa.Column("password_reset_nonce", sa.String(64), nullable=True), + ) + + +def downgrade(): + op.drop_column("user", "password_reset_nonce") From 2bfb070d1ea5407ddfaadd5fda658a8e30c3f0c0 Mon Sep 17 00:00:00 2001 From: Herman Snevajs Date: Tue, 29 Sep 2026 16:46:54 +0200 Subject: [PATCH 04/20] Add v2 endpoint to create project in workspace --- server/mergin/sync/public_api_controller.py | 20 +---- server/mergin/sync/public_api_v2.yaml | 76 +++++++++++++++++++ .../mergin/sync/public_api_v2_controller.py | 55 ++++++++++++++ server/mergin/sync/utils.py | 11 +++ server/mergin/tests/test_public_api_v2.py | 60 +++++++++++++++ 5 files changed, 205 insertions(+), 17 deletions(-) diff --git a/server/mergin/sync/public_api_controller.py b/server/mergin/sync/public_api_controller.py index 43ecd1cb..a27422a8 100644 --- a/server/mergin/sync/public_api_controller.py +++ b/server/mergin/sync/public_api_controller.py @@ -85,11 +85,11 @@ is_valid_uuid, is_versioned_file, prepare_download_response, + project_name_conflict_message, wkb2wkt, ) from ..utils import get_ip, get_user_agent, get_device_id from .errors import StorageLimitHit, ProjectLocked -from ..utils import format_time_delta def parse_project_access_update_request(access: Dict) -> Dict: @@ -201,14 +201,7 @@ def add_project(namespace): # noqa: E501 name=request.json["name"], workspace_id=workspace.id ).first() if proj: - if proj.removed_at: - msg = ( - f"Project with the same name is scheduled for deletion, " - f"you can create a project with this name in {format_time_delta(proj.expiration)}" - ) - else: - msg = "Project with the same name already exists" - abort(409, msg) + abort(409, project_name_conflict_message(proj)) request.json["storage_params"] = { "type": "local", @@ -1283,14 +1276,7 @@ def clone_project(namespace, project_name): # noqa: E501 _project = Project.query.filter_by(name=dest_project, workspace_id=ws.id).first() if _project: - if _project.removed_at: - msg = ( - f"Project with the same name is scheduled for deletion, " - f"you can create a project with this name in {format_time_delta(_project.expiration)}" - ) - else: - msg = "Project with the same name already exists" - abort(409, msg) + abort(409, project_name_conflict_message(_project)) # Check storage limit additional_storage = cloned_project.disk_usage diff --git a/server/mergin/sync/public_api_v2.yaml b/server/mergin/sync/public_api_v2.yaml index b351654f..e63915d7 100644 --- a/server/mergin/sync/public_api_v2.yaml +++ b/server/mergin/sync/public_api_v2.yaml @@ -550,6 +550,71 @@ paths: "404": $ref: "#/components/responses/NotFound" x-openapi-router-controller: mergin.sync.public_api_v2_controller + post: + tags: + - workspace + summary: Create a new empty project in the workspace + operationId: create_project + parameters: + - $ref: "#/components/parameters/WorkspaceId" + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - name + properties: + name: + type: string + example: survey + public: + type: boolean + default: false + example: false + responses: + "201": + description: New project + content: + application/json: + schema: + $ref: "#/components/schemas/Project" + "400": + description: Invalid project name + content: + application/json: + schema: + type: object + required: + - code + - detail + properties: + code: + type: string + enum: + - InvalidProjectName + example: InvalidProjectName + detail: + type: string + example: "Entered project name is invalid" + "401": + $ref: "#/components/responses/Unauthorized" + "403": + $ref: "#/components/responses/Forbidden" + "404": + $ref: "#/components/responses/NotFound" + "409": + $ref: "#/components/responses/Conflict" + "422": + description: New project cannot be created in the workspace + content: + application/problem+json: + schema: + anyOf: + - $ref: "#/components/schemas/ProjectsLimitHit" + - $ref: "#/components/schemas/TrialExpired" + x-openapi-router-controller: mergin.sync.public_api_v2_controller components: responses: NoContent: @@ -617,6 +682,17 @@ components: detail: You have reached a data limit (StorageLimitHit) current_usage: 24865 storage_limit: 24865 + ProjectsLimitHit: + allOf: + - $ref: "#/components/schemas/CustomError" + type: object + properties: + projects_quota: + type: integer + example: + code: ProjectsLimitHit + detail: Maximum number of projects is reached. Please upgrade your subscription to create new projects (ProjectsLimitHit) + projects_quota: 2 ProjectLocked: allOf: - $ref: "#/components/schemas/CustomError" diff --git a/server/mergin/sync/public_api_v2_controller.py b/server/mergin/sync/public_api_v2_controller.py index 6dc54dbd..d1a31ea1 100644 --- a/server/mergin/sync/public_api_v2_controller.py +++ b/server/mergin/sync/public_api_v2_controller.py @@ -60,9 +60,12 @@ ) from .schemas_v2 import ProjectSchema as ProjectSchemaV2 from .storages.disk import move_to_tmp, save_to_file +from .storages.storage import InitializationError from .utils import ( + generate_location, get_chunk_location, prepare_download_response, + project_name_conflict_message, ) from ..utils import get_ip, get_user_agent, get_device_id from .tasks import remove_transaction_chunks @@ -567,6 +570,58 @@ def list_workspace_projects(workspace_id, page, per_page, order_params=None, q=N return jsonify(projects=data, count=total, page=page, per_page=per_page), 200 +@auth_required +def create_project(workspace_id): + """Create a new empty project in the workspace""" + ws = current_app.ws_handler.get(workspace_id) + if not (ws and ws.is_active): + abort(404, "Workspace not found") + + if not ws.user_has_permissions(current_user, "admin"): + abort(403, "You do not have permissions for this workspace") + + name = request.json["name"].strip() + validation_error = project_name_validation(name) + if validation_error: + return ( + jsonify(code="InvalidProjectName", detail=validation_error), + 400, + ) + + existing_project = Project.query.filter_by(name=name, workspace_id=ws.id).first() + if existing_project: + abort(409, project_name_conflict_message(existing_project)) + + project = Project( + name=name, + storage_params={"type": "local", "location": generate_location()}, + creator=current_user, + workspace=ws, + public=request.json.get("public", False), + ) + project.updated = datetime.utcnow() + try: + project.storage.initialize() + except InitializationError as e: + abort(400, f"Failed to initialize project: {str(e)}") + + pv = ProjectVersion( + project, + 0, + current_user.id, + [], + get_ip(request), + get_user_agent(request), + get_device_id(request), + ) + db.session.add(project) + db.session.add(pv) + db.session.commit() + project_version_created.send(pv) + + return ProjectSchemaV2().dump(project), 201 + + def list_batch_projects(body): """List projects by given list of UUIDs. Limit to 100 projects per request. diff --git a/server/mergin/sync/utils.py b/server/mergin/sync/utils.py index e1c06678..d31d4d49 100644 --- a/server/mergin/sync/utils.py +++ b/server/mergin/sync/utils.py @@ -34,6 +34,7 @@ from pathlib import Path from .config import Configuration +from ..utils import format_time_delta # log base for caching strategy, diff checkpoints, etc. LOG_BASE = 4 @@ -113,6 +114,16 @@ def generate_location(): return os.path.join(secrets.token_hex(1), secrets.token_hex(16)) +def project_name_conflict_message(project) -> str: + """Return error message for a new project clashing with an existing project name""" + if project.removed_at: + return ( + f"Project with the same name is scheduled for deletion, " + f"you can create a project with this name in {format_time_delta(project.expiration)}" + ) + return "Project with the same name already exists" + + def is_valid_uuid(uuid): """Check object can be parse as valid UUID""" try: diff --git a/server/mergin/tests/test_public_api_v2.py b/server/mergin/tests/test_public_api_v2.py index d44516d1..94a220c5 100644 --- a/server/mergin/tests/test_public_api_v2.py +++ b/server/mergin/tests/test_public_api_v2.py @@ -1489,6 +1489,66 @@ def test_list_workspace_projects(client): assert client.get(url + "?page=1&per_page=10").status_code == 401 +def test_create_project(client): + url = f"v2/workspaces/{test_workspace_id}/projects" + response = client.post(url, json={"name": " new_project "}) + assert response.status_code == 201 + assert response.json["name"] == "new_project" + assert response.json["version"] == "v0" + assert response.json["size"] == 0 + assert response.json["workspace"]["id"] == test_workspace_id + assert response.json["role"] == "owner" + assert response.json["public"] is False + assert "files" not in response.json + project = Project.query.filter_by( + workspace_id=test_workspace_id, name="new_project" + ).first() + assert str(project.id) == response.json["id"] + assert project.latest_version == 0 + assert os.path.exists(project.storage.project_dir) + + # name already exists + response = client.post(url, json={"name": "new_project"}) + assert response.status_code == 409 + assert response.json["detail"] == "Project with the same name already exists" + # name is taken by project scheduled for deletion + project.removed_at = datetime.utcnow() + db.session.commit() + response = client.post(url, json={"name": "new_project"}) + assert response.status_code == 409 + assert "scheduled for deletion" in response.json["detail"] + + # invalid project name + for name in ["", ".new_project"]: + response = client.post(url, json={"name": name}) + assert response.status_code == 400 + assert response.json["code"] == "InvalidProjectName" + assert client.post(url, json={}).status_code == 400 + + # public project + response = client.post(url, json={"name": "public_project", "public": True}) + assert response.status_code == 201 + assert response.json["public"] is True + assert Project.query.filter_by(name="public_project").first().public + + # not existing workspace + response = client.post("v2/workspaces/1234/projects", json={"name": "other"}) + assert response.status_code == 404 + + # workspace writer cannot create projects + user = add_user("user", "password") + login(client, user.username, "password") + with patch.object(Configuration, "GLOBAL_ADMIN", 0), patch.object( + Configuration, "GLOBAL_WRITE", 1 + ): + response = client.post(url, json={"name": "other"}) + assert response.status_code == 403 + + logout(client) + assert client.post(url, json={"name": "other"}).status_code == 401 + assert not Project.query.filter_by(name="other").count() + + def test_list_projects_in_batch(client): """Test batch project listing endpoint.""" admin = User.query.filter_by(username=DEFAULT_USER[0]).first() From a29609026dfb1c8cdf180a1e8a988d896d5b7fde Mon Sep 17 00:00:00 2001 From: Herman Snevajs Date: Wed, 30 Sep 2026 09:41:07 +0200 Subject: [PATCH 05/20] Drop public flag from v2 project creation --- server/mergin/sync/public_api_v2.yaml | 4 ---- server/mergin/sync/public_api_v2_controller.py | 1 - server/mergin/tests/test_public_api_v2.py | 7 ------- 3 files changed, 12 deletions(-) diff --git a/server/mergin/sync/public_api_v2.yaml b/server/mergin/sync/public_api_v2.yaml index e63915d7..32b232e7 100644 --- a/server/mergin/sync/public_api_v2.yaml +++ b/server/mergin/sync/public_api_v2.yaml @@ -569,10 +569,6 @@ paths: name: type: string example: survey - public: - type: boolean - default: false - example: false responses: "201": description: New project diff --git a/server/mergin/sync/public_api_v2_controller.py b/server/mergin/sync/public_api_v2_controller.py index d1a31ea1..83cef245 100644 --- a/server/mergin/sync/public_api_v2_controller.py +++ b/server/mergin/sync/public_api_v2_controller.py @@ -597,7 +597,6 @@ def create_project(workspace_id): storage_params={"type": "local", "location": generate_location()}, creator=current_user, workspace=ws, - public=request.json.get("public", False), ) project.updated = datetime.utcnow() try: diff --git a/server/mergin/tests/test_public_api_v2.py b/server/mergin/tests/test_public_api_v2.py index 94a220c5..7722f54a 100644 --- a/server/mergin/tests/test_public_api_v2.py +++ b/server/mergin/tests/test_public_api_v2.py @@ -1498,7 +1498,6 @@ def test_create_project(client): assert response.json["size"] == 0 assert response.json["workspace"]["id"] == test_workspace_id assert response.json["role"] == "owner" - assert response.json["public"] is False assert "files" not in response.json project = Project.query.filter_by( workspace_id=test_workspace_id, name="new_project" @@ -1525,12 +1524,6 @@ def test_create_project(client): assert response.json["code"] == "InvalidProjectName" assert client.post(url, json={}).status_code == 400 - # public project - response = client.post(url, json={"name": "public_project", "public": True}) - assert response.status_code == 201 - assert response.json["public"] is True - assert Project.query.filter_by(name="public_project").first().public - # not existing workspace response = client.post("v2/workspaces/1234/projects", json={"name": "other"}) assert response.status_code == 404 From 9992d459da30afbb11a9c61bb19e4b002380a612 Mon Sep 17 00:00:00 2001 From: MarcelGeo Date: Wed, 30 Sep 2026 15:38:47 +0200 Subject: [PATCH 06/20] Upgrade necesssary beackend deps: - bump pipenv @varmar05 @harminius to 2026.8.0 - upgraded development.md --- .github/workflows/auto_tests.yml | 4 +- development.md | 69 +- server/Dockerfile | 2 +- server/Pipfile | 26 +- server/Pipfile.lock | 3541 ++++++++++++++++-------------- 5 files changed, 1977 insertions(+), 1665 deletions(-) diff --git a/.github/workflows/auto_tests.yml b/.github/workflows/auto_tests.yml index 0f7596e3..b868ae0a 100644 --- a/.github/workflows/auto_tests.yml +++ b/.github/workflows/auto_tests.yml @@ -44,8 +44,8 @@ jobs: run: | cd server sudo apt-get -y install libsqlite3-mod-spatialite - pip install pipenv==2026.0.3 - pipenv install --dev --verbose --python 3.12 + pip install pipenv==2026.8.0 + pipenv install --dev --deploy --verbose --python 3.12 - name: Run tests run: | diff --git a/development.md b/development.md index 87a42a68..1595362e 100644 --- a/development.md +++ b/development.md @@ -4,34 +4,47 @@ This page contains useful information for those who wish to develop Mergin. ## Running locally (for dev) + Install dependencies and run services: ### Postgres and Redis ```shell -$ docker run -d --rm --name mergin_maps_dev_db -p 5002:5432 -e POSTGRES_PASSWORD=postgres postgres:14 -$ docker run -d --rm --name mergin_maps_dev_redis -p 6379:6379 redis +docker run -d --rm --name mergin_maps_dev_db -p 5002:5432 -e POSTGRES_PASSWORD=postgres postgres:14 +docker run -d --rm --name mergin_maps_dev_redis -p 6379:6379 redis ``` ### Server + +The server requires **Python 3.12** (see `python_version` in `server/Pipfile`). If your system Python is a different version, use a separate environment, e.g. conda / miniforge or pyenv: + ```shell -$ pip3 install --upgrade pip==24.0 -$ pip3 install pipenv==2024.0.1 -$ cd server +# conda / miniforge +conda create -n mergin python=3.12 +conda activate mergin +# or pyenv +pyenv install 3.12 +pyenv local 3.12 +``` + +Pipenv then creates its own virtualenv on top of that interpreter. + +```shell +pip install pipenv==2026.8.0 +cd server # Install dependencies with pipenv -# Note: You can append --three flag in older versions of pipenv (< 3.16.8 2023-02-04) -$ pipenv install --dev -$ pipenv install --categories="telemetry -$ pipenv run pre-commit install -$ pipenv run pre-commit run --all-files -$ export FLASK_APP=application; export COLLECT_STATISTICS=0 -$ pipenv run flask init-db +pipenv install --dev --deploy +pipenv install --categories="telemetry" --deploy +pipenv run pre-commit install +pipenv run pre-commit run --all-files +export FLASK_APP=application; export COLLECT_STATISTICS=0 +pipenv run flask init-db # create admin user -$ pipenv run flask user create admin topsecret --is-admin --email admin@example.com +pipenv run flask user create admin topsecret --is-admin --email admin@example.com # create (non admin) user -$ pipenv run flask user create user topsecret --email user@example.com -$ pipenv run celery -A application.celery worker --loglevel=info & -$ pipenv run flask run # run dev server on port 5000 +pipenv run flask user create user topsecret --email user@example.com +pipenv run celery -A application.celery worker --loglevel=info & +pipenv run flask run # run dev server on port 5000 ``` ### Web applications @@ -39,12 +52,12 @@ $ pipenv run flask run # run dev server on port 5000 Before installing the web applications, make sure you have Node.js installed in a supported version. The applications require Node.js version **18 or higher**. ```shell -$ cd web-app -$ yarn install -$ yarn link:dependencies # link dependencies -$ yarn build:libs # bild libraries @mergin/lib @mergin/admin-lib @mergin/lib-vue2 -$ yarn dev # development client web application dev server on port 8080 (package @mergin/app) -$ yarn dev:admin # development admin application dev server on port 8081 (package @mergin/admin-app) +cd web-app +yarn install +yarn link:dependencies # link dependencies +yarn build:libs # bild libraries @mergin/lib @mergin/admin-lib @mergin/lib-vue2 +yarn dev # development client web application dev server on port 8080 (package @mergin/app) +yarn dev:admin # development admin application dev server on port 8081 (package @mergin/admin-app) ``` If you are developing a library package (named **-lib*), it is useful to watch the library for changes instead of rebuilding it each time. @@ -60,7 +73,6 @@ yarn watch:lib:types Watching the type definitions is also useful to pick up any changes to imports or new components that are added. - ## Running locally in a docker composition If you want to run the whole stack locally, you can use the docker. Docker will build the images from your local files and run the services. @@ -97,6 +109,7 @@ docker exec -it merginmaps-server flask server send-check-email --email admin@e In docker-compose.dev.yml is started maildev/maildev image that can be used to test emails (see [https://github.com/maildev/maildev/](https://github.com/maildev/maildev/)). In localhost:1080 you can see the emails sent by the application in web interface. ### Running with remote debugger + If you want to run the application with remote debugger, you can use debug compose file with attached source code and reload. It starts a debugpy session on port 5678 you can attach to. @@ -105,10 +118,12 @@ docker compose -f docker-compose.yml -f docker-compose.debug.yml up ``` ## Running tests + To launch the unit tests run: + ```shell -$ docker run -d --rm --name testing_pg -p 5435:5432 -e POSTGRES_PASSWORD=postgres postgres:14 -$ cd server -$ pipenv install --dev --sequential --verbose -$ pipenv run pytest -v --cov=mergin mergin/tests +docker run -d --rm --name testing_pg -p 5435:5432 -e POSTGRES_PASSWORD=postgres postgres:14 +cd server +pipenv install --dev --deploy --verbose +pipenv run pytest -v --cov=mergin mergin/tests ``` diff --git a/server/Dockerfile b/server/Dockerfile index 7b13a202..c5855686 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -30,7 +30,7 @@ WORKDIR /app # keep installing to system packages ENV PIP_BREAK_SYSTEM_PACKAGES=1 -RUN pip install pipenv==2026.0.3 +RUN pip install pipenv==2026.8.0 # for locale check this http://click.pocoo.org/5/python3/ ENV LC_ALL=C.UTF-8 ENV LANG=C.UTF-8 diff --git a/server/Pipfile b/server/Pipfile index 36f28d48..552741d0 100644 --- a/server/Pipfile +++ b/server/Pipfile @@ -5,9 +5,9 @@ name = "pypi" [packages] connexion = {extras = ["swagger-ui"],version = "==2.15.1"} -flask = "==3.1.2" +flask = "==3.1.3" python-dateutil = "==2.8.2" -marshmallow = "==3.26.1" +marshmallow = "==3.26.2" flask-marshmallow = "==0.15.0" marshmallow-sqlalchemy = "==1.4.1" psycopg2-binary = "==2.9.9" @@ -15,7 +15,7 @@ itsdangerous = "==2.2.0" Flask-SQLAlchemy = "==3.1.1" sqlalchemy = "==2.0.44" gunicorn = {extras = ["gevent"],version = "==23.0"} -python-dotenv = "==0.20.0" +python-dotenv = "==1.2.2" flask-login = "==0.6.3" bcrypt = "==4.2.0" wtforms = {extras = ["email"],version = "==3.2.1"} @@ -35,34 +35,36 @@ jsons = "==1.6.3" binaryornot = "==0.4.4" chardet = "<5" python-decouple = "==3.6" -urllib3 = "==2.2.2" +urllib3 = "==2.7.0" shapely = "==2.0.6" psycogreen = "==1.0.2" importlib-metadata = "==8.4.0" # https://github.com/pallets/flask/issues/4502 typing_extensions = "==4.12.2" python-magic = "==0.4.27" -click = "==8.2.0" +click = "==8.3.3" # requirements for development on windows colorama = "==0.4.5" [dev-packages] -pytest = "==8.3.2" +pytest = "==9.1.1" pytest-cov = "==5.0.0" pylint = "==3.2.6" responses = "==0.21.0" pytest-dotenv= "==0.5.2" -pysqlite3-binary= "==0.5.3" +# sqlite with loadable extensions for tests, pysqlite3-binary wheels are available only for linux +pysqlite3-binary = {version = "==0.5.3", markers = "sys_platform == 'linux'"} +pysqlite3 = {version = "==0.6.0", markers = "sys_platform != 'linux'"} black = "==25.1.0" pre-commit = "==4.1.0" # requirements for pytest on windows atomicwrites = "==1.4.0" [telemetry] -opentelemetry-distro = {extras = ["otlp"], version = "*"} -opentelemetry-instrumentation-flask = "*" -opentelemetry-instrumentation-celery = "*" -opentelemetry-instrumentation-sqlalchemy = "*" -opentelemetry-instrumentation-logging = "*" +opentelemetry-distro = {extras = ["otlp"], version = "==0.60b1"} +opentelemetry-instrumentation-flask = "==0.60b1" +opentelemetry-instrumentation-celery = "==0.60b1" +opentelemetry-instrumentation-sqlalchemy = "==0.60b1" +opentelemetry-instrumentation-logging = "==0.60b1" [requires] python_version = "3.12" diff --git a/server/Pipfile.lock b/server/Pipfile.lock index f805dff1..af4c6204 100644 --- a/server/Pipfile.lock +++ b/server/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "fe72eb8031cd715c5c8a8a080d92bc032a8f2ead54526bd7d39a5ffa97e2bce7" + "sha256": "250ff3b20424d27421a771e1618f66d389b07456cf88e45274d1f9f148ddc069" }, "pipfile-spec": 6, "requires": { @@ -18,137 +18,136 @@ "default": { "aiohappyeyeballs": { "hashes": [ - "sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558", - "sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8" + "sha256:065665c041c42a5938ed220bdcd7230f22527fbec085e1853d2402c8a3615d9d", + "sha256:9243213661e29250eb41368e5daa826fc017156c3b8a11440826b2e3ed376472" ], - "markers": "python_version >= '3.9'", - "version": "==2.6.1" + "markers": "python_version >= '3.10'", + "version": "==2.7.1" }, "aiohttp": { "hashes": [ - "sha256:019a67772e034a0e6b9b17c13d0a8fe56ad9fb150fc724b7f3ffd3724288d9e5", - "sha256:02222e7e233295f40e011c1b00e3b0bd451f22cf853a0304c3595633ee47da4b", - "sha256:023ecba036ddd840b0b19bf195bfae970083fd7024ce1ac22e9bba90464620e9", - "sha256:02e048037a6501a5ec1f6fc9736135aec6eb8a004ce48838cb951c515f32c80b", - "sha256:0494a01ca9584eea1e5fbd6d748e61ecff218c51b576ee1999c23db7066417d8", - "sha256:0f7a18f258d124cd678c5fe072fe4432a4d5232b0657fca7c1847f599233c83a", - "sha256:10a75acfcf794edf9d8db50e5a7ec5fc818b2a8d3f591ce93bc7b1210df016d2", - "sha256:110e448e02c729bcebb18c60b9214a87ba33bac4a9fa5e9a5f139938b56c6cb1", - "sha256:147b4f501d0292077f29d5268c16bb7c864a1f054d7001c4c1812c0421ea1ed0", - "sha256:157826e2fa245d2ef46c83ea8a5faf77ca19355d278d425c29fda0beb3318037", - "sha256:15c933ad7920b7d9a20de151efcd05a6e38302cbf0e10c9b2acb9a42210a2416", - "sha256:178c7b5e62b454c2bc790786e6058c3cc968613b4419251b478c153a4aec32b1", - "sha256:18a2f6c1182c51baa1d28d68fea51513cb2a76612f038853c0ad3c145423d3d9", - "sha256:1efb06900858bb618ff5cee184ae2de5828896c448403d51fb633f09e109be0a", - "sha256:20058e23909b9e65f9da62b396b77dfa95965cbe840f8def6e572538b1d32e36", - "sha256:206b7b3ef96e4ce211754f0cd003feb28b7d81f0ad26b8d077a5d5161436067f", - "sha256:20ae0ff08b1f2c8788d6fb85afcb798654ae6ba0b747575f8562de738078457b", - "sha256:2294172ce08a82fb7c7273485895de1fa1186cc8294cfeb6aef4af42ad261174", - "sha256:241a94f7de7c0c3b616627aaad530fe2cb620084a8b144d3be7b6ecfe95bae3b", - "sha256:26d2f8546f1dfa75efa50c3488215a903c0168d253b75fba4210f57ab77a0fb8", - "sha256:2837fb92951564d6339cedae4a7231692aa9f73cbc4fb2e04263b96844e03b4e", - "sha256:2994be9f6e51046c4f864598fd9abeb4fba6e88f0b2152422c9666dcd4aea9c6", - "sha256:2d6d44a5b48132053c2f6cd5c8cb14bc67e99a63594e336b0f2af81e94d5530c", - "sha256:31cebae8b26f8a615d2b546fee45d5ffb76852ae6450e2a03f42c9102260d6fe", - "sha256:327cc432fdf1356fb4fbc6fe833ad4e9f6aacb71a8acaa5f1855e4b25910e4a9", - "sha256:329f292ed14d38a6c4c435e465f48bebb47479fd676a0411936cc371643225cc", - "sha256:330f5da04c987f1d5bdb8ae189137c77139f36bd1cb23779ca1a354a4b027800", - "sha256:33add2463dde55c4f2d9635c6ab33ce154e5ecf322bd26d09af95c5f81cfa286", - "sha256:347542f0ea3f95b2a955ee6656461fa1c776e401ac50ebce055a6c38454a0adf", - "sha256:39380e12bd1f2fdab4285b6e055ad48efbaed5c836433b142ed4f5b9be71036a", - "sha256:3a807cabd5115fb55af198b98178997a5e0e57dead43eb74a93d9c07d6d4a7dc", - "sha256:3b13560160d07e047a93f23aaa30718606493036253d5430887514715b67c9d9", - "sha256:3df334e39d4c2f899a914f1dba283c1aadc311790733f705182998c6f7cae665", - "sha256:4bb6bf5811620003614076bdc807ef3b5e38244f9d25ca5fe888eaccea2a9832", - "sha256:4beac52e9fe46d6abf98b0176a88154b742e878fdf209d2248e99fcdf73cd297", - "sha256:4e704c52438f66fdd89588346183d898bb42167cf88f8b7ff1c0f9fc957c348f", - "sha256:4eac02d9af4813ee289cd63a361576da36dba57f5a1ab36377bc2600db0cbb73", - "sha256:53fc049ed6390d05423ba33103ded7281fe897cf97878f369a527070bd95795b", - "sha256:55b3bdd3292283295774ab585160c4004f4f2f203946997f49aac032c84649e9", - "sha256:57653eac22c6a4c13eb22ecf4d673d64a12f266e72785ab1c8b8e5940d0e8090", - "sha256:60869c7ac4aaabe7110f26499f3e6e5696eae98144735b12a9c3d9eae2b51a49", - "sha256:636bc362f0c5bbc7372bc3ae49737f9e3030dbce469f0f422c8f38079780363d", - "sha256:676e5651705ad5d8a70aeb8eb6936c436d8ebbd56e63436cb7dd9bb36d2a9a46", - "sha256:69f571de7500e0557801c0b51f4780482c0ec5fe2ac851af5a92cfce1af1cb83", - "sha256:6a7cbeb06d1070f1d14895eeeed4dac5913b22d7b456f2eb969f11f4b3993796", - "sha256:6cf81fe010b8c17b09495cbd15c1d35afbc8fb405c0c9cf4738e5ae3af1d65be", - "sha256:6e27ea05d184afac78aabbac667450c75e54e35f62238d44463131bd3f96753d", - "sha256:6f1cbf0c7926d315c3c26c2da41fd2b5d2fe01ac0e157b78caefc51a782196cf", - "sha256:6f497a6876aa4b1a102b04996ce4c1170c7040d83faa9387dd921c16e30d5c83", - "sha256:756c3c304d394977519824449600adaf2be0ccee76d206ee339c5e76b70ded25", - "sha256:77dfa48c9f8013271011e51c00f8ada19851f013cde2c48fca1ba5e0caf5bb06", - "sha256:7996023b2ed59489ae4762256c8516df9820f751cf2c5da8ed2fb20ee50abab3", - "sha256:7ab7229b6f9b5c1ba4910d6c41a9eb11f543eadb3f384df1b4c293f4e73d44d6", - "sha256:7becdf835feff2f4f335d7477f121af787e3504b48b449ff737afb35869ba7bb", - "sha256:7c35b0bf0b48a70b4cb4fc5d7bed9b932532728e124874355de1a0af8ec4bc88", - "sha256:7c4b6668b2b2b9027f209ddf647f2a4407784b5d88b8be4efcc72036f365baf9", - "sha256:7e5dc4311bd5ac493886c63cbf76ab579dbe4641268e7c74e48e774c74b6f2be", - "sha256:888e78eb5ca55a615d285c3c09a7a91b42e9dd6fc699b166ebd5dee87c9ccf14", - "sha256:898703aa2667e3c5ca4c54ca36cd73f58b7a38ef87a5606414799ebce4d3fd3a", - "sha256:8b14eb3262fad0dc2f89c1a43b13727e709504972186ff6a99a3ecaa77102b6c", - "sha256:8bd3ec6376e68a41f9f95f5ed170e2fcf22d4eb27a1f8cb361d0508f6e0557f3", - "sha256:8cf20a8d6868cb15a73cab329ffc07291ba8c22b1b88176026106ae39aa6df0f", - "sha256:8f14c50708bb156b3a3ca7230b3d820199d56a48e3af76fa21c2d6087190fe3d", - "sha256:8f546a4dc1e6a5edbb9fd1fd6ad18134550e096a5a43f4ad74acfbd834fc6670", - "sha256:912d4b6af530ddb1338a66229dac3a25ff11d4448be3ec3d6340583995f56031", - "sha256:9277145d36a01653863899c665243871434694bcc3431922c3b35c978061bdb8", - "sha256:95d14ca7abefde230f7639ec136ade282655431fd5db03c343b19dda72dd1643", - "sha256:999802d5fa0389f58decd24b537c54aa63c01c3219ce17d1214cbda3c2b22d2d", - "sha256:9a0f4474b6ea6818b41f82172d799e4b3d29e22c2c520ce4357856fced9af2f8", - "sha256:9b16c653d38eb1a611cc898c41e76859ca27f119d25b53c12875fd0474ae31a8", - "sha256:9d98cc980ecc96be6eb4c1994ce35d28d8b1f5e5208a23b421187d1209dbb7d1", - "sha256:9efcc0f11d850cefcafdd9275b9576ad3bfb539bed96807663b32ad99c4d4b88", - "sha256:a2567b72e1ffc3ab25510db43f355b29eeada56c0a622e58dcdb19530eb0a3cb", - "sha256:a5029cc80718bbd545123cd8fe5d15025eccaaaace5d0eeec6bd556ad6163d61", - "sha256:a60eaa2d440cd4707696b52e40ed3e2b0f73f65be07fd0ef23b6b539c9c0b0b4", - "sha256:a79a6d399cef33a11b6f004c67bb07741d91f2be01b8d712d52c75711b1e07c7", - "sha256:a84792f8631bf5a94e52d9cc881c0b824ab42717165a5579c760b830d9392ac9", - "sha256:a8a4d3427e8de1312ddf309cc482186466c79895b3a139fed3259fc01dfa9a5b", - "sha256:a8aca50daa9493e9e13c0f566201a9006f080e7c50e5e90d0b06f53146a54500", - "sha256:aa6d0d932e0f39c02b80744273cd5c388a2d9bc07760a03164f229c8e02662f6", - "sha256:ab2899f9fa2f9f741896ebb6fa07c4c883bfa5c7f2ddd8cf2aafa86fa981b2d2", - "sha256:af545c2cffdb0967a96b6249e6f5f7b0d92cdfd267f9d5238d5b9ca63e8edb10", - "sha256:b18f31b80d5a33661e08c89e202edabf1986e9b49c42b4504371daeaa11b47c1", - "sha256:b20df693de16f42b2472a9c485e1c948ee55524786a0a34345511afdd22246f3", - "sha256:b38765950832f7d728297689ad78f5f2cf79ff82487131c4d26fe6ceecdc5f8e", - "sha256:b6f6cd1560c5fa427e3b6074bb24d2c64e225afbb7165008903bd42e4e33e28a", - "sha256:bace460460ed20614fa6bc8cb09966c0b8517b8c58ad8046828c6078d25333b5", - "sha256:bca9ef7517fd7874a1a08970ae88f497bf5c984610caa0bf40bd7e8450852b95", - "sha256:c180f480207a9b2475f2b8d8bd7204e47aec952d084b2a2be58a782ffcf96074", - "sha256:c2b2355dc094e5f7d45a7bb262fe7207aa0460b37a0d87027dcf21b5d890e7d5", - "sha256:c564dd5f09ddc9d8f2c2d0a301cd30a79a2cc1b46dd1a73bef8f0038863d016b", - "sha256:c632ce9c0b534fbe25b52c974515ed674937c5b99f549a92127c85f771a78772", - "sha256:c719f65bebcdf6716f10e9eff80d27567f7892d8988c06de12bbbd39307c6e3a", - "sha256:c86969d012e51b8e415a8c6ce96f7857d6a87d6207303ab02d5d11ef0cad2274", - "sha256:c974fb66180e58709b6fc402846f13791240d180b74de81d23913abe48e96d94", - "sha256:c9883051c6972f58bfc4ebb2116345ee2aa151178e99c3f2b2bbe2af712abd13", - "sha256:ca9ac61ac6db4eb6c2a0cd1d0f7e1357647b638ccc92f7e9d8d133e71ed3c6ac", - "sha256:cb979826071c0986a5f08333a36104153478ce6018c58cba7f9caddaf63d5d67", - "sha256:cd3db5927bf9167d5a6157ddb2f036f6b6b0ad001ac82355d43e97a4bde76d76", - "sha256:d147004fede1b12f6013a6dbb2a26a986a671a03c6ea740ddc76500e5f1c399f", - "sha256:d3a4834f221061624b8887090637db9ad4f61752001eae37d56c52fddade2dc8", - "sha256:d9010032a0b9710f58012a1e9c222528763d860ba2ee1422c03473eab47703e7", - "sha256:d97f93fdae594d886c5a866636397e2bcab146fd7a132fd6bb9ce182224452f8", - "sha256:df23d57718f24badef8656c49743e11a89fd6f5358fa8a7b96e728fda2abf7d3", - "sha256:df6104c009713d3a89621096f3e3e88cc323fd269dbd7c20afe18535094320be", - "sha256:e5e5f7debc7a57af53fdf5c5009f9391d9f4c12867049d509bf7bb164a6e295b", - "sha256:e7d2f8616f0ff60bd332022279011776c3ac0faa0f1b463f7bb12326fbc97a1c", - "sha256:e999f0c88a458c836d5fb521814e92ed2172c649200336a6df514987c1488258", - "sha256:eb4639f32fd4a9904ab8fb45bf3383ba71137f3d9d4ba25b3b3f3109977c5b8c", - "sha256:ec707059ee75732b1ba130ed5f9580fe10ff75180c812bc267ded039db5128c6", - "sha256:ecc26751323224cf8186efcf7fbcbc30f4e1d8c7970659daf25ad995e4032a56", - "sha256:ee5e86776273de1795947d17bddd6bb19e0365fd2af4289c0d2c5454b6b1d36b", - "sha256:f1162a1492032c82f14271e831c8f4b49f2b6078f4f5fc74de2c912fa225d51d", - "sha256:f34ecee82858e41dd217734f0c41a532bd066bcaab636ad830f03a30b2a96f2a", - "sha256:f85c6f327bf0b8c29da7d93b1cabb6363fb5e4e160a32fa241ed2dce21b73162", - "sha256:f92995dfec9420bb69ae629abf422e516923ba79ba4403bc750d94fb4a6c68c1", - "sha256:fb0540c854ac9c0c5ad495908fdfd3e332d553ec731698c0e29b1877ba0d2ec6", - "sha256:fceedde51fbd67ee2bcc8c0b33d0126cc8b51ef3bbde2f86662bd6d5a6f10ec5", - "sha256:fe6970addfea9e5e081401bcbadf865d2b6da045472f58af08427e108d618540", - "sha256:fee86b7c4bd29bdaf0d53d14739b08a106fdda809ca5fe032a15f52fae5fe254" + "sha256:03cd2bde3d7f085b64e549c985f4bb928cad7e8ecf5323bfca320db548d81b39", + "sha256:041badb8f84396357c4d3ad26de6afd7a32b112f43d3c63045c0c8278cfd2043", + "sha256:0a5ff2dfbb9ce645fa5b8ef3e02c6c0b9cc3f6030ff863d0c51fffc50cb5541b", + "sha256:0fdea2281997af69da84c77ffa6f5938a0285f21fb3887c249d67419ca865b3d", + "sha256:11fb37ef075669eee52ab1928fbf6e1741fada40409fa309ebde9607a962aebf", + "sha256:134ac5ddcf61c6fad984b9a5727d83492ada43d63471db20fb73042c13fca62f", + "sha256:152516815ef926786a0b6ae2b8f1fd2e0c71582dee0b435636865316fd4891b7", + "sha256:1576145bdceeb92382d899751e12743a3a5b8e460a841e3e50543859e54864dc", + "sha256:16100ad3ab8d649fdfbee87602d9d2dcdca9df0b9eda8a1b5fdc0d41f96da559", + "sha256:16ea7e24c309fb7c0bbd505d149abe4fe4dccfb8db911db7dbec0921bc889a6f", + "sha256:18c441d0a8fca6de8d1f546849b9f0ab20d435993e2c5b59562b2fae6be2f929", + "sha256:18cb43369747b2ae007bd2655fb8e63a099c2ff1d207962943636dac989b3147", + "sha256:1b59533861b70a2185c8f4f350f791f39d64358ef6944ce71c5240c9ec0982c9", + "sha256:1c5281acc88b92396f88c7e1e2748f8466689df22b80170e4f51efa712fb47a8", + "sha256:1c5ec8fb1bcc31a8466f74aaf26c345d5c386fa4bd08a3f0eb9c7a4a3fe8b5bf", + "sha256:1caa7b0d05f3e3a36f87788c59e970a7ee1cefcfcbb924a9f138c4a6551c9cb7", + "sha256:21c016079415ed3fd676963e9793700a566d85dbbd6bfc564b9b2d209147dcc8", + "sha256:2498f0fe69ead802f9675beca44a7c21c62fdaa4ec5145ea1c3ad6edbee29f85", + "sha256:25bd2708db6bdf6a6630dd37bdcdfcb47c4434d22ac69c64665b802910140b30", + "sha256:270d3dace9ca2f10f0da5d8ebe519b7a310fc6112ed916e32df5866df0888553", + "sha256:2e1161602f45a54de2ce0905243a95f58cb42dcd378402f3697f5e0b21e9d2e7", + "sha256:2e9878ae68e4a5f1c0abe4dd497dbc3d51946f5837b56759e2a02e78fa90ef86", + "sha256:30402d03a7c0ff52bce290b57e564e9079fd9d0cb545c8aba73f86a103162d2e", + "sha256:33a2d7c28d33797a2e99923dffa63f83d908a19b6bf26cfe80fa790aa5e1a75a", + "sha256:362a3fd481769cac1a824514bcd86fda51c65e8fe6e051099e008fddde6db17c", + "sha256:38901a84da3ce22249f6e860bf8f90d141bcab7da090cc398f8bb58c0e44b7da", + "sha256:39aded8c7f3b935b54aab1d8d73c70ec0ee2d3ec3b943e0e86611bc150ba47f5", + "sha256:3a26434dafe408229ff3403458ca58de24fb51936504decac49ce6755f77e59d", + "sha256:3ae5b3a59436d089b5395d910121a390feed4d00578eb95a0fd1a329fe963100", + "sha256:3d4f72af88ac2474bb5bca640030320e3d38a0163a1d7533500e87be458eef71", + "sha256:3f42e9b78301f11c8f861746175d8b9c1ccef713fcad9eab396e2f6db8ed4a22", + "sha256:42a67efc36300d052fb4508a53e8b6901b9284b599ae63945c377569c5fcc1e1", + "sha256:48d67b87db6279c044760787eb01f6413032c2e6f3ba1cafaa492b1c8e578479", + "sha256:498c6c623134f8e09a3c4e60bcd607a0b4590dd7dbf08dd40851b27cbb520ccb", + "sha256:49f7325beb0f85ef4aef5f48f490269575f83e6e2acad00a1d80b807eb027062", + "sha256:4e3ac92d90e92773b2362d506068e9a948192bd553e743c5b2429e28527c8661", + "sha256:530125ee1163c4219af35dc3aa1206e541e7b31b6efc1a3f93b70a136f65d427", + "sha256:5373dc80ad1aa2fb9ad95c83f24eef418bbda3a61375f128e5b0192e4f3f9b32", + "sha256:53e5179d8abb5710f8e83ba207c41c8d1261fcffd4616500e15ca2b7a33be10a", + "sha256:53e7b4ce82b54a8bcc71b3b67a5cbd177ca1d7f592cbc92cd38b7349f73482db", + "sha256:543906c127fb1d929b95076db19b83fa2d46751006ff1e23b093aa5ac4d8db42", + "sha256:54cfcdee2770dac994417cbb0ee1f3eb0e7cb6b30c79bf44f2c02ff79ec5124a", + "sha256:55bdcc472aafe2de4a253045cc128007a64f1e0264fb675791e132ea5edaa3bd", + "sha256:56f355e79f71aef2a85c80305cc915f894b170dba76de5fe84f6351939b83c06", + "sha256:5895ef58c4620afe02fa16044f023dc4dafec08158f9d08874a46a7dbc0341b8", + "sha256:5bcb6ff3fdab1258a192679ff1a05d44f59626430aa05cd1a9d2447423599228", + "sha256:5f08ec777f35ee70720233b8b9811d3bb5d728137f30ac91b7457709c3261ac0", + "sha256:614c61d478b83953e261d02bb2df750f17227cd33ef8002945bf5aebbde21919", + "sha256:617105e2c3018ee38d0c8ce5ee3c84f621a6d8b9f723202aacaff28449ca91ee", + "sha256:6debfa7312ff9d4c124dc71d72e9a0a4b9e0879e48ba6fcb42bef5c3300289e2", + "sha256:7041d52c3a7fa20c9e8c182b534704abb19502c8bdcbde7ab23bfda6f642394f", + "sha256:70c987b27534f9ae1a723f47ae921571d616da21d3208282bf4c52af5164ac43", + "sha256:74ab5b6a9fb13e873e5a90946588baecaf488745e1db1a4a5c433f971f035098", + "sha256:78253b573e6ffab5028924fc98bc281aae05445969982a10864bc360dea2016c", + "sha256:7a75aa63cbf9b21cfaf60dc2657e19df2c2867d91707d653fee171ffeedd1371", + "sha256:8800c996b01c2772a783e3e46f3e1abd5823029adca0df54231960de9bfefa5b", + "sha256:89176250f686cb9853c0fb7ead90e639e915b84a6f43eedc2a4e7ec21f1037f0", + "sha256:8a5fd34f7f7410d1730d5c2ba873cacb2eed3fede366feb268a70ba22581ed8f", + "sha256:8b3b60de05f3dcb6f6a00f818bb2ec781cee4de0645f59ccaf99b1d1823b6100", + "sha256:8f2f1c4c032c7cedd7d8da6f54c97b70266c6570c3108d3fdffee7188bb70529", + "sha256:9491196535a88924a60afd5b5f434b5b203b6cc616250878dbdb223a8f7844bc", + "sha256:9aa6e61fdf20105c4144e755bd586008ff450791d67b1c8146fdc15959c4d51c", + "sha256:9d9edccfe496b476db5f398d97b865e9a6752bcf8aec4eef8390ce20fb64bb41", + "sha256:9fc7b5bfec6573f3ae844f457fdde5adeb713f8b8e4a81ad64fc207b49383716", + "sha256:a0dc483c00da8b673abbb367eb6f8d8f4bcec30eb58529ea13cb42e7fd2dfa33", + "sha256:a3a8296e7ab5c295f53f1041487cb088e1480775aafbf7fe545d93b770a0f96f", + "sha256:a3e22975f905b89a55a488c2a08f2fdb2186175349e917d48985cc468a3d4c6e", + "sha256:a4af35c443e0b1a1bd6a8af3f3485d7fda15c142751a00f3ff8090f0b93346fa", + "sha256:a94dbaae5ae27bd849c93570669bff91e0510f33a80805738e3de72a7be0447b", + "sha256:ac74facc01463f138b0da5580329cfcc82818dea5656e83ddcd11268fc12ff80", + "sha256:ad4c8b7488d745d2ca4838ebd8ae5ba9b56341d30b1da43640e4ce87f9f49646", + "sha256:b014a6ed7cf912e787149fdc529166d3ceabac23f26efeea3158c9aba2354e7e", + "sha256:b20032766aedf6261c7a566585a40867d092ac03a0d81592d5370ef9b054f99b", + "sha256:b2466434105a4e03113c36ec775cc2ebe6676b62eae326fa670bb607ef788c1c", + "sha256:b304db572b4368edd8dda8a2274f73156fe15558fca4a917cb8a09fc47af5963", + "sha256:ba59d59aba08ac02fc03b0c8983ccd5ee39a199d0552ce9e6d2b4845b34d59ae", + "sha256:bd52f811e65f6fb634b1047159657c98f52b407f8efec907bcfc09da9a4c0a25", + "sha256:bdd0e2834dce1a26c1bbe26464861e16bbe217042cbff619247c11594472518c", + "sha256:c23ec8ee9d5ab2f5421f9c7fffce208435607af27fd46d4a44e031954352838f", + "sha256:c39846c3aad97a8530c89d7a3869a8f8e9e3762c6ac0504481e5c80948f7e807", + "sha256:c3c200cf9757edd785051dc699c7ecbec22110dbfcb3fefc7a9f9695eda8ea7a", + "sha256:c7d3a97c678d34fc5b59da671ee9cd630096ddc643e7b5a30d54a2a6f3574d3f", + "sha256:c8653fd547c93a61aadc612007790f5555cdd18946fa48cf45e26d8ea4ea473d", + "sha256:cc7cb243a68167172f48c1fd43cee91ec4b1d40cefd190edd43369d1a6bc9c82", + "sha256:ccd4893707b3e2a13e39c90d43cf80edf2e4d0457935bcc103bf2346214c3f15", + "sha256:cd817772b2fcf2b8c0905795318485f9ec16eae60b29feb7f4c77085311637f0", + "sha256:cda5fd5c95ad7a125a2e8464acc78b98b94c475a3780d6aa0aa157c93f470f4d", + "sha256:cef89a58e628c4efcac3275c2d68083f82426dcdc89c1492a6f654f9f7ea6ab9", + "sha256:d1558173930a5a8d3069cee5c92fc91c87c4dbcb099debbb3622053717145a19", + "sha256:d6088ec9894113802bddb3c09e974929aed2c7b3a8c456219b8aab4481f1a239", + "sha256:d6218d92e450824e9b4881f44e8c09f1853b490f9a64130801024a4793b1b3b0", + "sha256:d77640cc618c1d99fc4f8589c0f24a730adfa54eb1e57ef7bf0c8dfb78da898c", + "sha256:d7d2deec16eeedf55f2c7cf75b521ea3856a5177e123844f8fd0f114ce252cb5", + "sha256:db332af25642007330fca8be5c4d194caf2bea7a7fc84415aff3497af5dfee6b", + "sha256:dd54d0e8717de95939766febac482ac0474d8ac3b048115f9f2b1d23a16e7db4", + "sha256:ddcac3c6b382e81f1dd0499199d4136b877beb4cb5ef770bbbfba56c4b8f55d2", + "sha256:df82f3787c940c94986b34222d59c9e38843fba85139f36e85255a82ad5355a9", + "sha256:dfa68deb2a443bdaa3ea5297b0699c1464f08aef3812b486d1348eee61b07dc0", + "sha256:dff9461ec275f22135650d5ba4b4931a11f3958df7dfbb8db630000d4dee0883", + "sha256:e1e74298bab6ee0d6e749ed4fd1901c7e604bdda32c03d787a2cc71c46d0433d", + "sha256:e2667f0bbe7eb6c74eae5e9691441ad186e5845ca3cff63230fc09c4e7514f5d", + "sha256:e3be98a7c30b8c25d573dafba7171d66dfb05ee6a9070fc46535464ff97700a6", + "sha256:e568e14940c09955aa51f4e645b6daa18a581c5dcfcd73744dcc86a856e3ced3", + "sha256:e72ee89e28d907a18f46959b4eb0bb06701cc7f8cf4366e00029e2ccfaaf5924", + "sha256:e92eb8acc45eb6a9f4935071a77edf5b85cc6f8dfad5cd99e97653c26593cdde", + "sha256:ea05e1f97ceea523942d9b2a7d7c0359d781d683d6b043f5943a602b14da4787", + "sha256:eac645b09bcfdf73df7536331f0678c1086ea250981118ddb5199e17ccef72bb", + "sha256:eb0495d778817619273c108784292be161a924b9f5ae5cbbc70a2caa6838250b", + "sha256:ebe8e504f058fe91223351cecd2d9d6946c9d241bb0250d898ffbdf584cc72b0", + "sha256:ed099d105449c4f9e84f24af203cd131349d4761d8813fa7e02c32e7128cd910", + "sha256:f0f177d1b195b9e06376cfd7d308d8a1b920909a609d03ac82a8c73bbb16d3b9", + "sha256:f3d2669fe7dec7fc359ecdb5984b29b50d85d5d00f8c1cb61de4f4a24ee42627", + "sha256:f4e05329faa0ea1a404b37de4f034fd2c2defcca06a68dc6745e4e56c88e8a48", + "sha256:f53bcd52f585e1ac3e590d61434eb61f9a88c38df041b4ea126d97144344a77b", + "sha256:f55119f7bf25f49ed210f6096090715da24f2943c62102448915fde3c62877ce", + "sha256:f631fe87a6f30df5fbe6d79640b25e4cffb38c31c7fb6f10871517b84b0f8c1a", + "sha256:f8fb78a83c9e5f741ca3a68cfb455c1f5bb83b4e7249a3848b3cd78d0a8563b0", + "sha256:fa9467a8113aa69d3d7c55a70ef0b7c636010a40993f3df9d9d0d73b3eb7ef24", + "sha256:fd51ebf9d3a00c074df4ede271023f4d2dba289bcc740b88191872716014e3c5" ], - "markers": "python_version >= '3.9'", - "version": "==3.13.5" + "markers": "python_version >= '3.10'", + "version": "==3.14.3" }, "aiohttp-jinja2": { "hashes": [ @@ -168,19 +167,19 @@ }, "alembic": { "hashes": [ - "sha256:a5ed4adcf6d8a4cb575f3d759f071b03cd6e5c7618eb796cb52497be25bfe19a", - "sha256:cb6e1fd84b6174ab8dbb2329f86d631ba9559dd78df550b57804d607672cedbc" + "sha256:77eb101048d95f982c0353e9233404889dcd7a6fc244c107836c0e2fc9cf7d9d", + "sha256:db505480647bc60386c5369402f4a57a506b7539c9e9ef5e270d45cbbe4939bf" ], "markers": "python_version >= '3.10'", - "version": "==1.18.4" + "version": "==1.20.0" }, "amqp": { "hashes": [ - "sha256:43b3319e1b4e7d1251833a93d672b4af1e40f3d632d479b98661a95f117880a2", - "sha256:cddc00c725449522023bad949f70fff7b48f0b1ade74d170a6f10ab044739432" + "sha256:5d931d8442a403b6d4a5725a868a55edaa40734eae37d282b16be9fa710bd8ee", + "sha256:aaa33987dcb6a7893955d3b4f537c5d4755addce1009929e63e5d18c1b51a0a7" ], - "markers": "python_version >= '3.6'", - "version": "==5.3.1" + "markers": "python_version >= '3.10'", + "version": "==5.4.0" }, "attrs": { "hashes": [ @@ -226,11 +225,11 @@ }, "billiard": { "hashes": [ - "sha256:525b42bdec68d2b983347ac312f892db930858495db601b5836ac24e6477cde5", - "sha256:55f542c371209e03cd5862299b74e52e4fbcba8250ba611ad94276b369b6a85f" + "sha256:3ddeaf82c0373e076c7b450c2fdc7ded6d73981bcfd931da1cdd0c0a03468dc5", + "sha256:be3e51fb6202df38e1d67ff0aa3bfa4cdc1838a3c47c36373cc3220c6b787c2a" ], - "markers": "python_version >= '3.7'", - "version": "==4.2.4" + "markers": "python_version >= '3.10'", + "version": "==4.3.0" }, "binaryornot": { "hashes": [ @@ -259,11 +258,11 @@ }, "certifi": { "hashes": [ - "sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa", - "sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7" + "sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775", + "sha256:741e2c3b351ddf169a738da9f2c048608ff7f2c5cc02f1ebc6b118bb090d5d55" ], "markers": "python_version >= '3.7'", - "version": "==2026.2.25" + "version": "==2026.7.22" }, "chardet": { "hashes": [ @@ -276,147 +275,190 @@ }, "charset-normalizer": { "hashes": [ - "sha256:06a7e86163334edfc5d20fe104db92fcd666e5a5df0977cb5680a506fe26cc8e", - "sha256:0c173ce3a681f309f31b87125fecec7a5d1347261ea11ebbb856fa6006b23c8c", - "sha256:0e28d62a8fc7a1fa411c43bd65e346f3bce9716dc51b897fbe930c5987b402d5", - "sha256:0e901eb1049fdb80f5bd11ed5ea1e498ec423102f7a9b9e4645d5b8204ff2815", - "sha256:11afb56037cbc4b1555a34dd69151e8e069bee82e613a73bef6e714ce733585f", - "sha256:150b8ce8e830eb7ccb029ec9ca36022f756986aaaa7956aad6d9ec90089338c0", - "sha256:172985e4ff804a7ad08eebec0a1640ece87ba5041d565fff23c8f99c1f389484", - "sha256:197c1a244a274bb016dd8b79204850144ef77fe81c5b797dc389327adb552407", - "sha256:1ae6b62897110aa7c79ea2f5dd38d1abca6db663687c0b1ad9aed6f6bae3d9d6", - "sha256:1cf0a70018692f85172348fe06d3a4b63f94ecb055e13a00c644d368eb82e5b8", - "sha256:1ed80ff870ca6de33f4d953fda4d55654b9a2b340ff39ab32fa3adbcd718f264", - "sha256:22c6f0c2fbc31e76c3b8a86fba1a56eda6166e238c29cdd3d14befdb4a4e4815", - "sha256:231d4da14bcd9301310faf492051bee27df11f2bc7549bc0bb41fef11b82daa2", - "sha256:259695e2ccc253feb2a016303543d691825e920917e31f894ca1a687982b1de4", - "sha256:2a24157fa36980478dd1770b585c0f30d19e18f4fb0c47c13aa568f871718579", - "sha256:2b1a63e8224e401cafe7739f77efd3f9e7f5f2026bda4aead8e59afab537784f", - "sha256:2bd9d128ef93637a5d7a6af25363cf5dec3fa21cf80e68055aad627f280e8afa", - "sha256:2e1d8ca8611099001949d1cdfaefc510cf0f212484fe7c565f735b68c78c3c95", - "sha256:2ef7fedc7a6ecbe99969cd09632516738a97eeb8bd7258bf8a0f23114c057dab", - "sha256:2f7fdd9b6e6c529d6a2501a2d36b240109e78a8ceaef5687cfcfa2bbe671d297", - "sha256:30f445ae60aad5e1f8bdbb3108e39f6fbc09f4ea16c815c66578878325f8f15a", - "sha256:31215157227939b4fb3d740cd23fe27be0439afef67b785a1eb78a3ae69cba9e", - "sha256:34315ff4fc374b285ad7f4a0bf7dcbfe769e1b104230d40f49f700d4ab6bbd84", - "sha256:3516bbb8d42169de9e61b8520cbeeeb716f12f4ecfe3fd30a9919aa16c806ca8", - "sha256:3778fd7d7cd04ae8f54651f4a7a0bd6e39a0cf20f801720a4c21d80e9b7ad6b0", - "sha256:39f5068d35621da2881271e5c3205125cc456f54e9030d3f723288c873a71bf9", - "sha256:404a1e552cf5b675a87f0651f8b79f5f1e6fd100ee88dc612f89aa16abd4486f", - "sha256:419a9d91bd238052642a51938af8ac05da5b3343becde08d5cdeab9046df9ee1", - "sha256:423fb7e748a08f854a08a222b983f4df1912b1daedce51a72bd24fe8f26a1843", - "sha256:4482481cb0572180b6fd976a4d5c72a30263e98564da68b86ec91f0fe35e8565", - "sha256:461598cd852bfa5a61b09cae2b1c02e2efcd166ee5516e243d540ac24bfa68a7", - "sha256:47955475ac79cc504ef2704b192364e51d0d473ad452caedd0002605f780101c", - "sha256:48696db7f18afb80a068821504296eb0787d9ce239b91ca15059d1d3eaacf13b", - "sha256:4be9f4830ba8741527693848403e2c457c16e499100963ec711b1c6f2049b7c7", - "sha256:4d1d02209e06550bdaef34af58e041ad71b88e624f5d825519da3a3308e22687", - "sha256:4f41da960b196ea355357285ad1316a00099f22d0929fe168343b99b254729c9", - "sha256:517ad0e93394ac532745129ceabdf2696b609ec9f87863d337140317ebce1c14", - "sha256:51fb3c322c81d20567019778cb5a4a6f2dc1c200b886bc0d636238e364848c89", - "sha256:5273b9f0b5835ff0350c0828faea623c68bfa65b792720c453e22b25cc72930f", - "sha256:530d548084c4a9f7a16ed4a294d459b4f229db50df689bfe92027452452943a0", - "sha256:530e8cebeea0d76bdcf93357aa5e41336f48c3dc709ac52da2bb167c5b8271d9", - "sha256:54fae94be3d75f3e573c9a1b5402dc593de19377013c9a0e4285e3d402dd3a2a", - "sha256:572d7c822caf521f0525ba1bce1a622a0b85cf47ffbdae6c9c19e3b5ac3c4389", - "sha256:58c948d0d086229efc484fe2f30c2d382c86720f55cd9bc33591774348ad44e0", - "sha256:5d11595abf8dd942a77883a39d81433739b287b6aa71620f15164f8096221b30", - "sha256:5f8ddd609f9e1af8c7bd6e2aca279c931aefecd148a14402d4e368f3171769fd", - "sha256:5feb91325bbceade6afab43eb3b508c63ee53579fe896c77137ded51c6b6958e", - "sha256:60c74963d8350241a79cb8feea80e54d518f72c26db618862a8f53e5023deaf9", - "sha256:613f19aa6e082cf96e17e3ffd89383343d0d589abda756b7764cf78361fd41dc", - "sha256:659a1e1b500fac8f2779dd9e1570464e012f43e580371470b45277a27baa7532", - "sha256:695f5c2823691a25f17bc5d5ffe79fa90972cc34b002ac6c843bb8a1720e950d", - "sha256:69dd852c2f0ad631b8b60cfbe25a28c0058a894de5abb566619c205ce0550eae", - "sha256:6cceb5473417d28edd20c6c984ab6fee6c6267d38d906823ebfe20b03d607dc2", - "sha256:71be7e0e01753a89cf024abf7ecb6bca2c81738ead80d43004d9b5e3f1244e64", - "sha256:74119174722c4349af9708993118581686f343adc1c8c9c007d59be90d077f3f", - "sha256:74a2e659c7ecbc73562e2a15e05039f1e22c75b7c7618b4b574a3ea9118d1557", - "sha256:7504e9b7dc05f99a9bbb4525c67a2c155073b44d720470a148b34166a69c054e", - "sha256:79090741d842f564b1b2827c0b82d846405b744d31e84f18d7a7b41c20e473ff", - "sha256:7a6967aaf043bceabab5412ed6bd6bd26603dae84d5cb75bf8d9a74a4959d398", - "sha256:7bda6eebafd42133efdca535b04ccb338ab29467b3f7bf79569883676fc628db", - "sha256:7edbed096e4a4798710ed6bc75dcaa2a21b68b6c356553ac4823c3658d53743a", - "sha256:7f9019c9cb613f084481bd6a100b12e1547cf2efe362d873c2e31e4035a6fa43", - "sha256:802168e03fba8bbc5ce0d866d589e4b1ca751d06edee69f7f3a19c5a9fe6b597", - "sha256:80d0a5615143c0b3225e5e3ef22c8d5d51f3f72ce0ea6fb84c943546c7b25b6c", - "sha256:82060f995ab5003a2d6e0f4ad29065b7672b6593c8c63559beefe5b443242c3e", - "sha256:836ab36280f21fc1a03c99cd05c6b7af70d2697e374c7af0b61ed271401a72a2", - "sha256:8761ac29b6c81574724322a554605608a9960769ea83d2c73e396f3df896ad54", - "sha256:87725cfb1a4f1f8c2fc9890ae2f42094120f4b44db9360be5d99a4c6b0e03a9e", - "sha256:899d28f422116b08be5118ef350c292b36fc15ec2daeb9ea987c89281c7bb5c4", - "sha256:8bc5f0687d796c05b1e28ab0d38a50e6309906ee09375dd3aff6a9c09dd6e8f4", - "sha256:8bea55c4eef25b0b19a0337dc4e3f9a15b00d569c77211fa8cde38684f234fb7", - "sha256:8e5a94886bedca0f9b78fecd6afb6629142fd2605aa70a125d49f4edc6037ee6", - "sha256:90ca27cd8da8118b18a52d5f547859cc1f8354a00cd1e8e5120df3e30d6279e5", - "sha256:92734d4d8d187a354a556626c221cd1a892a4e0802ccb2af432a1d85ec012194", - "sha256:947cf925bc916d90adba35a64c82aace04fa39b46b52d4630ece166655905a69", - "sha256:95b52c68d64c1878818687a473a10547b3292e82b6f6fe483808fb1468e2f52f", - "sha256:97d0235baafca5f2b09cf332cc275f021e694e8362c6bb9c96fc9a0eb74fc316", - "sha256:9ca4c0b502ab399ef89248a2c84c54954f77a070f28e546a85e91da627d1301e", - "sha256:9cc4fc6c196d6a8b76629a70ddfcd4635a6898756e2d9cac5565cf0654605d73", - "sha256:9cc6e6d9e571d2f863fa77700701dae73ed5f78881efc8b3f9a4398772ff53e8", - "sha256:a056d1ad2633548ca18ffa2f85c202cfb48b68615129143915b8dc72a806a923", - "sha256:a26611d9987b230566f24a0a125f17fe0de6a6aff9f25c9f564aaa2721a5fb88", - "sha256:a4474d924a47185a06411e0064b803c68be044be2d60e50e8bddcc2649957c1f", - "sha256:a4ea868bc28109052790eb2b52a9ab33f3aa7adc02f96673526ff47419490e21", - "sha256:a9e68c9d88823b274cf1e72f28cb5dc89c990edf430b0bfd3e2fb0785bfeabf4", - "sha256:aa9cccf4a44b9b62d8ba8b4dd06c649ba683e4bf04eea606d2e94cfc2d6ff4d6", - "sha256:ab30e5e3e706e3063bc6de96b118688cb10396b70bb9864a430f67df98c61ecc", - "sha256:ac2393c73378fea4e52aa56285a3d64be50f1a12395afef9cce47772f60334c2", - "sha256:ad8faf8df23f0378c6d527d8b0b15ea4a2e23c89376877c598c4870d1b2c7866", - "sha256:b35b200d6a71b9839a46b9b7fff66b6638bb52fc9658aa58796b0326595d3021", - "sha256:b3694e3f87f8ac7ce279d4355645b3c878d24d1424581b46282f24b92f5a4ae2", - "sha256:b4ff1d35e8c5bd078be89349b6f3a845128e685e751b6ea1169cf2160b344c4d", - "sha256:bbc8c8650c6e51041ad1be191742b8b421d05bbd3410f43fa2a00c8db87678e8", - "sha256:bc72863f4d9aba2e8fd9085e63548a324ba706d2ea2c83b260da08a59b9482de", - "sha256:bf625105bb9eef28a56a943fec8c8a98aeb80e7d7db99bd3c388137e6eb2d237", - "sha256:c2274ca724536f173122f36c98ce188fd24ce3dad886ec2b7af859518ce008a4", - "sha256:c45a03a4c69820a399f1dda9e1d8fbf3562eda46e7720458180302021b08f778", - "sha256:c8ae56368f8cc97c7e40a7ee18e1cedaf8e780cd8bc5ed5ac8b81f238614facb", - "sha256:c907cdc8109f6c619e6254212e794d6548373cc40e1ec75e6e3823d9135d29cc", - "sha256:ca0276464d148c72defa8bb4390cce01b4a0e425f3b50d1435aa6d7a18107602", - "sha256:cd5e2801c89992ed8c0a3f0293ae83c159a60d9a5d685005383ef4caca77f2c4", - "sha256:d08ec48f0a1c48d75d0356cea971921848fb620fdeba805b28f937e90691209f", - "sha256:d1a2ee9c1499fc8f86f4521f27a973c914b211ffa87322f4ee33bb35392da2c5", - "sha256:d5f5d1e9def3405f60e3ca8232d56f35c98fb7bf581efcc60051ebf53cb8b611", - "sha256:d60377dce4511655582e300dc1e5a5f24ba0cb229005a1d5c8d0cb72bb758ab8", - "sha256:d73beaac5e90173ac3deb9928a74763a6d230f494e4bfb422c217a0ad8e629bf", - "sha256:d7de2637729c67d67cf87614b566626057e95c303bc0a55ffe391f5205e7003d", - "sha256:dad6e0f2e481fffdcf776d10ebee25e0ef89f16d691f1e5dee4b586375fdc64b", - "sha256:dda86aba335c902b6149a02a55b38e96287157e609200811837678214ba2b1db", - "sha256:df01808ee470038c3f8dc4f48620df7225c49c2d6639e38f96e6d6ac6e6f7b0e", - "sha256:e1f6e2f00a6b8edb562826e4632e26d063ac10307e80f7461f7de3ad8ef3f077", - "sha256:e25369dc110d58ddf29b949377a93e0716d72a24f62bad72b2b39f155949c1fd", - "sha256:e3c701e954abf6fc03a49f7c579cc80c2c6cc52525340ca3186c41d3f33482ef", - "sha256:e5bcc1a1ae744e0bb59641171ae53743760130600da8db48cbb6e4918e186e4e", - "sha256:e68c14b04827dd76dcbd1aeea9e604e3e4b78322d8faf2f8132c7138efa340a8", - "sha256:e8aeb10fcbe92767f0fa69ad5a72deca50d0dca07fbde97848997d778a50c9fe", - "sha256:e985a16ff513596f217cee86c21371b8cd011c0f6f056d0920aa2d926c544058", - "sha256:ecbbd45615a6885fe3240eb9db73b9e62518b611850fdf8ab08bd56de7ad2b17", - "sha256:ee4ec14bc1680d6b0afab9aea2ef27e26d2024f18b24a2d7155a52b60da7e833", - "sha256:ef5960d965e67165d75b7c7ffc60a83ec5abfc5c11b764ec13ea54fbef8b4421", - "sha256:f0cdaecd4c953bfae0b6bb64910aaaca5a424ad9c72d85cb88417bb9814f7550", - "sha256:f1ce721c8a7dfec21fcbdfe04e8f68174183cf4e8188e0645e92aa23985c57ff", - "sha256:f50498891691e0864dc3da965f340fada0771f6142a378083dc4608f4ea513e2", - "sha256:f5ea69428fa1b49573eef0cc44a1d43bebd45ad0c611eb7d7eac760c7ae771bc", - "sha256:f61aa92e4aad0be58eb6eb4e0c21acf32cf8065f4b2cae5665da756c4ceef982", - "sha256:f6e4333fb15c83f7d1482a76d45a0818897b3d33f00efd215528ff7c51b8e35d", - "sha256:f820f24b09e3e779fe84c3c456cb4108a7aa639b0d1f02c28046e11bfcd088ed", - "sha256:f98059e4fcd3e3e4e2d632b7cf81c2faae96c43c60b569e9c621468082f1d104", - "sha256:fcce033e4021347d80ed9c66dcf1e7b1546319834b74445f561d2e2221de5659" + "sha256:01077390b03f7988f11d700a2194e69b119741a86b1a638b1db88891e3eced8e", + "sha256:01b0c0d2262a9e28e8484a278c7e1b5d650e3ac8cf2683d2967e25899f208bdf", + "sha256:04851f73ae72b8413dddadb16a49dfee95263553741fd42d546f7d66907e6be5", + "sha256:0521c5665880b33d603717defa76c094048900010897909952397feb3039da56", + "sha256:0774bf9bf620249fee3e0b8b9fd3065de213be30f3aa94ce2494b3b638949e26", + "sha256:0891b9d3903c5571c03771ca669a4b0ec5618ca722a5c957d3d29cd4e5062848", + "sha256:0c951d5e6dd9c2ff60609476752bee49da4206adde960ebc247766937f72e718", + "sha256:0fed1d06615f022ee3b13caf5e8b180cfea32bb2c5aded8a9d44277afc040f93", + "sha256:114e4d0c92d618409ed82a99e22b5c5e768fe995f2973f78265f4524f49d4640", + "sha256:11912e4bb14baae7c5d8791aa55ba0a3a03ec6729073307b0f57270abaa713d3", + "sha256:11a4d68a6ecda3292cb1e50239e111543ba5d709bb62a6b4ea1afcfa729d8875", + "sha256:124fbf1a8ff966d87ae05bb8bd45a71f966055ed8bba320d0c7cf450bc5f4d0e", + "sha256:1461ac396c4fdb983a675f20aa555624f0ee18ac83d832b9244ffff3d8055275", + "sha256:1503bccbeb36d5527790c3930327704c39af22de3112f1b1666a9f3ce15ee204", + "sha256:15bb4005af6320d259dc7593ca84a38d7fe06a421dbcf7b910ae23979101e787", + "sha256:15c44f7edfd477b06f517a5cc317fc1707edb9de2c865f43d4b6513907473234", + "sha256:16fa0eccf81304b79c5cd87f9271c3b85dd9dd99245e4422ae9c0dd45e0f99d3", + "sha256:183b88127acdb4fabe59d951ab424faf1af7b63cdbb5f776186c1ea2ffcaed98", + "sha256:195c26fb65950f8fce54e26349852b7bdd7c5f120aeefbcc440b8a20faaed4a3", + "sha256:1afb975bd5d68d5ce9f6b6d44fdf2f7e34b895a35e95708a7a91b20a3b51d187", + "sha256:1b4cbc7c3491ccb4aa17fcd8165649d01cf39f76de1696da8631b5f71b85401d", + "sha256:1bc0baf5ef96b6ede57d47f4b8fe4d9d84019c3bfcbeb20a41edc6a6ee341f1f", + "sha256:1c50fe28bbc2ced33386f298650d91218076c05420e6cbd790b913adc41659e7", + "sha256:1db38f4c5496827c1a501846d64d14c3b80c7e6714e406cd7dc36a9899fa1011", + "sha256:211d5a3eb6af8f513b8d4ca19a8c1b7accab1b5f0d3175f9826b03c1a920dc1f", + "sha256:23851fb4e1b85ed3f6c2a27b777cdfe2e19fb5b38429a8faf38c7542b7665869", + "sha256:254eb48b9fa5ee9898a3c445825a1f340fe53712a098904b39b0bddba8ea3cb1", + "sha256:2625388c6c754520c37abaf3b41eb34d1cc4a373f457898f08606c8e362b891d", + "sha256:281cb91036248400f4cc957495cccd44c275c2e0c5854f7e45ac5cf7dc193847", + "sha256:28a15fdad492a99b6eccfaaed66ef3f74050680545ea61ec8b2f4c538f1f1320", + "sha256:28b4f0d66fb834ff90f28209ac7bce77868c45d8c93e26f906709d9b7c2e1af9", + "sha256:2a925889534b3748302dae5dead07cc13480de1dac3aea80a941b729b471ef93", + "sha256:2b7b3bbfb4fe8ef40600792d762fbaa9057559f9d3fad209525b7a22b99e91fd", + "sha256:2c9ad19a6cfcd5ea5c0d41161d22f9df1dcc277e9bef2751391334546a314c00", + "sha256:2cc961b171b3f3440f410489ab3573e86aea8736134ebbb40ea1338b7f0831bc", + "sha256:2ce45c6627b22c47e390bc91a41c3d13032192e699fa0bea96e9671b373d69b0", + "sha256:2e06a3a98f916dd41d27f3105e02e7a40181c98c94b9158733d03a6f80506c09", + "sha256:304d5463e65a35d7bb0850550e0780395395f6fcf452f04db7d5ca7cecc425ac", + "sha256:304d8e4d493af723536393eee0c689eb7813f4a474c8b479dee63f1fdd98f621", + "sha256:30fcd120b732aa79317f08dee04d7de0847822e4cf7ee0e9f445bb958832252c", + "sha256:31f3930700408d211f13378ccbe1c40845d8da54bd0681fac3a9b5aae81c7aa8", + "sha256:34276fd796040bf0993ab33a369aa572e6979c7aab225a88893667ad8eac8f7a", + "sha256:355ad8011081dec5412240c087a9a0c9d4d5039f3ed11a3f13e18c2b29b56c51", + "sha256:38a873987f3be698494da8b2e3085e29da02da7b633dce73e79c699a113d7bf0", + "sha256:39de2a259fc954455c57274dc94c79d5842774e1247a016aff30bc0efed0f4ef", + "sha256:3d14b50de6bf4d0edf857a9386836846f982b8f524e188e2e68b96d702bcf4aa", + "sha256:3d21b8b13c7592db2ac5e544a6d83187b995257472b0c9e8351b6d507ae37ed6", + "sha256:3d31298449090ab8d47b7b1b2a555ff73cac7ed438a08b7ac160980c7ebed649", + "sha256:3ddacd27458c45bdacd6bd6db644bfb730efbf9e830310186e3045c9c5be8fb2", + "sha256:3df041de8887954562c9b261cba85ca0e9ded74048daf125f45edcfaa4832229", + "sha256:40ab6bffa02ae10a0581e6c198be7d2d8ca5c2a0c64e4ed3465d766df457573e", + "sha256:4275811936e2f06feff5e598fb42a1b7ae852da8e39605211892b56b81a34efd", + "sha256:443eae2bf318abeaf6f15d785138f71fd6de770e99a92158b8b814265e079115", + "sha256:447441e76ec720b15e64418d32e092297340387053047c7c694f579efb0ee1d9", + "sha256:4495c5002a7b28557e7e222e77e0b661183e432b7d6d2e788101e3f240e05b8c", + "sha256:44bd4fbb29dfbeba60e7d2bd000c59e4b21ddb3cc53912b14048d37092706d7c", + "sha256:4685902cf26edf013ed7a3da0f426ebba7a00ebb9541386d835afbf002c11cab", + "sha256:498dc3188ca05a68231ac3fdbfc7f57eb67e1343c30e0fea17f8218c1599b253", + "sha256:4c2b5031f63e331e3839b40aed2dd6f191e9c07edbde303e7876846ea1946995", + "sha256:4d48f2d08b9de5864e2c8744d4461b862fb149a18274abc8b698c45975573438", + "sha256:4f87960d57feabfb618e4e0af6e7371645fa26a277860739d6e5d6e0012c92f0", + "sha256:50e3adfb96fc189eb27b1cf62d3b598b89b4bb0420d93a3d3e42e137409011be", + "sha256:51cf45226a9b588d0d2b4880c62d686934b63ab0bd79ca23ab0e9762eb27441b", + "sha256:52aa6992700996af31f375de0c6bacd402b0097fe40b53c426b9f51a90ebabc7", + "sha256:55ea99acb17b9325618de155a0cd6a2e8f5d10be008113e1d433bbb58db543b2", + "sha256:56bc200a365efb37383b7852e4cc5898d3b2da5987289b543956cf8cad71018a", + "sha256:588461c2e8384d309bd63e5826019b6977bc66d629b99ac8737bb795d7b2cb5a", + "sha256:58ca3755ee7ff7f59b57789ec9833c9de9ea275405cdd240eda1f193112e398a", + "sha256:58f361dcbab699cf8f42db3f47c8e7fd1036f138c23a5d08de9fde5f425a730c", + "sha256:598a11a2c7ebaa5334bf698bf29568c9c390abac6a154d8170fedecd1cea38c5", + "sha256:59f63901b0031c3136cf64704dcb21de0bbae62ce2c9529bc39d27665463de37", + "sha256:5cde776b7cc66e4f6c99612cea4aa7269aa65863f7a15841b2c264f103822f4e", + "sha256:5e2b6b57e9733d39f0c9fd3185efa6b8e29652c4cd8fe94180272cf6ed9a78c4", + "sha256:5fb29fb8cd1a46c27a1bf9613ad5ec2599310d46b4025d9556404a6b6a292800", + "sha256:6045373d5a89a5ec71afde535db987ca28e76dfa276c2d4c818265b375d4b055", + "sha256:619799369eeef6366ed3e8755a5670f4f2f0fb6b30a0fd7264dc0fdc2357058e", + "sha256:62588a277bfb59def052abd940703fa35107152bf479781a878617d60faf8fb5", + "sha256:62603db9a7caa0802eaa28c1c46fecd7b3a263a774069c24c3c28c302448721c", + "sha256:65cd72beeeca9d3aaea1201e5923859f308f952f9c71de93f06063c79f0f7a3b", + "sha256:68eb192d85ab8e5f6ec69c2bc6ac0179fbf04a5ac1569d12fbef74883fe102d0", + "sha256:6bd128f206a7752ae1f2ab6c61bf8a24ba28913a10df8b14c2637b973ff97a80", + "sha256:6be488a102b8cf28d0391d8c4ba7748938ae28b78ad901f8585520fca33ead1a", + "sha256:7218e8f32b0956cfcd048fd42d9d5779809745ca1d86113ca56f66e7ae1549c4", + "sha256:7441d755b7ab94f8d4eb3e43ec05482d760842fd263d003a99102d742cd835e2", + "sha256:749e97e1b32313717a565abbe321bc2190bc8b35f1a67e4cdbc7c56c8d8ffe58", + "sha256:75a3ceed0724d625d64b86ca20aba182e4df462e04c2414fc941c0f523f06aac", + "sha256:780fbe7cab297b81dad9fb8dc5eb003c0468ffb0d9e5f65068c53a34661a96bc", + "sha256:78456a747de8dc58360ffa581f30a002baf5aa28cb262536545e91f113ed7639", + "sha256:7967d08cf06dee78443b874f98c98036f624f3a4e73e11f9f64f5be4d25393cf", + "sha256:7a881931aa470808df94a8c380eed2bbbc76cd9dc622310f99665658c821eb6d", + "sha256:7dcd882da75ef9adf94903b1e3b9419e8aa8fb4c7396822b834b9ef7fb96954f", + "sha256:7e841fb9010836c992c9f12fcbd43a831de93a5f726fc1ccd8ca1d0268c5014c", + "sha256:7fdde2c9fd9e3eca40631e024664cf2584272cc8f96308cbe5fdfc930f51d8bc", + "sha256:8024d00c3faf3fc0c16e07a69f4405e8eac7cc0ab15f65fe6cf43827c4cf72b4", + "sha256:80d02b6f04e92601a081dd97b23d3128033098bff5d35d392ddcc0476ea11253", + "sha256:838dcc90063569a0448120554591a1d6c4a4ffe11babf048908793154ab86ade", + "sha256:849df64e889b2e17230d58410a03dba311a65b163508fd33679b2b737d4b7858", + "sha256:87475fabc8d9996fd9c27debb395e642e8c838d78a00b6e932227a0e06b81e26", + "sha256:87e50a3e7cb90af586b6c5faf23e302a970415ac73bd7bd90a515a04b427ef96", + "sha256:89b53f3cda69831909888e0494f4fa0bcd3537e3e138dabeb620bd6ad946bae8", + "sha256:8a893cc101149f80a653f82062ebc95b34525a2614382e1da5458fe7c6997249", + "sha256:8b2bfab86aa71ae13aa41a6a26aab338e0db2b8bc75434b05aea89e011ff35a4", + "sha256:8d86d6fc60743dc916eb79e2eb1ec4818e21e427731543af40a3021851174a13", + "sha256:915563965d418f986e7e145accc592eae9e1a1be3566ff98a05d7a9ec42a76e1", + "sha256:92888bb3187c5ba50500b00b3b310c9f2c651709d28036077680cb5255450a03", + "sha256:93223adc95033dd47133a46ccfc316a0139176fd79085762e27202ec56018f03", + "sha256:9373ad13ef0d2c0fb761e04e55bfdee5a08b52cef2c882c8fbe9935b1517152e", + "sha256:9409a8bf35cf78353942504b24a57de3d75b708997a1e4bd8db71ac8633ce364", + "sha256:9b7f416ff0978e2f2249330527f0ad6fa02f4932e6199692d3b52da2048c19e4", + "sha256:9bde855991b7e362c146535e3136a50bfaffc0487d38b33ca7e5edefc6e23849", + "sha256:9cae88599c7219005d879f98e5ed53341e9a122af585e1091200358a3003d2a0", + "sha256:9cf9b1a857e25c4baceeb3624e92a56df3668f398c4acba74e174d81fb4d1d3a", + "sha256:9f56f72050826f63dcee7a7f55b0a77168cb3bfc553fd405e7f8f9ece75a4036", + "sha256:a090bb2c68df85450502e3e20d665e3a5af9c65a84d6508ed477badd49166fd3", + "sha256:a192e2c40070d92c3ccf777e3a5c4ff515573cd2bb7ed0c537fdadbbec5bbf21", + "sha256:a19a731138fc27d5682277d3b9df22855cea1239bce7fcec5f78f42ef2d1f3c3", + "sha256:a66c3bc5ab1f0ff2164fc9965ddd611ff0802173f4b9d24554c563f6ab7e1d6e", + "sha256:a815775b6c38d4e0ff7bcffbeba67feded90202bb6a226b8dd35f1c855217413", + "sha256:a89012d6d5476ee112d20d998570ed58df2260a852afb1758809cd6900411d21", + "sha256:ae4f5fea5b8b8ccff88238cc8569303e5ee95efae67fa62922a311397a71f346", + "sha256:b6856554c4f44d79fc2307d5768854310a8f0096e501c75637542c82292b0429", + "sha256:b6b751274acb69d77b3323d6b7dbaa3c7fdfc1eb829b7eb61d262f32e1af9685", + "sha256:b736353c0a625bbd5fcec108576e2385db3496f4f771f785ff32e108d3c3bc45", + "sha256:b7fd005a73d9e657273b7a10dc71a9e03c8fb9ee6999798d6918ce095b81ac7f", + "sha256:b91363207bd9dc966a691e959bb47f64b30f7ac4b072be9968b366982f7db77c", + "sha256:ba0b1d2620edf869789c3879223f52bf2afc5d31b3cb47cc57b3a12c05e2aa9d", + "sha256:bbbfc8e28816f19d7c0f1816664980c0a9875d01b27cdf8eedddb639d9e108ad", + "sha256:bd16aabe4a02a297c23417aa17ac6299dbd8c49f673bcd645b4929b11f5a4400", + "sha256:c0afc6800ba57ccc350374c5bd6150419915d95ce93cdbab2d783d75eaf30ecb", + "sha256:c6708715abcf3c73b99508253e961a9967f02fe536532834149574eda6de0d1c", + "sha256:c7c9ab723cde841fefb34efbad91e87f00a674b1fe1cd0784fde742bf2c154dc", + "sha256:c8f3d67aeaf55f017982b73683f0e7342ba2f6635a78f69ce89ebb26aa411e5c", + "sha256:c9790464842f85f437dbbb54417eda1e0e6bfc52dd8d22d6fd1c994b73b2dc74", + "sha256:ca403d7e4798f525fdfc78e258820419cbbd0f0ecbab9de7840e3c017cf6b8cf", + "sha256:d008d90a7f2471519aef0c90dfbe73b3e6e4d5e66ac48e19154c17e89e98b604", + "sha256:d19fbd981a488e22cd04883659ca6b08f50b5974f9fd7c95655ef6a043e5893f", + "sha256:d1befeed746d247c81127bb14de9dc3d30edb6e5976d34f83f86ed262b1d9105", + "sha256:d2374b62878abb00cd8309b32af6c0b715cd02dec0ca74ef12e5069bdc64144a", + "sha256:d376bbd28b3a8999db1a103b3b388aee6f1ddeb3e51bc2172993efdcd86e064d", + "sha256:d4a7319f304a774bed22115bc891618e45f85065ab44ea6acd07d274e750519a", + "sha256:d6734d2ef8a50fbf8445c139477da401f50d62a0606bf00e20ec6d87773fefb1", + "sha256:d760fe2a4d7c3b226cb9026d6a842868d52a7901bd98420e1baf14e80da85cf5", + "sha256:d913de495d90407cd859d263bee2e5d1a4ed3eb6573c04e70d9ec619a7cbed7f", + "sha256:db19d07e2e0129e974a0e65d0064fc222a446cd5122c2fd4184d2af9fc734a9e", + "sha256:dca9ab98072a5a54ebacebdc45f53e645336b320c667410b061be1ca588ae709", + "sha256:ddc7dacc8ece3a182e7f15cb862d1fd616b46d076cb1ae9dd232b2c38b655874", + "sha256:ddf19c062bea7a0cc80f519243d2c01dd091be0cf952a0750d4ad576709559f5", + "sha256:def79fa35ef0cef8d2accec024f4fdc7ead3012ff02f5215c783f39f03ef8cfc", + "sha256:df29a0a7107f7011e77f4eebdddec4c7331e24d787a0b21a46d63bdf7445da95", + "sha256:e09a3942ecbdee5cce73ea9d42da82b81b72ac1bf031ce069b93b5adf4eac8cd", + "sha256:e242bb1c5e76e97dfa9e7f209a71e93a01d7f19ffdd5cfbb2e2d55b4f08f8ab0", + "sha256:e243bd13217235fc7290c621941c3f5cc8b66e4872495be821d7436ba2fb838d", + "sha256:e2af3aad578aa6bd1384bcf4750fc285e5a9de53f40b7d41e5a0bf748edeb2b3", + "sha256:e4e81e09c1578b8df602e3db08b0b3ea0a6947ad612f52bf8dc5ea8d47691f0c", + "sha256:e54da4baf05720032d527874d40b65fa4d7e5c6c6a43d0c3adbeffcaf275a2b3", + "sha256:e80e6c2f55656b4824d72065abb4ddd6a525c74bd78a0aab5d9fc2cf4fb5af50", + "sha256:ed2a239c0ea213acc1908150a3037257083c7c083128f1a4cec2ec4b97dca491", + "sha256:ed905975ab14056a2e5eb1c376cb2e1ebc5396baf84163939c518556fccde9f5", + "sha256:ee21e28f0430bd6dc9086c6e525d5e818a44a5ad19720c8a0ef766792f3eb5e5", + "sha256:ee43c17b173d46a3212baa6ead3ae258eeabdae48c263a01ccf0218c366dd655", + "sha256:ef4fcbf3327382cd4c9f540babd61248208af7b93eec4de397b4d5f58a09e288", + "sha256:eff0ac9dbe711a4aee69bf04a83896aa9b85f19641264053a9f6d48573abb7dd", + "sha256:f0aa869112ef88429ae17820d99c3dd9504c9e9c671d3c246f3d7442cb051084", + "sha256:f3c96f633825733f735c5a9cf21d21a257d8e1edf0b1cee0a064b9c424ca0f7d", + "sha256:f5833ad231be5eb6553de524a70f48d71b2c8563101750531e0b80184e175cd4", + "sha256:f5ec61164adcec446f8969a3358ec3f9b26bbda3b9213e5586d219afa8df2915", + "sha256:f7d486c83842422badd511868fd8a9a20e9407ace71564b6af47ce7e60a336c1", + "sha256:fb9e68df06293761f9fe66ade60a9bc6d0f5e42b8acf2939a9158af86ab0e5bd", + "sha256:fc14a032f813bf5fe624d991960ea83e9715adc27e4c1830a2361eb1d02ac341", + "sha256:fcff63213e8e6e47770541a4607175404f47cbb3ebea7b6058cc82d524a0e424", + "sha256:fd1fbe0f116b6e55da77aca2c6ddcddcfac2186cbf78bdebf40fc156efca389d", + "sha256:fe9753dfee015c570d73df76f899f18444d41388bffcde097deba51c4fadbb9f" ], "markers": "python_version >= '3.7'", - "version": "==3.4.6" + "version": "==3.5.2" }, "click": { "hashes": [ - "sha256:6b303f0b2aa85f1cb4e5303078fadcbcd4e476f114fab9b5007005711839325c", - "sha256:f5452aeddd9988eefa20f90f05ab66f17fce1ee2a36907fd30b05bbb5953814d" + "sha256:398329ad4837b2ff7cbe1dd166a4c0f8900c3ca3a218de04466f38f6497f18a2", + "sha256:a2bf429bb3033c89fa4936ffb35d5cb471e3719e1f3c8a7c3fff0b8314305613" ], "index": "pypi", "markers": "python_version >= '3.10'", - "version": "==8.2.0" + "version": "==8.3.3" }, "click-didyoumean": { "hashes": [ @@ -435,11 +477,11 @@ }, "click-repl": { "hashes": [ - "sha256:17849c23dba3d667247dc4defe1757fff98694e90fe37474f3feebb69ced26a9", - "sha256:fb7e06deb8da8de86180a33a9da97ac316751c094c6899382da7feeeeb51b812" + "sha256:52f8962ff0fdae8105d568123b144951257b6bfcfb44ff6f043379c307d0a8ac", + "sha256:fee730650f34204f1bd41b8fab46f6b51dda019b4a35ed89ab8553ba31f7d6d3" ], - "markers": "python_version >= '3.6'", - "version": "==0.3.0" + "markers": "python_version >= '3.9'", + "version": "==0.4.0" }, "clickclick": { "hashes": [ @@ -494,12 +536,12 @@ }, "flask": { "hashes": [ - "sha256:bf656c15c80190ed628ad08cdfd3aaa35beb087855e2f494910aa3774cc4fd87", - "sha256:ca1d8112ec8a6158cc29ea4858963350011b5c846a414cdb7a954aa9e967d03c" + "sha256:0ef0e52b8a9cd932855379197dd8f94047b359ca0a78695144304cb45f87c9eb", + "sha256:f4bcbefc124291925f1a26446da31a5178f9483862233b23c0c96a20701f670c" ], "index": "pypi", "markers": "python_version >= '3.9'", - "version": "==3.1.2" + "version": "==3.1.3" }, "flask-login": { "hashes": [ @@ -693,111 +735,142 @@ }, "gevent": { "hashes": [ - "sha256:012a44b0121f3d7c800740ff80351c897e85e76a7e4764690f35c5ad9ec17de5", - "sha256:03c74fec58eda4b4edc043311fca8ba4f8744ad1632eb0a41d5ec25413581975", - "sha256:0adb937f13e5fb90cca2edf66d8d7e99d62a299687400ce2edee3f3504009356", - "sha256:18e5aff9e8342dc954adb9c9c524db56c2f3557999463445ba3d9cbe3dada7b7", - "sha256:1a3fe4ea1c312dbf6b375b416925036fe79a40054e6bf6248ee46526ea628be1", - "sha256:1cdf6db28f050ee103441caa8b0448ace545364f775059d5e2de089da975c457", - "sha256:1d0f5d8d73f97e24ea8d24d8be0f51e0cf7c54b8021c1fddb580bf239474690f", - "sha256:2951bb070c0ee37b632ac9134e4fdaad70d2e660c931bb792983a0837fe5b7d7", - "sha256:323a27192ec4da6b22a9e51c3d9d896ff20bc53fdc9e45e56eaab76d1c39dd74", - "sha256:34e01e50c71eaf67e92c186ee0196a039d6e4f4b35670396baed4a2d8f1b347f", - "sha256:427f869a2050a4202d93cf7fd6ab5cffb06d3e9113c10c967b6e2a0d45237cb8", - "sha256:46b188248c84ffdec18a686fcac5dbb32365d76912e14fda350db5dc0bfd4f86", - "sha256:4acd6bcd5feabf22c7c5174bd3b9535ee9f088d2bbce789f740ad8d6554b18f3", - "sha256:4f84591d13845ee31c13f44bdf6bd6c3dbf385b5af98b2f25ec328213775f2ed", - "sha256:5e4b6278b37373306fc6b1e5f0f1cf56339a1377f67c35972775143d8d7776ff", - "sha256:6ea78b39a2c51d47ff0f130f4c755a9a4bbb2dd9721149420ad4712743911a51", - "sha256:72152517ecf548e2f838c61b4be76637d99279dbaa7e01b3924df040aa996586", - "sha256:7a834804ac00ed8a92a69d3826342c677be651b1c3cd66cc35df8bc711057aa2", - "sha256:812debe235a8295be3b2a63b136c2474241fa5c58af55e6a0f8cfc29d4936235", - "sha256:856b990be5590e44c3a3dc6c8d48a40eaccbb42e99d2b791d11d1e7711a4297e", - "sha256:88b6c07169468af631dcf0fdd3658f9246d6822cc51461d43f7c44f28b0abb82", - "sha256:8d94936f8f8b23d9de2251798fcb603b84f083fdf0d7f427183c1828fb64f117", - "sha256:9cdbb24c276a2d0110ad5c978e49daf620b153719ac8a548ce1250a7eb1b9245", - "sha256:a8ae9f895e8651d10b0a8328a61c9c53da11ea51b666388aa99b0ce90f9fdc27", - "sha256:adf9cd552de44a4e6754c51ff2e78d9193b7fa6eab123db9578a210e657235dd", - "sha256:b274a53e818124a281540ebb4e7a2c524778f745b7a99b01bdecf0ca3ac0ddb0", - "sha256:b28b61ff9216a3d73fe8f35669eefcafa957f143ac534faf77e8a19eb9e6883a", - "sha256:b56cbc820e3136ba52cd690bdf77e47a4c239964d5f80dc657c1068e0fe9521c", - "sha256:b5a67a0974ad9f24721034d1e008856111e0535f1541499f72a733a73d658d1c", - "sha256:b7bb0e29a7b3e6ca9bed2394aa820244069982c36dc30b70eb1004dd67851a48", - "sha256:bb63c0d6cb9950cc94036a4995b9cc4667b8915366613449236970f4394f94d7", - "sha256:c049880175e8c93124188f9d926af0a62826a3b81aa6d3074928345f8238279e", - "sha256:c5fa9ce5122c085983e33e0dc058f81f5264cebe746de5c401654ab96dddfca8", - "sha256:c6c91f7e33c7f01237755884316110ee7ea076f5bdb9aa0982b6dc63243c0a38", - "sha256:d99f0cb2ce43c2e8305bf75bee61a8bde06619d21b9d0316ea190fc7a0620a56", - "sha256:dc45cd3e1cc07514a419960af932a62eb8515552ed004e56755e4bf20bad30c5", - "sha256:ddd3ff26e5c4240d3fbf5516c2d9d5f2a998ef87cfb73e1429cfaeaaec860fa6", - "sha256:e4e17c2d57e9a42e25f2a73d297b22b60b2470a74be5a515b36c984e1a246d47", - "sha256:eb51c5f9537b07da673258b4832f6635014fee31690c3f0944d34741b69f92fa", - "sha256:f0d8b64057b4bf1529b9ef9bd2259495747fba93d1f836c77bfeaacfec373fd0", - "sha256:f18f80aef6b1f6907219affe15b36677904f7cfeed1f6a6bc198616e507ae2d7", - "sha256:f2b54ea3ca6f0c763281cd3f96010ac7e98c2e267feb1221b5a26e2ca0b9a692", - "sha256:fe1599d0b30e6093eb3213551751b24feeb43db79f07e89d98dd2f3330c9063e" + "sha256:0b3f0ad9dc8e2ba585e0f6498c96b78ba61b1214f5b2e17081839c93b69a58c3", + "sha256:0ec6525fa2d55b96fc538be48a53a875c4b804738b016078a6eb49a6a2adf2e6", + "sha256:12e909b93dcda8d3a40eb8130de605a70eca95a58f4ef74133d07c11495f8c89", + "sha256:1c56654619fc284091f82900469993de50263a9f6c44724e0f084167e9cc8917", + "sha256:1e2b9508076350799def5eb7ac57a9d7c14234da201372d9f7329f45074f833a", + "sha256:231058bdb60dbf1074b2e74fbb77c0b0f1b045886bf7203b816692c3663726cc", + "sha256:23f08013256a3e9b5928b65856116f9bdc775ee8246c0361bc916ea283c9c6fd", + "sha256:32c8236cb4b2911cee7d5caaa8fcd8ab2267354d46fc8223a880e3466859d0bf", + "sha256:3427358b8dcde8abcfab45d649aeedab9eb5d31916886e277405f95660e12751", + "sha256:3b6404d18df517663df90889568de931ae43aae765bae542edb9ada73a9595db", + "sha256:405d73327feecab8cc9976f7bc2a0dbd1adaccf2e4b5e86e97e7b87879fa5cfd", + "sha256:415f963d9b8e9022156afb091f6399de1d598aca173622cf5e2d0472178d57b1", + "sha256:44a0d58301a333608aad5fef0c19ca8122eb7753484416f000c1f00b4b407697", + "sha256:460c6db10c8d9475efb9a24d84c4a0e47bf628dce569efa0821217d83c68e584", + "sha256:46fc47fa2d8a685efd05ff4c4aaab3a390915edc58936409bb63570e4bf51c7d", + "sha256:4827d454a2d0c7b4789dcd396cfa42c1ed2b03f3d6b02d6936112e2a82afa93c", + "sha256:4a698fa2f5cf096bd6c1f59fd38a0d420e8b3a815b01be197eb9529cdd57d06b", + "sha256:4dd4703d71737a456c1c9df5cd43a82934e5b10c87549caa02495f487d1ef0b1", + "sha256:5415eb380995015664d24672a884b2d93cddc0838beec13a6a96c6ac3be23f84", + "sha256:5560ec62a44dc8bb983dd09bca05df01b77b94993c51bfe856a2163d785688ac", + "sha256:5902ecdd81454615a3bf610897592058c4fe347c8e4ce4313dc31aeb29ba0ca7", + "sha256:5b089f158cdecddf5ac8face23e1cf7318a704625a32998c37118818efc97f16", + "sha256:7dce7f1a5be4be303e7a3c1db2e453abc5495c8b91b8708a0e64e116b3c6c4db", + "sha256:810cd040eda484e8ce73d649fa994a4fc247b427023db52d4daaa10e8fd2f4aa", + "sha256:83c51ffa0ef9c960fe3b6bc0a9de8997cd04a9476ff5d4e682c0c62481ef3924", + "sha256:86999e6ec77ae16411c734658c88fde8b5c4be0112dc442ac498925fc881ddb2", + "sha256:8e47e8c24135936bc01198f93aa97061e543a8b0d7a339d34182c35901b41da0", + "sha256:8f70c12e1ec091ed326ee8096245a12257c7c2f95b043ed953f934c63eaefd7e", + "sha256:979caf5b96f5806cb5b66fd2c7972f1043cc4069d1ee8b2998c42cb0b39dc445", + "sha256:9eac1550fce3e356dee3448c2b95080d25e3affd560e22936fffc79d4d6c3a38", + "sha256:ab1db9defde9ea9bd1825057fd90474148f74dcc57d104ddc62343092eaa256f", + "sha256:afb17dfcb8e33ba4c84cf50a08974925c50a9d01306f199712897cfb00775d56", + "sha256:c38da261295c20066b352007703a2acec91644ada03a0e4f1a9d0efee8cb5a5c", + "sha256:c47c70f1bc131178a7b7ec1f5afb8ac6b1573ed1caf5c31889261e8b5caae0e6", + "sha256:c59d95daacf71dfb763824b85a89b06ca4faa74b2e7df926714d439d5a47ee26", + "sha256:c8b3bf3865f11504941d11bcca1dbf53beee79405b0da7577b1db29f94bb2209", + "sha256:cb52241e8c691818853361663134a72c4d5601a9fa46ff7f9cb749878855b26f", + "sha256:cf1544a8fa0d94563e1f31bc23363f437ae56b952f220dd588ca43c48c844ff3", + "sha256:d05115c494183d032d5dd3ee4f1517f4caa145f38008cee46405c5c2c8a4214b", + "sha256:e7e9247b449ee69f275bc4d44ceebaa0b71772d02bb3c52c146b2f613c4ad8d7", + "sha256:e9915c9870160c2d8b4d97ceb55b5598c33cee2dcef0635db363d5519147556c", + "sha256:e9c8cdf9ff3eac29abb5ae55da16dac02cc464fc0e1e13818fca0437e8cfee0a", + "sha256:ea5f8f84232f1900a1a56ad6f7ba6804c49eeb8efdf861a6bae00bcf226568f5", + "sha256:ed0e8c8123eda65f8ff1b69b76e6429e9aa51e6141b574ae7899792d31c7a072", + "sha256:f5e894f892347e242742ab24c881be271c2ea4be149bdb80307bab7a8f506ccb", + "sha256:f88d4eabc75ff3d48322fb8014ba82c062808c3f35ce6e30d474b74b57582208", + "sha256:f91b87ca2ac3af502f7ee806c266ba6f64e4d1591e2e29456ed7cc538e5473ec", + "sha256:f9ff7c692028c577937ad00bdd1183371a086f7d6908c7c1f18f1c51ccf8caac" ], - "markers": "python_version >= '3.9'", - "version": "==25.9.1" + "markers": "python_version >= '3.10'", + "version": "==26.9.0" }, "greenlet": { "hashes": [ - "sha256:02b0a8682aecd4d3c6c18edf52bc8e51eacdd75c8eac52a790a210b06aa295fd", - "sha256:18cb1b7337bca281915b3c5d5ae19f4e76d35e1df80f4ad3c1a7be91fadf1082", - "sha256:1a9172f5bf6bd88e6ba5a84e0a68afeac9dc7b6b412b245dd64f52d83c81e55b", - "sha256:1e692b2dae4cc7077cbb11b47d258533b48c8fde69a33d0d8a82e2fe8d8531d5", - "sha256:1ebd458fa8285960f382841da585e02201b53a5ec2bac6b156fc623b5ce4499f", - "sha256:1fb39a11ee2e4d94be9a76671482be9398560955c9e568550de0224e41104727", - "sha256:20154044d9085151bc309e7689d6f7ba10027f8f5a8c0676ad398b951913d89e", - "sha256:2eaf067fc6d886931c7962e8c6bede15d2f01965560f3359b27c80bde2d151f2", - "sha256:34308836d8370bddadb41f5a7ce96879b72e2fdfb4e87729330c6ab52376409f", - "sha256:394ead29063ee3515b4e775216cb756b2e3b4a7e55ae8fd884f17fa579e6b327", - "sha256:3ceec72030dae6ac0c8ed7591b96b70410a8be370b6a477b1dbc072856ad02bd", - "sha256:4375a58e49522698d3e70cc0b801c19433021b5c37686f7ce9c65b0d5c8677d2", - "sha256:43e99d1749147ac21dde49b99c9abffcbc1e2d55c67501465ef0930d6e78e070", - "sha256:442b6057453c8cb29b4fb36a2ac689382fc71112273726e2423f7f17dc73bf99", - "sha256:45abe8eb6339518180d5a7fa47fa01945414d7cca5ecb745346fc6a87d2750be", - "sha256:4c956a19350e2c37f2c48b336a3afb4bff120b36076d9d7fb68cb44e05d95b79", - "sha256:508c7f01f1791fbc8e011bd508f6794cb95397fdb198a46cb6635eb5b78d85a7", - "sha256:527fec58dc9f90efd594b9b700662ed3fb2493c2122067ac9c740d98080a620e", - "sha256:59b3e2c40f6706b05a9cd299c836c6aa2378cabe25d021acd80f13abf81181cf", - "sha256:5d0e35379f93a6d0222de929a25ab47b5eb35b5ef4721c2b9cbcc4036129ff1f", - "sha256:63d10328839d1973e5ba35e98cccbca71b232b14051fd957b6f8b6e8e80d0506", - "sha256:64970c33a50551c7c50491671265d8954046cb6e8e2999aacdd60e439b70418a", - "sha256:6c6f8ba97d17a1e7d664151284cb3315fc5f8353e75221ed4324f84eb162b395", - "sha256:8b466dff7a4ffda6ca975979bab80bdadde979e29fc947ac3be4451428d8b0e4", - "sha256:8c1fdd7d1b309ff0da81d60a9688a8bd044ac4e18b250320a96fc68d31c209ca", - "sha256:8c4dd0f3997cf2512f7601563cc90dfb8957c0cff1e3a1b23991d4ea1776c492", - "sha256:8d1658d7291f9859beed69a776c10822a0a799bc4bfe1bd4272bb60e62507dab", - "sha256:8e2cd90d413acbf5e77ae41e5d3c9b3ac1d011a756d7284d7f3f2b806bbd6358", - "sha256:8e4ab3cfb02993c8cc248ea73d7dae6cec0253e9afa311c9b37e603ca9fad2ce", - "sha256:94ad81f0fd3c0c0681a018a976e5c2bd2ca2d9d94895f23e7bb1af4e8af4e2d5", - "sha256:97245cc10e5515dbc8c3104b2928f7f02b6813002770cfaffaf9a6e0fc2b94ef", - "sha256:9bc885b89709d901859cf95179ec9f6bb67a3d2bb1f0e88456461bd4b7f8fd0d", - "sha256:a2a5be83a45ce6188c045bcc44b0ee037d6a518978de9a5d97438548b953a1ac", - "sha256:a443358b33c4ec7b05b79a7c8b466f5d275025e750298be7340f8fc63dff2a55", - "sha256:a7945dd0eab63ded0a48e4dcade82939783c172290a7903ebde9e184333ca124", - "sha256:aa6ac98bdfd716a749b84d4034486863fd81c3abde9aa3cf8eff9127981a4ae4", - "sha256:ab0c7e7901a00bc0a7284907273dc165b32e0d109a6713babd04471327ff7986", - "sha256:ac8d61d4343b799d1e526db579833d72f23759c71e07181c2d2944e429eb09cd", - "sha256:ad0c8917dd42a819fe77e6bdfcb84e3379c0de956469301d9fd36427a1ca501f", - "sha256:ae9e21c84035c490506c17002f5c8ab25f980205c3e61ddb3a2a2a2e6c411fcb", - "sha256:b26b0f4428b871a751968285a1ac9648944cea09807177ac639b030bddebcea4", - "sha256:b568183cf65b94919be4438dc28416b234b678c608cafac8874dfeeb2a9bbe13", - "sha256:b6997d360a4e6a4e936c0f9625b1c20416b8a0ea18a8e19cabbefc712e7397ab", - "sha256:b8bddc5b73c9720bea487b3bffdb1840fe4e3656fba3bd40aa1489e9f37877ff", - "sha256:c04c5e06ec3e022cbfe2cd4a846e1d4e50087444f875ff6d2c2ad8445495cf1a", - "sha256:c2e47408e8ce1c6f1ceea0dffcdf6ebb85cc09e55c7af407c99f1112016e45e9", - "sha256:c56692189a7d1c7606cb794be0a8381470d95c57ce5be03fb3d0ef57c7853b86", - "sha256:ccd21bb86944ca9be6d967cf7691e658e43417782bce90b5d2faeda0ff78a7dd", - "sha256:cd6f9e2bbd46321ba3bbb4c8a15794d32960e3b0ae2cc4d49a1a53d314805d71", - "sha256:d248d8c23c67d2291ffd47af766e2a3aa9fa1c6703155c099feb11f526c63a92", - "sha256:d3a62fa76a32b462a97198e4c9e99afb9ab375115e74e9a83ce180e7a496f643", - "sha256:e26e72bec7ab387ac80caa7496e0f908ff954f31065b0ffc1f8ecb1338b11b54", - "sha256:e3cb43ce200f59483eb82949bf1835a99cf43d7571e900d7c8d5c62cdf25d2f9" + "sha256:0616b8f878098c5681fd8f0dc92d887551717402342a70f0abcbfea5f5ad8a44", + "sha256:06c0e933290fba8ffe53ead4ae1b8044b0e9754b75cebf381aa2bc3e50d82fac", + "sha256:128813fc29f2336a21b4d06eedd5e16bcc7ea46f59e9ff1cb30ea70e48195d88", + "sha256:188bf333769b7145e2b0b4a7f09615ec550ed44d3a2a8395fb7b36f0e9901e13", + "sha256:1c20ea32a73d17b9b60e3371240e17b0068120c98a5ec01a224a7dd8c89733ba", + "sha256:2ab5f42ac6c238eb71770715e6e909ad9a1a92b6c681ccb64cd5a0f07edb953f", + "sha256:301102a49120b095e72a7838792b41233975fc1c155daec6d98f81c00c9280e0", + "sha256:311018b46472fb26ee85870847fb89eb64cc8aaddb617400789d87076f7cfeec", + "sha256:3ac3494c381dab876cad7d0b22f3a722f3e0c8deb3a65b9e7f35ad7f58b8fcb3", + "sha256:3c6dede9133e1da41d561bc3fb14e92b47e2ce39ae60edefaad145658ea7c5e2", + "sha256:3dbb4596a6a4e5d47121a33ff20533a81e60f302d9e67b69909a8bc21a43f0a7", + "sha256:3deccbb57a481e3a408fe61cdfd5c13e0678fc0a30fdd09597917ca87b4be877", + "sha256:45663c01a4de48b9a64a2ee1509d92d1dfd3afb02b2ccfc9333029d11aef996a", + "sha256:45bfd2b51e38aaa5f9849f114d9c7c1d75f69187c849b3549cd64c465283abfa", + "sha256:460e70b033aba8ed47e2ac9b5d0d2157b05a34fbfa30a241400aef4118902cdc", + "sha256:4fb8e59f68845d56c23c031dcd79c329f345e4a9d2ffac91c3d1ab366bdc457b", + "sha256:520648db8fb92eef7b3e6013f5a6f901cdf0d6685f639c2f7a245879f865bef7", + "sha256:5599b380c1f28efeb724e81569eac80cd92f99a85bd9775456caaf3225d40b11", + "sha256:59deccd347735a7774223b05a93773fddbb298aba3cea21be4337fb4752dbe32", + "sha256:5a0b2791239c99992a86c1b635b787fe2a877d9eaaa26f8891ce943832b585ae", + "sha256:5adcbbfe78bdc242c71740a02e0991cc1b2f34d33c8bb15ca45eee8fd1140942", + "sha256:5b602b4201b965a8354d74e232364a66ff243dd142e350d035f46169bb36e13d", + "sha256:5bbda3c70dd35d60671bc33b01916802707a052130d9e50cdb871d34594d35cb", + "sha256:602024dae6d77e161f4b89491b62ca1d4f19949d79d47b2db057e476d21179d6", + "sha256:61a61b4a95a4f97922c3a6f5606d3e360851584bd47e500a5161373c53810e3d", + "sha256:63aff70fe5aac59c72215f42ec39fcb59ff46774fa966e717f8ecb6ee2273577", + "sha256:71890d5247020c25c21a6b65202782bfc281d4e6e244842419d30e3492bb6dcc", + "sha256:73a29b5ba642e35433166a03a3e02935e7238c4b3467fbd77523b99edea23e5b", + "sha256:7969bffa322c097bd46ae595ada6a931cefda613f18ba64587e9cff4cb320756", + "sha256:7ac4abb3877c43af320392c664774eef6fa2cc063c79a55fc02d844a3cbe7395", + "sha256:7f731ebac68ea06d628658295cb2d217b10186329fcf9a3b6a149045059bf92e", + "sha256:7f924a5a9d5890649566f2f6682e0d8ad8ca23028bacffbbac36dbd7fd680176", + "sha256:874cea8bb1ec1ddccbacbd027856f6bf496f6bc18aba97a918c20e067edab236", + "sha256:876077e7ebb8c84ed068e2b23d4c62ebb010d60df84b9591af1be2f39010ffb2", + "sha256:886bcf1870af74c32bc310fd00a6b803445e17e51b7d5a107c7b35c0f362cc16", + "sha256:8b27df301f56e3b3d2298095c8f7d6b68f2521f6b1693e901fa039bdbae34424", + "sha256:8b7c73d1cef3d9ae963e9ff03f6222df43efbb9054ffd2f1969c935b7fc84c02", + "sha256:8cda13494d86a4f12429641117cb6ac4bbbc9c30a33f711f7d3a2e5fbe4b0b7e", + "sha256:8cddea1b8339451c2fb3388e138347b6126744f33b611bdb55b7357361cfef46", + "sha256:8dba0129b93e7091dfefaf4cf7000172741bff7f47bf6326fcf17f32fbb54d6b", + "sha256:8e67c43bdfc88d5fee6db0d3e40175b362fc95fb85f0412d233b9b203c53a575", + "sha256:9133d68624b1f2e89ec2f554d56aea8a5b0d7168cd9320200ba58d4d794845a4", + "sha256:916f92f2a8db10508f739d0b5e00b83defe5d1115a997c54532a6d7cf8c95404", + "sha256:9297fb9c39b9a2c039dbcd306c410bd6906b95244dec3bba4318d36c718c164c", + "sha256:95e7c44d072db623a1aab04ce488cf9533294a77ed9d072cd503a3596f4106ac", + "sha256:975736b002ed080d124cf81a79cb7e05cb26d6b3f5c7a7b651c0fcce70353aa1", + "sha256:97c5a53e8c1754df58e73f047a99e287d4da1bdfe64b0072fb25c87000897951", + "sha256:9a09d59bef1db94f384b5bcc2d523694d338f3df6b757aeeaf7baca5d0c0be88", + "sha256:a364c1ea75dc51b83a17f52fe0c79cf8bc4ddf740403bebd4581c7666eea017d", + "sha256:a3b4a01c6da07ef9f80d4fe8933b994bc99747bcea3eab0330a9c34d3c12655b", + "sha256:a5876d0a60355af98d535c47f6cd6eb0f8a432396dab26845d380b92f8412422", + "sha256:a6a4b98a9132e0f45c9fc245a63894cfd8c45fb7a0d6bffc5eab3ec327cf7324", + "sha256:a6b4ff33f7e011bbaa148238d131c4fd4f8afbab3c104ddfbdb2b12b74ff7016", + "sha256:a93ee7c6e8fd0f8a83525a51bd777be57ee17787e91d805bd8d6faf9dcada18e", + "sha256:b374e79ffa7511afc11773aef40a4ccea6191fba1c856ea2f9c56738dca69d7a", + "sha256:b7d501d5eb5d4f67207df364752ad697465b834268744be7581c18d81d35d41d", + "sha256:c59acfa8eb73a1e0d484392dc002bdf001fd4ce73394e0132df3d1ab6093d7cb", + "sha256:c75116c9de79949de23006e2d9b35ee82874c594fcf5c0311b439acaa14b8441", + "sha256:ca80a49b53ed1d22f7282da7255f7bb2fd1935fd0f623d8613fda38745f18961", + "sha256:cad5782f93f7f738b62c6527b6f32a60694d924029f299a8b524758cfa53d815", + "sha256:ccadce0130fd813ec86ebfe969a6c58b42acc1d0fe55a47525375b740e07b605", + "sha256:d701eab36200c36224833d07dbdb709adb7fd4253429548ddb5e547b8ed40586", + "sha256:dad3d233d441a022c1f7155f0fb9d5aff7b97c1ea8c7dfa02cce586b16ab2d0b", + "sha256:dd0b83bed3405b586a3133629f1d1a5bc7bfd64822a3b7ab342bdc68e6dbc61b", + "sha256:de3de000d459402cda015068fd135aa50c0bf6f2477a80d4da1e646f123b4e78", + "sha256:de9923832f2d8c1a5ecd8d7260465a6ca5a86888a0d129e3bd5cf0406d2fc5bf", + "sha256:df19e2d0b1620039af5102563fbd96e8938c7f5c3f5828528d641d9fc585525e", + "sha256:e85880b538e59a59f55117b81f208a6660ad5ac328aad9305f812d9b8bc67a0f", + "sha256:ee7d9da3bf493909cf811a3f038840cb34fab5ae2956b8a263919f6e289ab188", + "sha256:eed88b64a5e5da72d6a71cdc5aaeefaa5ced9b748f8d19f89800b339961dad39", + "sha256:f0ba7c2a329d650628f4c8572fd1db29f0a59dd70a3e3e0710dcf18a35cce9d8", + "sha256:f8e63209c3e1e828ee6a457529b4a6d8b05d050fe0ae03a7ae49e967c5d312e0", + "sha256:f8f0bd690e1a41294ac87905e8121c81a3761ec2583c768f13467428606c8c7a", + "sha256:f96f0e30b5a95c7631b12bfe214cbc90ec8fe8cfa36920596c10514a65743519", + "sha256:f98e8215e172f567ce80eeaed9107fb4d32b6c44f26983d9b8334658136a205a", + "sha256:f9fe868463ec7e1363733af77e38a5fda3e9b63940337048c945d69e0c80ff24", + "sha256:fdacf26402389bdd89857ad3c045a26fe8f3314f9a8b28226f82f88463a65b77", + "sha256:fe3170a69fe039b18ad18171e66faa9a75f6fe9d78f968fd9b54e09fbd714d81", + "sha256:fea4427d1ffdb3b523d7daa6712038428a4c16c450b9777bdd1221cfee0eab49" ], "markers": "python_version >= '3.10'", - "version": "==3.3.2" + "version": "==3.5.6" }, "gunicorn": { "extras": [ @@ -812,11 +885,11 @@ }, "idna": { "hashes": [ - "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", - "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902" + "sha256:a7db850025b95ded1eae8a46181a1a6c56c92c96f0e2b005d9ff8dc0210cab44", + "sha256:ab7ae7122974553370f0bdb919e1a960b2cd1bc1ef0276416d896db81c14582c" ], - "markers": "python_version >= '3.8'", - "version": "==3.11" + "markers": "python_version >= '3.9'", + "version": "==3.20" }, "importlib-metadata": { "hashes": [ @@ -887,11 +960,11 @@ }, "mako": { "hashes": [ - "sha256:99579a6f39583fa7e5630a28c3c1f440e4e97a414b80372649c0ce338da2ea28", - "sha256:baef24a52fc4fc514a0887ac600f9f1cff3d82c61d4d700a1fa84d597b88db59" + "sha256:723296007c870bfd6b3f0c3230dba7198096e5269297ebf5e4eff9e7ffa39d4f", + "sha256:cd6537fe88d5fec315c55c2f8529bc4ce7a9a352ad7db3eeaa6a66e2dd4ec37a" ], - "markers": "python_version >= '3.8'", - "version": "==1.3.10" + "markers": "python_version >= '3.10'", + "version": "==1.4.3" }, "markupsafe": { "hashes": [ @@ -990,12 +1063,12 @@ }, "marshmallow": { "hashes": [ - "sha256:3350409f20a70a7e4e11a27661187b77cdcaeb20abca41c1454fe33636bea09c", - "sha256:e6d8affb6cb61d39d26402096dc0aee12d5a26d490a121f118d2e81dc0719dc6" + "sha256:013fa8a3c4c276c24d26d84ce934dc964e2aa794345a0f8c7e5a7191482c8a73", + "sha256:bbe2adb5a03e6e3571b573f42527c6fe926e17467833660bebd11593ab8dfd57" ], "index": "pypi", "markers": "python_version >= '3.9'", - "version": "==3.26.1" + "version": "==3.26.2" }, "marshmallow-sqlalchemy": { "hashes": [ @@ -1008,241 +1081,260 @@ }, "multidict": { "hashes": [ - "sha256:026d264228bcd637d4e060844e39cdc60f86c479e463d49075dedc21b18fbbe0", - "sha256:03ede2a6ffbe8ef936b92cb4529f27f42be7f56afcdab5ab739cd5f27fb1cbf9", - "sha256:0458c978acd8e6ea53c81eefaddbbee9c6c5e591f41b3f5e8e194780fe026581", - "sha256:067343c68cd6612d375710f895337b3a98a033c94f14b9a99eff902f205424e2", - "sha256:08ccb2a6dc72009093ebe7f3f073e5ec5964cba9a706fa94b1a1484039b87941", - "sha256:0b38ebffd9be37c1170d33bc0f36f4f262e0a09bc1aac1c34c7aa51a7293f0b3", - "sha256:0b4c48648d7649c9335cf1927a8b87fa692de3dcb15faa676c6a6f1f1aabda43", - "sha256:0d17522c37d03e85c8098ec8431636309b2682cf12e58f4dbc76121fb50e4962", - "sha256:0e161ddf326db5577c3a4cc2d8648f81456e8a20d40415541587a71620d7a7d1", - "sha256:0e697826df7eb63418ee190fd06ce9f1803593bb4b9517d08c60d9b9a7f69d8f", - "sha256:10ae39c9cfe6adedcdb764f5e8411d4a92b055e35573a2eaa88d3323289ef93c", - "sha256:121a34e5bfa410cdf2c8c49716de160de3b1dbcd86b49656f5681e4543bcd1a8", - "sha256:128441d052254f42989ef98b7b6a6ecb1e6f708aa962c7984235316db59f50fa", - "sha256:12fad252f8b267cc75b66e8fc51b3079604e8d43a75428ffe193cd9e2195dfd6", - "sha256:14525a5f61d7d0c94b368a42cff4c9a4e7ba2d52e2672a7b23d84dc86fb02b0c", - "sha256:17207077e29342fdc2c9a82e4b306f1127bf1ea91f8b71e02d4798a70bb99991", - "sha256:17307b22c217b4cf05033dabefe68255a534d637c6c9b0cc8382718f87be4262", - "sha256:1b99af4d9eec0b49927b4402bcbb58dea89d3e0db8806a4086117019939ad3dd", - "sha256:1d540e51b7e8e170174555edecddbd5538105443754539193e3e1061864d444d", - "sha256:1e3a8bb24342a8201d178c3b4984c26ba81a577c80d4d525727427460a50c22d", - "sha256:1fa6609d0364f4f6f58351b4659a1f3e0e898ba2a8c5cac04cb2c7bc556b0bc5", - "sha256:21f830fe223215dffd51f538e78c172ed7c7f60c9b96a2bf05c4848ad49921c3", - "sha256:233b398c29d3f1b9676b4b6f75c518a06fcb2ea0b925119fb2c1bc35c05e1601", - "sha256:24c0cf81544ca5e17cfcb6e482e7a82cd475925242b308b890c9452a074d4505", - "sha256:25167cc263257660290fba06b9318d2026e3c910be240a146e1f66dd114af2b0", - "sha256:253282d70d67885a15c8a7716f3a73edf2d635793ceda8173b9ecc21f2fb8292", - "sha256:273d23f4b40f3dce4d6c8a821c741a86dec62cded82e1175ba3d99be128147ed", - "sha256:283ddac99f7ac25a4acadbf004cb5ae34480bbeb063520f70ce397b281859362", - "sha256:28ca5ce2fd9716631133d0e9a9b9a745ad7f60bac2bccafb56aa380fc0b6c511", - "sha256:2b41f5fed0ed563624f1c17630cb9941cf2309d4df00e494b551b5f3e3d67a23", - "sha256:2bbd113e0d4af5db41d5ebfe9ccaff89de2120578164f86a5d17d5a576d1e5b2", - "sha256:2e1425e2f99ec5bd36c15a01b690a1a2456209c5deed58f95469ffb46039ccbb", - "sha256:2e2d2ed645ea29f31c4c7ea1552fcfd7cb7ba656e1eafd4134a6620c9f5fdd9e", - "sha256:3758692429e4e32f1ba0df23219cd0b4fc0a52f476726fff9337d1a57676a582", - "sha256:38fb49540705369bab8484db0689d86c0a33a0a9f2c1b197f506b71b4b6c19b0", - "sha256:3943debf0fbb57bdde5901695c11094a9a36723e5c03875f87718ee15ca2f4d2", - "sha256:398c1478926eca669f2fd6a5856b6de9c0acf23a2cb59a14c0ba5844fa38077e", - "sha256:3ab8b9d8b75aef9df299595d5388b14530839f6422333357af1339443cff777d", - "sha256:3bd231490fa7217cc832528e1cd8752a96f0125ddd2b5749390f7c3ec8721b65", - "sha256:3d51ff4785d58d3f6c91bdbffcb5e1f7ddfda557727043aa20d20ec4f65e324a", - "sha256:3fccb473e87eaa1382689053e4a4618e7ba7b9b9b8d6adf2027ee474597128cd", - "sha256:401c5a650f3add2472d1d288c26deebc540f99e2fb83e9525007a74cd2116f1d", - "sha256:41f2952231456154ee479651491e94118229844dd7226541788be783be2b5108", - "sha256:432feb25a1cb67fe82a9680b4d65fb542e4635cb3166cd9c01560651ad60f177", - "sha256:439cbebd499f92e9aa6793016a8acaa161dfa749ae86d20960189f5398a19144", - "sha256:4885cb0e817aef5d00a2e8451d4665c1808378dc27c2705f1bf4ef8505c0d2e5", - "sha256:497394b3239fc6f0e13a78a3e1b61296e72bf1c5f94b4c4eb80b265c37a131cd", - "sha256:497bde6223c212ba11d462853cfa4f0ae6ef97465033e7dc9940cdb3ab5b48e5", - "sha256:4cfb48c6ea66c83bcaaf7e4dfa7ec1b6bbcf751b7db85a328902796dfde4c060", - "sha256:538cec1e18c067d0e6103aa9a74f9e832904c957adc260e61cd9d8cf0c3b3d37", - "sha256:55d97cc6dae627efa6a6e548885712d4864b81110ac76fa4e534c03819fa4a56", - "sha256:563fe25c678aaba333d5399408f5ec3c383ca5b663e7f774dd179a520b8144df", - "sha256:57b46b24b5d5ebcc978da4ec23a819a9402b4228b8a90d9c656422b4bdd8a963", - "sha256:5884a04f4ff56c6120f6ccf703bdeb8b5079d808ba604d4d53aec0d55dc33568", - "sha256:59bc83d3f66b41dac1e7460aac1d196edc70c9ba3094965c467715a70ecb46db", - "sha256:5a37ca18e360377cfda1d62f5f382ff41f2b8c4ccb329ed974cc2e1643440118", - "sha256:5c4b9bfc148f5a91be9244d6264c53035c8a0dcd2f51f1c3c6e30e30ebaa1c84", - "sha256:5e01429a929600e7dab7b166062d9bb54a5eed752384c7384c968c2afab8f50f", - "sha256:5fa6a95dfee63893d80a34758cd0e0c118a30b8dcb46372bf75106c591b77889", - "sha256:619e5a1ac57986dbfec9f0b301d865dddf763696435e2962f6d9cf2fdff2bb71", - "sha256:65573858d27cdeaca41893185677dc82395159aa28875a8867af66532d413a8f", - "sha256:6704fa2b7453b2fb121740555fa1ee20cd98c4d011120caf4d2b8d4e7c76eec0", - "sha256:6aac4f16b472d5b7dc6f66a0d49dd57b0e0902090be16594dc9ebfd3d17c47e7", - "sha256:6b10359683bd8806a200fd2909e7c8ca3a7b24ec1d8132e483d58e791d881048", - "sha256:6b83cabdc375ffaaa15edd97eb7c0c672ad788e2687004990074d7d6c9b140c8", - "sha256:6d3bc717b6fe763b8be3f2bee2701d3c8eb1b2a8ae9f60910f1b2860c82b6c49", - "sha256:6f77ce314a29263e67adadc7e7c1bc699fcb3a305059ab973d038f87caa42ed0", - "sha256:749aa54f578f2e5f439538706a475aa844bfa8ef75854b1401e6e528e4937cf9", - "sha256:7a7e590ff876a3eaf1c02a4dfe0724b6e69a9e9de6d8f556816f29c496046e59", - "sha256:7dfb78d966b2c906ae1d28ccf6e6712a3cd04407ee5088cd276fe8cb42186190", - "sha256:7eee46ccb30ff48a1e35bb818cc90846c6be2b68240e42a78599166722cea709", - "sha256:7ff981b266af91d7b4b3793ca3382e53229088d193a85dfad6f5f4c27fc73e5d", - "sha256:841189848ba629c3552035a6a7f5bf3b02eb304e9fea7492ca220a8eda6b0e5c", - "sha256:844c5bca0b5444adb44a623fb0a1310c2f4cd41f402126bb269cd44c9b3f3e1e", - "sha256:84e61e3af5463c19b67ced91f6c634effb89ef8bfc5ca0267f954451ed4bb6a2", - "sha256:8affcf1c98b82bc901702eb73b6947a1bfa170823c153fe8a47b5f5f02e48e40", - "sha256:8be1802715a8e892c784c0197c2ace276ea52702a0ede98b6310c8f255a5afb3", - "sha256:8f333ec9c5eb1b7105e3b84b53141e66ca05a19a605368c55450b6ba208cb9ee", - "sha256:9004d8386d133b7e6135679424c91b0b854d2d164af6ea3f289f8f2761064609", - "sha256:90efbcf47dbe33dcf643a1e400d67d59abeac5db07dc3f27d6bdeae497a2198c", - "sha256:935434b9853c7c112eee7ac891bc4cb86455aa631269ae35442cb316790c1445", - "sha256:93b1818e4a6e0930454f0f2af7dfce69307ca03cdcfb3739bf4d91241967b6c1", - "sha256:95922cee9a778659e91db6497596435777bd25ed116701a4c034f8e46544955a", - "sha256:960c83bf01a95b12b08fd54324a4eb1d5b52c88932b5cba5d6e712bb3ed12eb5", - "sha256:97231140a50f5d447d3164f994b86a0bed7cd016e2682f8650d6a9158e14fd31", - "sha256:974e72a2474600827abaeda71af0c53d9ebbc3c2eb7da37b37d7829ae31232d8", - "sha256:97891f3b1b3ffbded884e2916cacf3c6fc87b66bb0dde46f7357404750559f33", - "sha256:98655c737850c064a65e006a3df7c997cd3b220be4ec8fe26215760b9697d4d7", - "sha256:98bc624954ec4d2c7cb074b8eefc2b5d0ce7d482e410df446414355d158fe4ca", - "sha256:98c5787b0a0d9a41d9311eae44c3b76e6753def8d8870ab501320efe75a6a5f8", - "sha256:9b0d9b91d1aa44db9c1f1ecd0d9d2ae610b2f4f856448664e01a3b35899f3f92", - "sha256:9c90fed18bffc0189ba814749fdcc102b536e83a9f738a9003e569acd540a733", - "sha256:9d624335fd4fa1c08a53f8b4be7676ebde19cd092b3895c421045ca87895b429", - "sha256:9f9af11306994335398293f9958071019e3ab95e9a707dc1383a35613f6abcb9", - "sha256:a0543217a6a017692aa6ae5cc39adb75e587af0f3a82288b1492eb73dd6cc2a4", - "sha256:a088b62bd733e2ad12c50dad01b7d0166c30287c166e137433d3b410add807a6", - "sha256:a407f13c188f804c759fc6a9f88286a565c242a76b27626594c133b82883b5c2", - "sha256:a90f75c956e32891a4eda3639ce6dd86e87105271f43d43442a3aedf3cddf172", - "sha256:a9fc4caa29e2e6ae408d1c450ac8bf19892c5fca83ee634ecd88a53332c59981", - "sha256:aa23b001d968faef416ff70dc0f1ab045517b9b42a90edd3e9bcdb06479e31d5", - "sha256:ac1c665bad8b5d762f5f85ebe4d94130c26965f11de70c708c75671297c776de", - "sha256:af959b9beeb66c822380f222f0e0a1889331597e81f1ded7f374f3ecb0fd6c52", - "sha256:b0fa96985700739c4c7853a43c0b3e169360d6855780021bfc6d0f1ce7c123e7", - "sha256:b26684587228afed0d50cf804cc71062cc9c1cdf55051c4c6345d372947b268c", - "sha256:b4938326284c4f1224178a560987b6cf8b4d38458b113d9b8c1db1a836e640a2", - "sha256:b8c990b037d2fff2f4e33d3f21b9b531c5745b33a49a7d6dbe7a177266af44f6", - "sha256:ba0a9fb644d0c1a2194cf7ffb043bd852cea63a57f66fbd33959f7dae18517bf", - "sha256:bb08271280173720e9fea9ede98e5231defcbad90f1624bea26f32ec8a956e2f", - "sha256:bdbf9f3b332abd0cdb306e7c2113818ab1e922dc84b8f8fd06ec89ed2a19ab8b", - "sha256:bfde23ef6ed9db7eaee6c37dcec08524cb43903c60b285b172b6c094711b3961", - "sha256:c0abd12629b0af3cf590982c0b413b1e7395cd4ec026f30986818ab95bfaa94a", - "sha256:c102791b1c4f3ab36ce4101154549105a53dc828f016356b3e3bcae2e3a039d3", - "sha256:c3a32d23520ee37bf327d1e1a656fec76a2edd5c038bf43eddfa0572ec49c60b", - "sha256:c524c6fb8fc342793708ab111c4dbc90ff9abd568de220432500e47e990c0358", - "sha256:c5f0c21549ab432b57dcc82130f388d84ad8179824cc3f223d5e7cfbfd4143f6", - "sha256:c6b3228e1d80af737b72925ce5fb4daf5a335e49cd7ab77ed7b9fdfbf58c526e", - "sha256:c76c4bec1538375dad9d452d246ca5368ad6e1c9039dadcf007ae59c70619ea1", - "sha256:c9035dde0f916702850ef66460bc4239d89d08df4d02023a5926e7446724212c", - "sha256:c93c3db7ea657dd4637d57e74ab73de31bccefe144d3d4ce370052035bc85fb5", - "sha256:cb2a55f408c3043e42b40cc8eecd575afa27b7e0b956dfb190de0f8499a57a53", - "sha256:cdea2e7b2456cfb6694fb113066fd0ec7ea4d67e3a35e1f4cbeea0b448bf5872", - "sha256:ce1bbd7d780bb5a0da032e095c951f7014d6b0a205f8318308140f1a6aba159e", - "sha256:cf37cbe5ced48d417ba045aca1b21bafca67489452debcde94778a576666a1df", - "sha256:d4f49cb5661344764e4c7c7973e92a47a59b8fc19b6523649ec9dc4960e58a03", - "sha256:d54ecf9f301853f2c5e802da559604b3e95bb7a3b01a9c295c6ee591b9882de8", - "sha256:d62b7f64ffde3b99d06b707a280db04fb3855b55f5a06df387236051d0668f4a", - "sha256:d82dd730a95e6643802f4454b8fdecdf08667881a9c5670db85bc5a56693f122", - "sha256:da62917e6076f512daccfbbde27f46fed1c98fee202f0559adec8ee0de67f71a", - "sha256:dd96c01a9dcd4889dcfcf9eb5544ca0c77603f239e3ffab0524ec17aea9a93ee", - "sha256:df9f19c28adcb40b6aae30bbaa1478c389efd50c28d541d76760199fc1037c32", - "sha256:e1c5988359516095535c4301af38d8a8838534158f649c05dd1050222321bcb3", - "sha256:e628ef0e6859ffd8273c69412a2465c4be4a9517d07261b33334b5ec6f3c7489", - "sha256:e82d14e3c948952a1a85503817e038cba5905a3352de76b9a465075d072fba23", - "sha256:e954b24433c768ce78ab7929e84ccf3422e46deb45a4dc9f93438f8217fa2d34", - "sha256:eb0ce7b2a32d09892b3dd6cc44877a0d02a33241fafca5f25c8b6b62374f8b75", - "sha256:eb304767bca2bb92fb9c5bd33cedc95baee5bb5f6c88e63706533a1c06ad08c8", - "sha256:eb351f72c26dc9abe338ca7294661aa22969ad8ffe7ef7d5541d19f368dc854a", - "sha256:ec6652a1bee61c53a3e5776b6049172c53b6aaba34f18c9ad04f82712bac623d", - "sha256:f2a0a924d4c2e9afcd7ec64f9de35fcd96915149b2216e1cb2c10a56df483855", - "sha256:f33dc2a3abe9249ea5d8360f969ec7f4142e7ac45ee7014d8f8d5acddf178b7b", - "sha256:f537b55778cd3cbee430abe3131255d3a78202e0f9ea7ffc6ada893a4bcaeea4", - "sha256:f5dd81c45b05518b9aa4da4aa74e1c93d715efa234fd3e8a179df611cc85e5f4", - "sha256:f99fe611c312b3c1c0ace793f92464d8cd263cc3b26b5721950d977b006b6c4d", - "sha256:fa263a02f4f2dd2d11a7b1bb4362aa7cb1049f84a9235d31adf63f30143469a0", - "sha256:fc5907494fccf3e7d3f94f95c91d6336b092b5fc83811720fae5e2765890dfba", - "sha256:fcee94dfbd638784645b066074b338bc9cc155d4b4bffa4adce1615c5a426c19" + "sha256:006c4478de0a1876f4834e14255776286f09b9846b505fe63f67f9d173a9487c", + "sha256:024123f0ab402ab33828e24eb80fa8f25167d0d3783ba5f287e39ed741e6abf9", + "sha256:02f6d0c4b70f783305e73f9944d8efe6be1022550f0974ba0ae9d8893c0350fa", + "sha256:02fe09dc197b8ae7e355371e51e5dce2f39060cd5a8badf94904527e23a3f188", + "sha256:03731f6fc036180700c9dc2308205a48e5ca6f3ff03087739ab746f294022201", + "sha256:03d47df72f084f757c1cb771188d5f4e3a805e4abc4d67e32509272343ae9382", + "sha256:03fac50ddfd8302175b77863a015eccfae76767cda5506eef86df559ba861e1f", + "sha256:042fb0196047e786936a730bd302de83143950da45f2c16078da8f35e1cf7919", + "sha256:083735b7f395894e43adb278d5dae901448883a835ff8f1977e285fefdb10418", + "sha256:095d900c242e00fbe5f321ee072e7278b4153e78c5ce9c1efde167d62c1e4771", + "sha256:0a5769559e3312dd96731fbe15b4abb6033368ac1cad5a98dadd21946a4c7d6c", + "sha256:0b2fb8c349d1103863750b5d8cb5ace766917f4b35f3d883c8f778853eaa9f76", + "sha256:0dd655518f136febd96c05131a76a863e32fc2a1d7acd4e3c959e3ceb77d8345", + "sha256:0f06e60fa190aa7abd0914c2a766736fdc8e9f34878c4346338534b73d1b20e2", + "sha256:0f2ce963299d42fa3f22a90adc0fdf174792ffef5ff4c7ffb68260548fb05580", + "sha256:0f3bd290711c6e9486173a6ee7cd4e7f00c3971c7908c1ec1b6e5437c5e4c6f9", + "sha256:10083a8a0f4e1b26b599889e90b9802504ce5d3f7722f925bbb7ca47dd22a7c1", + "sha256:13849a1d4f54c3809ae721e9e83ab28f5ea602f33660cb84eb6ef261eac706c1", + "sha256:14c56f73e78faa1f68bbb826197cd5871994e70e841b8590829c35912ece5c64", + "sha256:15db6a102cbaf1949cf028ecf080aac76d20bcd29ad4e092574db6c6b7af78a5", + "sha256:19e31815d41cefc365489e591d105d2baceb2f65aa75d29471fbdbda8651e006", + "sha256:1a53de2772cfb74559df2eb4456ec4eeb908435ec55a84b69370d9d745d62aa8", + "sha256:1a8adfcaf96f587ab138476eaddef95f29b8a2a8a9afbfea8d2fd62180995d02", + "sha256:1a938761c77e0e6edb0c93d02f4e988d44a69e5195e5a3b893e5553311347132", + "sha256:1c9f3c25df6c9d3bbae4f6fd3f514b1c5c740a2110f56ccf36069c85417e289c", + "sha256:1ca5ebe6d454f1e5496cf052386a559f1080bf2de75bf327ebca0a6003b79f19", + "sha256:1d804e4caf5d5da37d6dac1325da5629ebef1e27a294c2b568b295814aa36c7b", + "sha256:1fee9a16d88a1c4865610de31ef5c666671020d7a81d1f510eaf3c97d00ebeba", + "sha256:23136f5a564654eb61061ec6d5620a4c1ea32c8f552b65e9982a12b72bff601b", + "sha256:2784090c30a586d5b45197bd9c32f87fb927216cde302f6cfd76d76577e90f08", + "sha256:29138fef49828542e859828107e42e50d0e587c513b7eb4b2d92bade2b0860fe", + "sha256:2c1aeb92eea59d824f004341b26d5e4b47a8a441cf9726769b9a90abf9d0e08f", + "sha256:2c5d675da8f1cb5650271c8ad5e95c0a3e5a183c105e72d953b12877b1c8d0fd", + "sha256:3100d169ceb7bc8f05f89a6db11d1b21f119975fc26f29dc45a472e3569f0879", + "sha256:31199204b3ced121ff5407a2c342326a5d27e3870abbf94bd80dbd2451b7bc8f", + "sha256:32217133dddc58c927805cf6c0731d8144584176b768042ee886d51e71860bc9", + "sha256:33fa55b990f81c2927e01399ace0d18926c69d69baa8cdaa819424132fb97987", + "sha256:35ba0263bae5dd3ad5aad767cc9afc01a8598c7dae30f1b3b2de98b1b32c28bd", + "sha256:35fc236507fb1b3138f0af5ecd5f94ed752d4d6d826248eae425f86204013eea", + "sha256:361f7206cf341ba94fb015688f5c8b480f8e63bd58a4c14a48aeca7851a241cc", + "sha256:369b5aa01b241cd3fea6890bdbb11a1425d87bf1515831500d518f4223e9d72c", + "sha256:37245ca4105386194dd1d292a6f2aae09bfe1bd7ac6f9ec25093e3cf8e9b143b", + "sha256:372c063f37480f62c1ae32dc3a1a0a5942b180c883f99789075a8a8ec3c4e709", + "sha256:37a9ebe00c698279213d56e6c64e1962ab1e092918270649b397cac3dc196ca4", + "sha256:38c9986f9ce50c459b10de216a05f4bd7ed5ac63887d56e500a52bb464b861ce", + "sha256:3adf06c66041aa21eeb8a71e82379b74773298c8e6d3d839b151aae441a99b94", + "sha256:3c95601ed98fad3f6e2f8fe809c3b526b0fab31ef525e00a155e227f3d17f58a", + "sha256:40aec5299e1ed71fbb988389059da381c3c1a60e0c649acceb2a35d9b128848e", + "sha256:43124fe172ada86d03ac3c8dc8179091341f6724d5e5d5b160e1587e4cd3761b", + "sha256:4736d350371337825cac1793c9f7c40701c32a03912548c2a7608e51679cbb96", + "sha256:475d04d5192eba487a3e2f935976340baa24529046e9c1c9c7a3b7bf80445ae1", + "sha256:4a409ccc42aefec904038695d5d7fd6d8f3af2721b7b6401d55135ec7d6d298e", + "sha256:4d718fa1b5f0d0dd75e86fbbc5b0c93ea3a5d65216c85c61cd5d7cdddfe08455", + "sha256:501ed8b02a5990c67a91c732843609d43a6be1f7576fcdfc867331239f37fbd3", + "sha256:539c2cd5fed0947c135cd7eabaaac55f48300dfa1de0f3ca4edb5efa6606f471", + "sha256:557a4e1708df428ebe6c3081c83a273d275dad2446ce0d81fc648ac71afdb18d", + "sha256:56d834b74c993a7d7cb2b8ab33a0d55c3e0d4a3d2f2da2808a4ad3d79189711b", + "sha256:5800368526647146978389dfaa46da3356291e9f0fff9a4ef12e8c2bef964a0d", + "sha256:59c123d0e948d760a5f930f316cfefa07e8d632ab84327c0693ee6a88171154f", + "sha256:5b30ddf7234e611ca877575b62840e6af5977f92f1f9d532eedbb05a44ff8004", + "sha256:5ecace251ccfa705bf3d7d35c5032cf750f5c629809740405697bce5c118c4a4", + "sha256:5f89dad732280e7a10b74d40b91364f88e13c3f2c08c2ef83a8cd42f7a61af2e", + "sha256:637f4ae36264bd7b8d9a60193acddc1d735ad52e8ed53a19931ea6d921fea8e5", + "sha256:63ada7ee2e9345695f9e9bc4c65d72222253f07b1ac94fd0e37555cc6f3c7f60", + "sha256:6441cc837aea58be7d9baef1b2383eb8311ab9303f500f99ac90b584cd78bb14", + "sha256:658f90f49cf5af2441cad0a2b801c3ef520471989a1ec55bcb25b255b2ca8d2f", + "sha256:66987aa68b0f7c2a1cc5f388ca962b8ed92b10f79de38d6d0d8c716154f519d9", + "sha256:696477ad71385c4795e3b8e4cf10b0d2c28c2a1ca6a955e031cb1e62993e9ee3", + "sha256:6b7e54fd883671d1a8810704851c044b7173287c552b9f5c3d9e0eb9f00ae194", + "sha256:6bc94fe17c3c56e5418f79515b786b101845f70609b0d19d0c1ba13448e5633a", + "sha256:6e6b7e3a1520c39a2772f414cd9ddf5995f77e4e823dfa1522af383addd465a3", + "sha256:6ed30be8918e18c8bed0a2e8b70639ecf02feb61ed00ca2e41cfcb2a50fa3f42", + "sha256:73533644e1f69ea1164d56cc6505f564c6c44072b646b66d67df2d31fed0348c", + "sha256:73bcafa21a78d0776b3ee7cd2a63c66f968eb7db8e8d594e32d7329950f6e828", + "sha256:7814bbee202acd3bd240204c17d8b87a4c48c81064fd8674dbe527d94d5a4290", + "sha256:783ba7d845d79ce976afd9c1e91a4e5714671defa198ee789e8b23316083a485", + "sha256:79da2491348b30810728050b4a8ec0416f85884125c2fd44655b3d01150d9c3e", + "sha256:7a0c98f6a636adf0d7edd60c61589eaf52d149239af754d0bfeb0effedba53a8", + "sha256:7ab379f95caee071a37cbd8be86d4c65accc651d391f9f97748fef006f38769c", + "sha256:7bf6478188f4e47bf5686e8a33da4ae28bf43b1b2528d9ee144d28492bfac60b", + "sha256:7c6eecfab7ce4cd9487ff8ba936fe38cdfd68c04faf3d5c710363c6a8e695659", + "sha256:7c708566da8014b120a64b1eb6d200c6c0c8cb36296383723cdb6fc82038270b", + "sha256:7c8d5882ba25ac0282258be435d8a05aa0cbcacfce15799154a338f847f159b9", + "sha256:7fc59e9ba821b220944ccfe0f89c9dc4745f6d097569992356eb03869f21e953", + "sha256:7fd79c521f6290c69125fa2b85fa65d9e657e6a8ffaf722dc881b926bef4aa5c", + "sha256:803f8b575a71b1b299d677c28db0653459c79b5308874efec813f17b7457c7f1", + "sha256:8050e75af7e4c6e2d5260b84eeedb618f3e452e66473432e085b5d1b81429299", + "sha256:81cdc537e0a42e3c0170752fcadbe450246d5c3b4b7231d6eb9672456605ac94", + "sha256:827c92145b3b976b39430129c89d213b250dacbe5fce678e9a03940e6e848983", + "sha256:854fd2f1bc6e8a56b89910b5cd7261a8b40f13ebb31572da985ce59c7da0886d", + "sha256:877ca17fdcfdf5c397493a71e5ff97a87bb181417fe717fdadc77c08c09301ac", + "sha256:87cc632c88ee5dc80e12681047839304d98ee5c9a708d686505767001c9b8b9a", + "sha256:8879510a76940670517ea1cb589978da44b86e286ec3e50d664ef330817afce7", + "sha256:8885e3808aedbd6725b921fb67dacaae0678933561ddd47c2b01315198c70e2e", + "sha256:8b193bf7a443c97d81c47052f60c486071a4bdef4a573fa2514f920089414d45", + "sha256:8ed78ccad4c7b421804f5d524b7740946a7ef75d89dc0dac52e9d7c24c472410", + "sha256:8f2973bbd2bebd9d2e0cd6394c1292a1a19ccd56bdcbe1e174059f1a39be5b40", + "sha256:910d4260512660484c0dc1588a316fbb35a40c081c36fc51d1225351af17cfe4", + "sha256:95052e8777a86bae87c0bd0b5ab22d809e3d1d02bf69e3e66ddda5ba75a05805", + "sha256:95f273bea318a194f656527ee2ed19494327bc500b8e87d9358e3222579aa28d", + "sha256:963a8d8f97057082679523d0fd4c53a38f86bc58cabe4556faef682ae53fa2fa", + "sha256:976fd7689d69ec78d67d31d38d396d8adb562f7e8368279f76aed4aa451fa06d", + "sha256:989261c5f1735a165f2e4e87cf6d5f17ab734fa18f9ad0383d5adfcdaefce701", + "sha256:9ae9614c317c50836689ce2dfde07c05fe0b16378562e2221746c3913ede3c80", + "sha256:9b0124b9c17e9890f0819b2e7a5f65ec9a2f5aabd6c8e7ad090c1675cf70dee6", + "sha256:9c4880d017555d70dea367dd49271830842d48e3891c2da97da7ce8c4abcee40", + "sha256:9c62e71e6289d78c0108d8aeb495f8bd3cad4bc1632fedddc9297ddf287ecc20", + "sha256:9d0a21cf76153de8f2d96a877991d6bc59b9ab5180b949e50db73cc193b4a694", + "sha256:9e14d17773b1b3c758ff153659a1824608a0cb562c45f484b5ed8a433428444a", + "sha256:a16a1dc8529f9e734a41c3b856f3eae7ebacdc061dde3f8a844e0c7889c97203", + "sha256:a2212a0c842c723d919ea4a22a9296cb6b244b386e4e6ea92adfc7fbf3095519", + "sha256:a313bad717dde740959d50850c315b75fd4eb0c5e6b4dc8535db0f1c369be125", + "sha256:a32b78c1e52ebd8e247bb68300b90b233300d8816faa008ed0713bc539fb6af0", + "sha256:a3ffe881246d28a862f1985824f484cb7361f44d6b99c4c620436ef56462f38d", + "sha256:a49ff5cdb33654cb7d6a3c377aa2a83ddefaa1db31eb10bcf3c180aa84f9af8a", + "sha256:a8b75dd3d3638d9a19f23e84af4ffab3b8940422c0df2da2a77005ef5aa3d7ea", + "sha256:ab64ace1a68682d191d9bedd9d4c939406ad86b1d9f628180410644249ad46c2", + "sha256:abc7c2e4b47bfe6a9aea434d3fdebb9597ee636e914e92ba352f2068b9142f4c", + "sha256:ac348379cf4de5538a0a213be1532d289aa801ec5d267c5909446b9ea2f8e2c3", + "sha256:ac51cd64bae51c462ea58ad2492c9b8209667a4ef60c45c4a304518b67598d5d", + "sha256:acddcac38adc8342ba48aba98896faa7928854bebb62542362138655b5367ee3", + "sha256:ad4528cdce058b684f75fad1faf4a6a6c992fe2f08376370ca66e4ce5916a84a", + "sha256:aec65b53a07f580606593f877eefbb29a45939bfc0d3fe6e6d9f42b41b749f68", + "sha256:aef74e9beabbd6c4aafc091dabff86d046ccf013ce1e4396c0fbb01b4cad9de8", + "sha256:af1b5a92315048c3e36bbebfa7d4760a9c3e910bc4166f11b20d77d20d6bcfca", + "sha256:b22ff30006a2f28f8bff878fb93413cbe3a4d1fd517c28081d848c90e9cfd2c8", + "sha256:b2483da477932ad1983d1d33c18bc3771c6fb00cfbaaed70a875fd547ef8e840", + "sha256:b2f0adc22a4eb31e545221d93fc73a0f6a8cc2379d0f4309f71d1d17ba938b82", + "sha256:b4c9e5d05b126b267ac048a89a0e2d9b48b1b648add62d4872906304a8590610", + "sha256:b4da208a63434d21a3df64d29758e650fc4aa8cb05848554b76949c296539cca", + "sha256:b5f8771aaaed7f80e84a4e471d2f29ab6721e4595075e54d03ae1ed951b2000a", + "sha256:b65121091567847a8cb520d364ab22ba90e00d3cc55fa9eb34bb439f0684bcd1", + "sha256:b66ccc5c2cdd26e74fa5d4c29ffae424cc6148bf93ce574821783fb3b6d452c5", + "sha256:b69651732c64afb691e50cdc3387cae305e0eeff8804fe3e3ce203876494932a", + "sha256:b828cf64d62dc09ac183f03c1aeedd164ade96a2ce4934109452edf29de1dd13", + "sha256:b8a65621b98984a62e59403009591b8a5a7736273aefe1cab64cfb85b365cc07", + "sha256:bb0d664505f4b112f384cffeee82e91e3f6448d8e574989479db4439b68cba05", + "sha256:bb58ba73a3f96f9a3e46b1fab69929d7edbbddb3133ee74b5c3c54074a53c4f1", + "sha256:bc94a68ea5e18f8e85dc6b522bcb53093f692c8eb62b4837ac047da73956cbe4", + "sha256:bd82c4977196681a499bb6ca9e462afbc5c91c1c15b6a991dfbd72733fea4dd2", + "sha256:c0c88085affd35c33e124e36930c5ad96aff9294ce195eaa0fd9cec962b64a82", + "sha256:c148e8b596000dd3e4bfe206e70f3e666be18d72032e0012555f2373c52e35d6", + "sha256:c57541034d12b215ab0a2bfa371d1a8a198da18176d0426c27105b9161a6862d", + "sha256:c9648ed33dc8179e4ec04bbc73bd7f0038e1e81217a69467f61f02a78bf07e88", + "sha256:ca65cced0d67a9039e93bcd98a369920e499bf98296844ff56ead01c9085321f", + "sha256:cf22b43f35b7dbb9f71e8ee2041b5c00029cdfc28ede3a2f31cf8906f9a6c126", + "sha256:d35a4f1c63f07fbb8c8f9946dea98b21eddf6c57421585f71d91864be3ba2a24", + "sha256:d3b6e6840421c83ccb60398e333b44f910b0907bb409597685ab2eedd1e22eab", + "sha256:d73fed4e37158ff00cd271871170b79e40138db51e625fd352fa17c6acb34f67", + "sha256:d7bf9e43282d69561618e8a0ea33368d532ebef42f15c096f427090521dd74f3", + "sha256:d9d6544790ba50438a9c1a903c3c4afb1ec8a7832db5518549275b40ef0dd4b1", + "sha256:db4d697b18b6ef5528b1f36bfa25072cd2a421869f5963bc0e92c8a34b9e2800", + "sha256:dd9a137a4a9becda3094f3831cd026380f75f6855e051eefe4c73ade524f1cc3", + "sha256:de7738b8c0bb74c4cc16bbd7fb49fc2bcf6430dba11b3432cd52768ae40933e8", + "sha256:e3b1aa25f01238886a6baed9e13b9a9240ed344346c79ae280ae65e8603b21d5", + "sha256:e58952f04772f59f11c6e007471449809a30165188669bca8fdb19dde40a8f24", + "sha256:e5ccad4b7bac125722f48d6f862bed3b514d8526deea06316bb72f152cd30a7c", + "sha256:e7386aa18d98d6b8af44b92173654ec469237fda35f8e8523e43b581a86f476a", + "sha256:e81ae656b9935ac4528a71f96bb7a14d949778ed1897c573d3e7ebb9187f8841", + "sha256:e8f1e362c9352b50ed120f001046fdbb80810c9d56580f4c3fc13bbe30823387", + "sha256:e96ca64383efa107262ee3949f047af5ee4f1845ba09463466c04d35a83bd3ec", + "sha256:ea999ae6e80e66ad5eea287860951b033d0104ca34d6d87c7b5125ebe0e12721", + "sha256:ecc89dbd4155b2f8a47f4bbd89242a35ed15e8e0ec581cab5ac65fa38407329d", + "sha256:ef01d29fca550ab871fd99154f82c6472aacf8e7def272dfb07b460123850390", + "sha256:f04551dce5a7db8c9659f2e4245494c182d0663b83661803e08d46bfcae5eda1", + "sha256:f0700527dd5bfa8b7204b08330542f4f388899d3c14d885d8a368992e0eb562d", + "sha256:f2524ec55b3e65cbe235a8b3c36e2af3b635be02ed05e20c94e70c5c943c009e", + "sha256:f5844e7befc707367807586f550fa97e23dcfef0728f02b98c7bc498a961a5df", + "sha256:f9dad513626a33670f17cddc6078e30e311f444c957e8dbfc5b2b4603c8b4edb", + "sha256:fc0dcb22fa9aeabfe3fa4e0430099acff985ec5d77a851382f76cc6146e780e5", + "sha256:fd882aa29bf402b62bf1fd7c19fd5df4b6528cf468a908864b39368572b662a9" ], - "markers": "python_version >= '3.9'", - "version": "==6.7.1" + "markers": "python_version >= '3.10'", + "version": "==6.9.1" }, "numpy": { "hashes": [ - "sha256:07077278157d02f65c43b1b26a3886bce886f95d20aabd11f87932750dfb14ed", - "sha256:08f2e31ed5e6f04b118e49821397f12767934cfdd12a1ce86a058f91e004ee50", - "sha256:0aec54fd785890ecca25a6003fd9a5aed47ad607bbac5cd64f836ad8666f4959", - "sha256:0d35aea54ad1d420c812bfa0385c71cd7cc5bcf7c65fed95fc2cd02fe8c79827", - "sha256:0d4e437e295f18ec29bc79daf55e8a47a9113df44d66f702f02a293d93a2d6dd", - "sha256:0dfd3f9d3adbe2920b68b5cd3d51444e13a10792ec7154cd0a2f6e74d4ab3233", - "sha256:1378871da56ca8943c2ba674530924bb8ca40cd228358a3b5f302ad60cf875fc", - "sha256:15716cfef24d3a9762e3acdf87e27f58dc823d1348f765bbea6bef8c639bfa1b", - "sha256:19710a9ca9992d7174e9c52f643d4272dcd1558c5f7af7f6f8190f633bd651a7", - "sha256:23cbfd4c17357c81021f21540da84ee282b9c8fba38a03b7b9d09ba6b951421e", - "sha256:2483e4584a1cb3092da4470b38866634bafb223cbcd551ee047633fd2584599a", - "sha256:27a8d92cd10f1382a67d7cf4db7ce18341b66438bdd9f691d7b0e48d104c2a9d", - "sha256:28a650663f7314afc3e6ec620f44f333c386aad9f6fc472030865dc0ebb26ee3", - "sha256:2aa0613a5177c264ff5921051a5719d20095ea586ca88cc802c5c218d1c67d3e", - "sha256:2c194dd721e54ecad9ad387c1d35e63dce5c4450c6dc7dd5611283dda239aabb", - "sha256:2d19e6e2095506d1736b7d80595e0f252d76b89f5e715c35e06e937679ea7d7a", - "sha256:2d390634c5182175533585cc89f3608a4682ccb173cc9bb940b2881c8d6f8fa0", - "sha256:30caa73029a225b2d40d9fae193e008e24b2026b7ee1a867b7ee8d96ca1a448e", - "sha256:42c16925aa5a02362f986765f9ebabf20de75cdefdca827d14315c568dcab113", - "sha256:45dbed2ab436a9e826e302fcdcbe9133f9b0006e5af7168afb8963a6520da103", - "sha256:4636de7fd195197b7535f231b5de9e4b36d2c440b6e566d2e4e4746e6af0ca93", - "sha256:4a19d9dba1a76618dd86b164d608566f393f8ec6ac7c44f0cc879011c45e65af", - "sha256:4bbc7f303d125971f60ec0aaad5e12c62d0d2c925f0ab1273debd0e4ba37aba5", - "sha256:4d6d57903571f86180eb98f8f0c839fa9ebbfb031356d87f1361be91e433f5b7", - "sha256:4e874c976154687c1f71715b034739b45c7711bec81db01914770373d125e392", - "sha256:51fc224f7ca4d92656d5a5eb315f12eb5fe2c97a66249aa7b5f562528a3be38c", - "sha256:58c8b5929fcb8287cbd6f0a3fae19c6e03a5c48402ae792962ac465224a629a4", - "sha256:5a285b3b96f951841799528cd1f4f01cd70e7e0204b4abebac9463eecfcf2a40", - "sha256:5c70f1cc1c4efbe316a572e2d8b9b9cc44e89b95f79ca3331553fbb63716e2bf", - "sha256:62d6b0f03b694173f9fcb1fb317f7222fd0b0b103e784c6549f5e53a27718c44", - "sha256:6a246d5914aa1c820c9443ddcee9c02bec3e203b0c080349533fae17727dfd1b", - "sha256:6aa3236c78803afbcb255045fbef97a9e25a1f6c9888357d205ddc42f4d6eba5", - "sha256:6bbe4eb67390b0a0265a2c25458f6b90a409d5d069f1041e6aff1e27e3d9a79e", - "sha256:715d1c092715954784bc79e1174fc2a90093dc4dc84ea15eb14dad8abdcdeb74", - "sha256:72944b19f2324114e9dc86a159787333b77874143efcf89a5167ef83cfee8af0", - "sha256:81f4a14bee47aec54f883e0cad2d73986640c1590eb9bfaaba7ad17394481e6e", - "sha256:846300f379b5b12cc769334464656bc882e0735d27d9726568bc932fdc49d5ec", - "sha256:86b6f55f5a352b48d7fbfd2dbc3d5b780b2d79f4d3c121f33eb6efb22e9a2015", - "sha256:874f200b2a981c647340f841730fc3a2b54c9d940566a3c4149099591e2c4c3d", - "sha256:8a87ec22c87be071b6bdbd27920b129b94f2fc964358ce38f3822635a3e2e03d", - "sha256:8b3b60bb7cba2c8c81837661c488637eee696f59a877788a396d33150c35d842", - "sha256:8e3ed142f2728df44263aaf5fb1f5b0b99f4070c553a0d7f033be65338329150", - "sha256:93e15038125dc1e5345d9b5b68aa7f996ec33b98118d18c6ca0d0b7d6198b7e8", - "sha256:989824e9faf85f96ec9c7761cd8d29c531ad857bfa1daa930cba85baaecf1a9a", - "sha256:99d838547ace2c4aace6c4f76e879ddfe02bb58a80c1549928477862b7a6d6ed", - "sha256:9b2aec6af35c113b05695ebb5749a787acd63cafc83086a05771d1e1cd1e555f", - "sha256:9c585a1790d5436a5374bac930dad6ed244c046ed91b2b2a3634eb2971d21008", - "sha256:a7164afb23be6e37ad90b2f10426149fd75aee07ca55653d2aa41e66c4ef697e", - "sha256:ac6b31e35612a26483e20750126d30d0941f949426974cace8e6b5c58a3657b0", - "sha256:ad2e2ef14e0b04e544ea2fa0a36463f847f113d314aa02e5b402fdf910ef309e", - "sha256:b268594bccac7d7cf5844c7732e3f20c50921d94e36d7ec9b79e9857694b1b2f", - "sha256:b5f0362dc928a6ecd9db58868fca5e48485205e3855957bdedea308f8672ea4a", - "sha256:ba1f4fc670ed79f876f70082eff4f9583c15fb9a4b89d6188412de4d18ae2f40", - "sha256:ba203255017337d39f89bdd58417f03c4426f12beed0440cfd933cb15f8669c7", - "sha256:c901b15172510173f5cb310eae652908340f8dede90fff9e3bf6c0d8dfd92f83", - "sha256:c9b39d38a9bd2ae1becd7eac1303d031c5c110ad31f2b319c6e7d98b135c934d", - "sha256:d2a8490669bfe99a233298348acc2d824d496dee0e66e31b66a6022c2ad74a5c", - "sha256:dddbbd259598d7240b18c9d87c56a9d2fb3b02fe266f49a7c101532e78c1d871", - "sha256:df3775294accfdd75f32c74ae39fcba920c9a378a2fc18a12b6820aa8c1fb502", - "sha256:e44319a2953c738205bf3354537979eaa3998ed673395b964c1176083dd46252", - "sha256:e4a010c27ff6f210ff4c6ef34394cd61470d01014439b192ec22552ee867f2a8", - "sha256:e823b8b6edc81e747526f70f71a9c0a07ac4e7ad13020aa736bb7c9d67196115", - "sha256:e892aff75639bbef0d2a2cfd55535510df26ff92f63c92cd84ef8d4ba5a5557f", - "sha256:eea7ac5d2dce4189771cedb559c738a71512768210dc4e4753b107a2048b3d0e", - "sha256:ef4059d6e5152fa1a39f888e344c73fdc926e1b2dd58c771d67b0acfbf2aa67d", - "sha256:f169b9a863d34f5d11b8698ead99febeaa17a13ca044961aa8e2662a6c7766a0", - "sha256:f2cf083b324a467e1ab358c105f6cad5ea950f50524668a80c486ff1db24e119", - "sha256:f8474c4241bc18b750be2abea9d7a9ec84f46ef861dbacf86a4f6e043401f79e", - "sha256:f983334aea213c99992053ede6168500e5f086ce74fbc4acc3f2b00f5762e9db", - "sha256:f9e75681b59ddaa5e659898085ae0eaea229d054f2ac0c7e563a62205a700121", - "sha256:fbc356aae7adf9e6336d336b9c8111d390a05df88f1805573ebb0807bd06fd1d", - "sha256:fcfe2045fd2e8f3cb0ce9d4ba6dba6333b8fa05bb8a4939c908cd43322d14c7e" - ], - "markers": "python_version >= '3.11'", - "version": "==2.4.4" + "sha256:012e66aca395d795496446e52aeeb5866312a5d4d3f27da270e5a0b43f70dc5c", + "sha256:09d5a423c71ad5feb5625844ad58050e35df43871004b52ac9c0ad44a56775be", + "sha256:09ffa5d903faeaa5c4dd05009cf81c8bab9f2cb37c548b8d39b65b4cfa7c97f7", + "sha256:0a59a421a32580a009e8a1751345bf829631b990dc1794b80514ab722b435def", + "sha256:116f96cadd935c6122e9228d676fe7ede19e741f5c8bb1c3cddbe0c51ccebea2", + "sha256:1302b90c0e52281681b2975adfe8a860cb7b12216a27b4b0b4207c44bf7bccf0", + "sha256:15aa985ac73a8db02db7663381aa109510449d3819d37206caed27b33a65a8a6", + "sha256:1aad64d99730d013cfc6debafed22783b4fc5a7f4b8bc744d2d8cf7dcc880551", + "sha256:1c80eabb4035ecf4ca9cd49cde8a9fdd69a729e63e6474887d1523ade7aa277f", + "sha256:1f3ed25271581281f2fccb1adcedfcde4c07362eec69189b50baf6f90e3ae159", + "sha256:1fb6f8fb9ff0b3a69f52c66ce397b0246583e9f28616231b0e32ca49259a5fa6", + "sha256:214045a5bf00113a146ab9ee9730c44501af6723cdf1f6830932f7b5ef2e7af0", + "sha256:26e15e4aecd8617dfbaecb37d223e365d7b39411fba20454be2670a96aa74cb5", + "sha256:2c25dfa72943e4336ddb6b0ee4277b47a0c85bede0807530ec68103bf58e2c10", + "sha256:2d8240cb4c16fd831074aa2b2cf9fc54664d826341d61c372245b96a74a49a9a", + "sha256:350ba9783ce969cf9f7ce6e6a9a58e1a6e2a19ca025b7ee448c4db727706212a", + "sha256:4c8a6d2ebce6305fd82fbefca827775437147052a976ee7c94b36a0c1b52ac6c", + "sha256:4f8929ee6c96bfbd7b4ed2032e0c03af86fe1826740ab61ddabf9072d06e57ff", + "sha256:536f963710a4e63934d80ac0dc4f478804a83e9a84b6828018f25d09953ada33", + "sha256:54a115e5a73b8fc44f0cebef486365a1894b5c9760685d4558b72b7c3eb846e0", + "sha256:595d020938c84e320bcf40ad71089e108eac0d377cd018e14a8c094f39e98d85", + "sha256:66a78fe4556c60aceda5916f9eacd638b18e9e681016ec302dcb4682d6d4d034", + "sha256:6b05c171afb3aa07adbd20abc00aea86fe375beb0fdb9ef780ec5b7f63bab1c0", + "sha256:6cef4bb1706dfec49243c05d921eefb4e190d41e2528b30d8035ea1f36b4c24a", + "sha256:6f24021b9f22bc6301c37b196974a92c1c18dccedb6fef3dd252e95f2d6adbe4", + "sha256:71b39d9f935b6ec0f8753e3e2afb51e3efba6f2e05b68b32a40754d24bcd4a3c", + "sha256:71cad2b2a7451ab79d8f5e71b453485b6775963d5cf794179144a7463fe6e8ec", + "sha256:76c2c1e6bfa5c84adc6434dfbf013aa92096a7985221762c8f11fedfd20fff58", + "sha256:8617bbfae4486cf99c9f899966699428d19da931d06ca94ad3da986c76e15997", + "sha256:86bff898a431c0fb71f7610b75726e75a54d47b37edc9d537f48de63bb3c0b90", + "sha256:8e4dd766076855b5ff7ea52fa5f07ce26286726e0f8bff446b7739d02e6ea204", + "sha256:92f30e89b8ee0ecf363033576c422b2f58fed6a80bed0aa48dff6d14c654663e", + "sha256:93e1f5447e2b1e479d7bd74701e84746b86450cff1fc368b132d195e2b8f8211", + "sha256:9a37475425b431b4d060f23b4f52cd2f3aef6bc7c654bd760adf0040eec9d435", + "sha256:9deb49575e5b0b94ed72c8a64ec4d033381adc27e9060ae842971f697ba96104", + "sha256:a5fa86b80fd24bcd1aff83ad23be44ea323de3f787be8f8b15d4a65621e25321", + "sha256:a6391fafaba97500887132cd582abc6e19452b1ac775a47caa7b24490e152058", + "sha256:a72f874bc9e10e4b8f80426fb49716d5141f64442a0c8418065093ec8017fbb0", + "sha256:ac7bb1c52d445bd4f8f7f97fefe6abc3a084dc4d63df50d79b17fa2b78e89297", + "sha256:adc1ada2662f8a5f960b8a10d9986897e7499ef07e06d4cfe7197f8cce923c07", + "sha256:b00eefbcf0f292945c4b4dec2ae845389ef5bcdcd596e6e4328051db5b5ba694", + "sha256:b0521d0f4aebb6e06189451025fa17a913287b13c03d5fe05c017333b654ea5b", + "sha256:b5d93cf48f687479941d12b69c873ad2cc76bbd487f0091c2200636497f34034", + "sha256:b7e18c623bb5c95acb3b3328861272816ba199fb531921c5d6d0b675f1fde9e3", + "sha256:bd4cb9ad3c7889b9b3fe0a9a9fb5d2ed26f9879bff2608d9f01aed147a20d231", + "sha256:be5a8381859b6da607c84f4f7d6847725f1cf1853ef8a2c9e115b7d58bef47dc", + "sha256:befa1ae5bd6030b3f512b43ff3fa5290bbed6b84411a44244b14adf835f5b89d", + "sha256:bf63afbe037eb5d2fe87fbcc7778e61da53ebaf21d938a4515aa73b62532a5d4", + "sha256:c00abe94c1a69d75d827dcf1c025b25c8a45d230b3bcd77a9020883a1b047653", + "sha256:c2381f82999704f818e2c987a865050e285ec3621262c66d40f5a96c8f899f8e", + "sha256:c76d5dde9f445058f83d0c02af00557a4db91de9a9a57c0df87d1535001d654b", + "sha256:cb189f09db39283b26bfd061ec16189e14f71c6755207f72a0f7540867afe5b9", + "sha256:ccb32e0525d29e8b0572eb84c9a57af0e7a4e615726927506f55063c62414034", + "sha256:ccbc4665079665c3cf3bab4db9f6b095370cd6437d66be549b6c2a1fd19e1958", + "sha256:d1c89973648c85069c5046ad460f7b8a00218b29a2e42359ac8cc63e9ab94832", + "sha256:df2d5874ff183595a4ba404edd04f6bd9b5505c1d7708573f6a6c17489a67563", + "sha256:e01c918ac3d48e18a927cf7b14a26a3e29ff2bdf2eacb976da0aecd6a43ed034", + "sha256:e6ab667ba76450084eb64013762c438ea76d9d29cc676dcd6c2e9892ba37f841", + "sha256:e931e4f499e0dc7ef29d269a8e5b35dd722e5d14be07df6240166ea7c6532fae", + "sha256:f54660b0eb6b0b9f36e7fe1cdfdff472028dd0d14acd9b9b65098efbad059469", + "sha256:f59a878c33d6b88122d80d239bb3b845d58708750b0cb06a09aebb9b18ec696c", + "sha256:f7fabeb6cea87d65f3b926de33d03fb016cfdc29314c90974383b5582ae72891", + "sha256:f9579f383d1bf9df80081e72760e84960a7fd4f88cf0c9e535a8597c9bb646f5", + "sha256:f9a2353b37a1a9e78fd82b27ad7e2a32a2d036604d18f02b05e3136c62ca3b09", + "sha256:fc36dc566135b5eceec4cf89758fcb719266a019ef07dae1754ae7c9f617ef3e", + "sha256:ffdc76bfcae6b255dff75202c5e7feaf95b40246bc0a17944facc1fecf9f79ab" + ], + "markers": "python_version >= '3.12'", + "version": "==2.5.3" }, "packaging": { "hashes": [ - "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4", - "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529" + "sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79", + "sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c" ], - "markers": "python_version >= '3.8'", - "version": "==26.0" + "markers": "python_version >= '3.9'", + "version": "==26.3" }, "pathvalidate": { "hashes": [ @@ -1255,139 +1347,155 @@ }, "prompt-toolkit": { "hashes": [ - "sha256:28cde192929c8e7321de85de1ddbe736f1375148b02f2e17edd840042b1be855", - "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955" + "sha256:01c0891d7f9237d5e339f7d3e42cdae80b7534abb1c7c0e3352efba6231492f2", + "sha256:9ec8a0ad96d5c56148b3f914aa79c1564c3fde5d2e6b876e7bc327e353cf8fa6" ], - "markers": "python_version >= '3.8'", - "version": "==3.0.52" + "markers": "python_version >= '3.10'", + "version": "==3.0.53" }, "propcache": { "hashes": [ - "sha256:0002004213ee1f36cfb3f9a42b5066100c44276b9b72b4e1504cddd3d692e86e", - "sha256:0013cb6f8dde4b2a2f66903b8ba740bdfe378c943c4377a200551ceb27f379e4", - "sha256:005f08e6a0529984491e37d8dbc3dd86f84bd78a8ceb5fa9a021f4c48d4984be", - "sha256:031dce78b9dc099f4c29785d9cf5577a3faf9ebf74ecbd3c856a7b92768c3df3", - "sha256:05674a162469f31358c30bcaa8883cb7829fa3110bf9c0991fe27d7896c42d85", - "sha256:060b16ae65bc098da7f6d25bf359f1f31f688384858204fe5d652979e0015e5b", - "sha256:120c964da3fdc75e3731aa392527136d4ad35868cc556fd09bb6d09172d9a367", - "sha256:15932ab57837c3368b024473a525e25d316d8353016e7cc0e5ba9eb343fbb1cf", - "sha256:17612831fda0138059cc5546f4d12a2aacfb9e47068c06af35c400ba58ba7393", - "sha256:182b51b421f0501952d938dc0b0eb45246a5b5153c50d42b495ad5fb7517c888", - "sha256:1cdb7988c4e5ac7f6d175a28a9aa0c94cb6f2ebe52756a3c0cda98d2809a9e37", - "sha256:1eb2994229cc8ce7fe9b3db88f5465f5fd8651672840b2e426b88cdb1a30aac8", - "sha256:1f0978529a418ebd1f49dad413a2b68af33f85d5c5ca5c6ca2a3bed375a7ac60", - "sha256:204483131fb222bdaaeeea9f9e6c6ed0cac32731f75dfc1d4a567fc1926477c1", - "sha256:296f4c8ed03ca7476813fe666c9ea97869a8d7aec972618671b33a38a5182ef4", - "sha256:2ad890caa1d928c7c2965b48f3a3815c853180831d0e5503d35cf00c472f4717", - "sha256:2b16ec437a8c8a965ecf95739448dd938b5c7f56e67ea009f4300d8df05f32b7", - "sha256:2bb07ffd7eaad486576430c89f9b215f9e4be68c4866a96e97db9e97fead85dc", - "sha256:333ddb9031d2704a301ee3e506dc46b1fe5f294ec198ed6435ad5b6a085facfe", - "sha256:357f5bb5c377a82e105e44bd3d52ba22b616f7b9773714bff93573988ef0a5fb", - "sha256:35c3277624a080cc6ec6f847cbbbb5b49affa3598c4535a0a4682a697aaa5c75", - "sha256:364426a62660f3f699949ac8c621aad6977be7126c5807ce48c0aeb8e7333ea6", - "sha256:381914df18634f5494334d201e98245c0596067504b9372d8cf93f4bb23e025e", - "sha256:3d233076ccf9e450c8b3bc6720af226b898ef5d051a2d145f7d765e6e9f9bcff", - "sha256:3d902a36df4e5989763425a8ab9e98cd8ad5c52c823b34ee7ef307fd50582566", - "sha256:3f7124c9d820ba5548d431afb4632301acf965db49e666aa21c305cbe8c6de12", - "sha256:405aac25c6394ef275dee4c709be43745d36674b223ba4eb7144bf4d691b7367", - "sha256:41a89040cb10bd345b3c1a873b2bf36413d48da1def52f268a055f7398514874", - "sha256:43eedf29202c08550aac1d14e0ee619b0430aaef78f85864c1a892294fbc28cf", - "sha256:473c61b39e1460d386479b9b2f337da492042447c9b685f28be4f74d3529e566", - "sha256:49a2dc67c154db2c1463013594c458881a069fcf98940e61a0569016a583020a", - "sha256:4b536b39c5199b96fc6245eb5fb796c497381d3942f169e44e8e392b29c9ebcc", - "sha256:4c3c70630930447f9ef1caac7728c8ad1c56bc5015338b20fed0d08ea2480b3a", - "sha256:4d3df5fa7e36b3225954fba85589da77a0fe6a53e3976de39caf04a0db4c36f1", - "sha256:4d7af63f9f93fe593afbf104c21b3b15868efb2c21d07d8732c0c4287e66b6a6", - "sha256:501d20b891688eb8e7aa903021f0b72d5a55db40ffaab27edefd1027caaafa61", - "sha256:521a463429ef54143092c11a77e04056dd00636f72e8c45b70aaa3140d639726", - "sha256:5558992a00dfd54ccbc64a32726a3357ec93825a418a401f5cc67df0ac5d9e49", - "sha256:55c72fd6ea2da4c318e74ffdf93c4fe4e926051133657459131a95c846d16d44", - "sha256:564d9f0d4d9509e1a870c920a89b2fec951b44bf5ba7d537a9e7c1ccec2c18af", - "sha256:580e97762b950f993ae618e167e7be9256b8353c2dcd8b99ec100eb50f5286aa", - "sha256:5a103c3eb905fcea0ab98be99c3a9a5ab2de60228aa5aceedc614c0281cf6153", - "sha256:5c3310452e0d31390da9035c348633b43d7e7feb2e37be252be6da45abd1abcc", - "sha256:5d4e2366a9c7b837555cf02fb9be2e3167d333aff716332ef1b7c3a142ec40c5", - "sha256:5fd37c406dd6dc85aa743e214cef35dc54bbdd1419baac4f6ae5e5b1a2976938", - "sha256:60a8fda9644b7dfd5dece8c61d8a85e271cb958075bfc4e01083c148b61a7caf", - "sha256:66c1f011f45a3b33d7bcb22daed4b29c0c9e2224758b6be00686731e1b46f925", - "sha256:671538c2262dadb5ba6395e26c1731e1d52534bfe9ae56d0b5573ce539266aa8", - "sha256:678ae89ebc632c5c204c794f8dab2837c5f159aeb59e6ed0539500400577298c", - "sha256:67fad6162281e80e882fb3ec355398cf72864a54069d060321f6cd0ade95fe85", - "sha256:6918ecbd897443087a3b7cd978d56546a812517dcaaca51b49526720571fa93e", - "sha256:6f6ff873ed40292cd4969ef5310179afd5db59fdf055897e282485043fc80ad0", - "sha256:6f8b465489f927b0df505cbe26ffbeed4d6d8a2bbc61ce90eb074ff129ef0ab1", - "sha256:71b749281b816793678ae7f3d0d84bd36e694953822eaad408d682efc5ca18e0", - "sha256:74c1fb26515153e482e00177a1ad654721bf9207da8a494a0c05e797ad27b992", - "sha256:7c2d1fa3201efaf55d730400d945b5b3ab6e672e100ba0f9a409d950ab25d7db", - "sha256:824e908bce90fb2743bd6b59db36eb4f45cd350a39637c9f73b1c1ea66f5b75f", - "sha256:8326e144341460402713f91df60ade3c999d601e7eb5ff8f6f7862d54de0610d", - "sha256:8873eb4460fd55333ea49b7d189749ecf6e55bf85080f11b1c4530ed3034cba1", - "sha256:89eb3fa9524f7bec9de6e83cf3faed9d79bffa560672c118a96a171a6f55831e", - "sha256:8c9b3cbe4584636d72ff556d9036e0c9317fa27b3ac1f0f558e7e84d1c9c5900", - "sha256:8e57061305815dfc910a3634dcf584f08168a8836e6999983569f51a8544cd89", - "sha256:929d7cbe1f01bb7baffb33dc14eb5691c95831450a26354cd210a8155170c93a", - "sha256:92d1935ee1f8d7442da9c0c4fa7ac20d07e94064184811b685f5c4fada64553b", - "sha256:948dab269721ae9a87fd16c514a0a2c2a1bdb23a9a61b969b0f9d9ee2968546f", - "sha256:981333cb2f4c1896a12f4ab92a9cc8f09ea664e9b7dbdc4eff74627af3a11c0f", - "sha256:990f6b3e2a27d683cb7602ed6c86f15ee6b43b1194736f9baaeb93d0016633b1", - "sha256:99d43339c83aaf4d32bda60928231848eee470c6bda8d02599cc4cebe872d183", - "sha256:9a0bd56e5b100aef69bd8562b74b46254e7c8812918d3baa700c8a8009b0af66", - "sha256:9a52009f2adffe195d0b605c25ec929d26b36ef986ba85244891dee3b294df21", - "sha256:9d2b6caef873b4f09e26ea7e33d65f42b944837563a47a94719cc3544319a0db", - "sha256:9f302f4783709a78240ebc311b793f123328716a60911d667e0c036bc5dcbded", - "sha256:a0ee98db9c5f80785b266eb805016e36058ac72c51a064040f2bc43b61101cdb", - "sha256:a129e76735bc792794d5177069691c3217898b9f5cee2b2661471e52ffe13f19", - "sha256:a78372c932c90ee474559c5ddfffd718238e8673c340dc21fe45c5b8b54559a0", - "sha256:a9695397f85973bb40427dedddf70d8dc4a44b22f1650dd4af9eedf443d45165", - "sha256:ab08df6c9a035bee56e31af99be621526bd237bea9f32def431c656b29e41778", - "sha256:ab2943be7c652f09638800905ee1bab2c544e537edb57d527997a24c13dc1455", - "sha256:ab4c29b49d560fe48b696cdcb127dd36e0bc2472548f3bf56cc5cb3da2b2984f", - "sha256:af223b406d6d000830c6f65f1e6431783fc3f713ba3e6cc8c024d5ee96170a4b", - "sha256:af2a6052aeb6cf17d3e46ee169099044fd8224cbaf75c76a2ef596e8163e2237", - "sha256:bcc9aaa5d80322bc2fb24bb7accb4a30f81e90ab8d6ba187aec0744bc302ad81", - "sha256:c07fda85708bc48578467e85099645167a955ba093be0a2dcba962195676e859", - "sha256:c0d4b719b7da33599dfe3b22d3db1ef789210a0597bc650b7cee9c77c2be8c5c", - "sha256:c0ef0aaafc66fbd87842a3fe3902fd889825646bc21149eafe47be6072725835", - "sha256:c2b5e7db5328427c57c8e8831abda175421b709672f6cfc3d630c3b7e2146393", - "sha256:c30b53e7e6bda1d547cabb47c825f3843a0a1a42b0496087bb58d8fedf9f41b5", - "sha256:c80ee5802e3fb9ea37938e7eecc307fb984837091d5fd262bb37238b1ae97641", - "sha256:c9b822a577f560fbd9554812526831712c1436d2c046cedee4c3796d3543b144", - "sha256:cae65ad55793da34db5f54e4029b89d3b9b9490d8abe1b4c7ab5d4b8ec7ebf74", - "sha256:cb2d222e72399fcf5890d1d5cc1060857b9b236adff2792ff48ca2dfd46c81db", - "sha256:cbc3b6dfc728105b2a57c06791eb07a94229202ea75c59db644d7d496b698cac", - "sha256:cd547953428f7abb73c5ad82cbb32109566204260d98e41e5dfdc682eb7f8403", - "sha256:cfc27c945f422e8b5071b6e93169679e4eb5bf73bbcbf1ba3ae3a83d2f78ebd9", - "sha256:d472aeb4fbf9865e0c6d622d7f4d54a4e101a89715d8904282bb5f9a2f476c3f", - "sha256:d62cdfcfd89ccb8de04e0eda998535c406bf5e060ffd56be6c586cbcc05b3311", - "sha256:d82ad62b19645419fe79dd63b3f9253e15b30e955c0170e5cebc350c1844e581", - "sha256:d8f353eb14ee3441ee844ade4277d560cdd68288838673273b978e3d6d2c8f36", - "sha256:daede9cd44e0f8bdd9e6cc9a607fc81feb80fae7a5fc6cecaff0e0bb32e42d00", - "sha256:db65d2af507bbfbdcedb254a11149f894169d90488dd3e7190f7cdcb2d6cd57a", - "sha256:dee69d7015dc235f526fe80a9c90d65eb0039103fe565776250881731f06349f", - "sha256:e153e9cd40cc8945138822807139367f256f89c6810c2634a4f6902b52d3b4e2", - "sha256:e35b88984e7fa64aacecea39236cee32dd9bd8c55f57ba8a75cf2399553f9bd7", - "sha256:e53f3a38d3510c11953f3e6a33f205c6d1b001129f972805ca9b42fc308bc239", - "sha256:e9b0d8d0845bbc4cfcdcbcdbf5086886bc8157aa963c31c777ceff7846c77757", - "sha256:ec17c65562a827bba85e3872ead335f95405ea1674860d96483a02f5c698fa72", - "sha256:ecef2343af4cc68e05131e45024ba34f6095821988a9d0a02aa7c73fcc448aa9", - "sha256:ed5a841e8bb29a55fb8159ed526b26adc5bdd7e8bd7bf793ce647cb08656cdf4", - "sha256:ee17f18d2498f2673e432faaa71698032b0127ebf23ae5974eeaf806c279df24", - "sha256:f048da1b4f243fc44f205dfd320933a951b8d89e0afd4c7cacc762a8b9165207", - "sha256:f10207adf04d08bec185bae14d9606a1444715bc99180f9331c9c02093e1959e", - "sha256:f1d2f90aeec838a52f1c1a32fe9a619fefd5e411721a9117fbf82aea638fe8a1", - "sha256:f48107a8c637e80362555f37ecf49abe20370e557cc4ab374f04ec4423c97c3d", - "sha256:f7ee0e597f495cf415bcbd3da3caa3bd7e816b74d0d52b8145954c5e6fd3ff37", - "sha256:f93243fdc5657247533273ac4f86ae106cc6445a0efacb9a1bfe982fcfefd90c", - "sha256:f95393b4d66bfae908c3ca8d169d5f79cd65636ae15b5e7a4f6e67af675adb0e", - "sha256:fc38cba02d1acba4e2869eef1a57a43dfbd3d49a59bf90dda7444ec2be6a5570", - "sha256:fd0858c20f078a32cf55f7e81473d96dcf3b93fd2ccdb3d40fdf54b8573df3af", - "sha256:fd138803047fb4c062b1c1dd95462f5209456bfab55c734458f15d11da288f8f", - "sha256:fd2dbc472da1f772a4dae4fa24be938a6c544671a912e30529984dd80400cd88", - "sha256:fd6f30fdcf9ae2a70abd34da54f18da086160e4d7d9251f81f3da0ff84fc5a48", - "sha256:fe49d0a85038f36ba9e3ffafa1103e61170b28e95b16622e11be0a0ea07c6781" + "sha256:004e685b315646c410771836e72a44f143bbe624f29653a42687815069a303d5", + "sha256:02c0a34f16889cf800f10f0247a564d8ce6eeab6ffcd7c87198f769067eb8432", + "sha256:03969626faf0783a592dfa17e28eac06018bd0b44dafae6943d53b92421a7f72", + "sha256:03b229037d25b801e7af53fd52b9fc49d9439b036fca1e087e02780631adfa97", + "sha256:0951315a6b3142ee2167404d707743f0157c110091342b1aa0accac5cf0e4acf", + "sha256:0a095db8e15a6020db149ecbed6461939fe74f6acaa3ae8b702a1fe8c38cd983", + "sha256:0c889f6fa84957bc7e8b4eab71fd16a0455068d5045e3aa40c733071d2b2fd77", + "sha256:0d21d0d2c82bbfeb1677a9711f38df968f9837576102bb4add1bd449d28d88f1", + "sha256:10ef33a68a61ce317e095fd2e202a592ea92392b90944a78c993f0d9a73ab06c", + "sha256:12682126712ddc19b70ff819debbd279e58adf1f0c8f8f8138c18ade2044b284", + "sha256:135036c5cfc93864affb0f9af9a27e5d7a71cb7bd745e7b6dbfc2d56cc30e827", + "sha256:13e52b6e0bde97dee98ab66552dbff2931649c96f1ac432eac299fe689ec373b", + "sha256:141fdbd73748db0cf7636035030aaac383d2efde8f34e7bc24594cc776d225b8", + "sha256:146f48a9e4812611a7581003b1a39de56c34967046310c4171a68ef908c9a745", + "sha256:174507f82d3594622acb1dd2dafecf2d899d6d506335494e7107767bf05f3aae", + "sha256:1783582065a1f07f9d9ee1e992e13f15d7dc8fb1eb3a7476d43eb3f2e69d26bb", + "sha256:17a7400cec0256f0a71ae71f9da398f9894c956ff6668a1c9d317b3367316320", + "sha256:1b2f3bec4261a94019575481c726c29850f72e27907773c75b1de421e20e9f9d", + "sha256:1d759d05634f1b038fb625a66662a8c85e5a8fec912da381b5149ddac107482b", + "sha256:1df8d8561b21465c5dd56110a01caf897e026d065b4b84e98a488209094272ec", + "sha256:213bb68d9ced5cf2bf717b1071bf2b09b4b04c426256f9fe6d054c60318424c4", + "sha256:23278f808cd81d5ada7184a76606b925fb3389c60e1077b2cd7da7b1fcf0553c", + "sha256:251c63dd46a0659bb875cb254dc4c1e79ee91a847c737cd62373295afc2235dc", + "sha256:279655a16973f1ee2bd2fe79973137681642fd9ae0d89215bba263726eb0dc3a", + "sha256:2814ecd8e818f487bee4b0f921bc4d1c176cc5fc71ac0f072d0fa67eda4ac14b", + "sha256:286867fb156488c251a3721766e380ac4495e4fd6b51aaa1403d89ce7f4359d9", + "sha256:2dba2f02d2d5c09ef8a0e6c1a42aeaa451f4be9898cb00b04fe98717da2eb23b", + "sha256:30cc1cebaf9aef49db06357a50398323ae04d70460c0491837d026ab7d6452ea", + "sha256:31eb43ba2edc704ab2ec27815315dd8a19def0fb16215be4cfe8d32fe78ffd51", + "sha256:350b272b2279f4135a64fc0c304a5d08e28a137c9573442c606152446638a831", + "sha256:36c0d9db44b523ef93d03341b1c42d69ff01d673c053d1b1c6c3a363bcaa39ba", + "sha256:3af0c8642b2da4815d86e631232ac8286e17644fad907c19508aa8e7cb4ba8ad", + "sha256:3cd3a7edb6b95b9b33998135ebfa18d709da82290fb8f27c858970b5a12c8b56", + "sha256:3d605bb239b796e82a81c6709548b2bd460ab73b4590cb0c83de8a2dd9694d0f", + "sha256:3e413d7a4a9b4866b7a761d6060d434b64d23cd35122eda3b026a0bbe8196b25", + "sha256:3eb2e820e8e2101407da93f17c57cbb7d225461955fc60105daaba14cd421ee2", + "sha256:3fa15757fea1dfcd5b7745cad9f4638929605531bd4018ab2adff7955f1a403d", + "sha256:3fc24f209c1b7f7f688b66b98293954f5504279760999b58920ee12dd8471c1d", + "sha256:4054acf80d40456a0537f2913b349718649d8d6458a14ab7f48d0ce28c30869d", + "sha256:40e94adb1e7d39ff28a8bd8d8b8fbd1df6b9f40976dbe379134f1ce058e532dd", + "sha256:420162a77f94eb1cf5ef7893f500016dabd548e73de956785a1dd899cc73006a", + "sha256:425f8cc86ab5018b4b8d4a23bc8e74d964bd3d757c3702e301aa79be76c53f6c", + "sha256:44149f46500a0a41b95b4d99c2e586a77319539730607b9892974a092788b111", + "sha256:445ee3bfb46e85838387fb3c536a73cc0b994dc192b004e40e170adc54aa2a7e", + "sha256:45488d1a5f9ab5bd90aaa1ca20f50fe1922b8ffad71a2009d2adf41355897aac", + "sha256:45bebbe252550fec975ba3b62bc6f931643cfd3b5464ef47619cf3fef154e01c", + "sha256:45bf2e730ab8905d0527fe05a86500f406e64305c34cc81ebe64b4617cab9760", + "sha256:48cb48c5346a97de792254af77715aa2529c2a1ebc5f586aa0aae44a02f1fe57", + "sha256:4a1f4f5ffa55dce6307631f3cb2948e117e665966ea512e0d502b16c24f567e7", + "sha256:4cfe0a92ae30151869e67a4b5f5e105e4e03ad30b3f38e5211b5bf77d0881993", + "sha256:4d86476a935c88963d9b8e1a9a0d38188790e9622169bfbafa173046846709d3", + "sha256:4e985382be6d15da8d0c2710a6fa7b9070fc9ecdeefb7f580e88373984ec8be3", + "sha256:4f2d880ff60f45898f4acfa152aac8d04e3ee627d90ff4003491bf92239d5757", + "sha256:4fbc1a15dc8cd1689508758d626b372b1f09d28d9577667feaf9e6bfcd8efcbc", + "sha256:50e337653721d20ead710da33bf44487fbe8a0db8782714b60306481e9f95b51", + "sha256:53eaa697c4d0422ff4cb714d00231b43352064d97b944033b30c1d57cc506ec0", + "sha256:56fc3f7599528db40b1efa0889a620116e2704144495273d66066e8164e45838", + "sha256:58134228927cee6c047d626c08e60a81be604a20578a12ce752cc5c9a84d4826", + "sha256:594eb4c6ec35e7179b058481f4e9f02521b56de16fa577c4b85c76fb1bf8a9f8", + "sha256:5cacf3c9efd09df409dc33654dd077e1c245ba8fb747b0f0236ef41b7c49b589", + "sha256:60a64cbccaa11b7760ce705a14ada17ba459e7ca9f23ba587eb013821032d7ef", + "sha256:62530ca89187827e4a4fe733f971abe81a7542eeea48ff61995f19b64d7199c8", + "sha256:62c60aec739ed00124573cce1178138fd690c7676352d67a37328c1cf51d7468", + "sha256:69fc35c0779522da366c563e5faf203ffc1f8ff0021d5b1337fa4efa5be73177", + "sha256:6af4693716bfb03f1752ef1b30faa593db2c01d5272e9b8564a1549452a979ab", + "sha256:6c7599df2b57ebeea8de011b5f2f7b85de95e76037d43d34b95e328430275487", + "sha256:6e9368e87a3efc285e559131092c5db643eb8e56de4ee42064d5baec22ef2bb5", + "sha256:6f0093ac3e9daada202c2082439d414a625c57184727a46e112a3fb2a81cb788", + "sha256:7177c43eddf10a0893c4fec52ebb408fdcd7f7d63962caace9180d8f81b14ece", + "sha256:720cf832eb2d0b0dfee129cb3335a26f6ce3cc45ee1187e8f0731758caa16792", + "sha256:770e8209d018175fc0063936fa9583b6d27e88c5ad31543f3383d66080efdd62", + "sha256:7a8d5ff04eb1f85698a78d20c62a14676e7b960dcafde09a388d60ad377d355d", + "sha256:7b9100a93b372418d8688f3f2a3e5b45c64d70ca4d6176e121aca1e3bfc1e32f", + "sha256:7cc528e760a8af06f2b13e9b9f362cd90c7c718ea61228a96dbd31ba16ed7f47", + "sha256:7ffafcbfc7b549ab940047e505c831eabac5e67de53e1bc174adbc5285c55944", + "sha256:87a3caecf8095e48dc72f84bfa42e23a848cf410cc9cc13031fba4869b706a21", + "sha256:886b59c4d28ca97dd23b025fdfc50a0356be934efbbbca89ad26230067f86fe5", + "sha256:8876b39961e33d912afe3c1bee18ee564fdad0206f873cc15d522756b7f50737", + "sha256:897d1ddf6716e8f47200f7aad9a0efa6cc7586df66c6defa572f9eab379c078e", + "sha256:8a1fc236528c457cd739c88abe823da851b7ab645d72792f88658114cc340c12", + "sha256:8a235f73d6e020855dc29dff012d920c02ee0feab8d73a24185a7569f4be1161", + "sha256:8f911c395cef73c510bac566da9507bb6a43e7763d0c79138dc60ee53f11207e", + "sha256:96f7c5c15656040ddcbc51e56dc59b58aa25999d743c126abd425b9766ab43e9", + "sha256:978f28401afbc76cdc3df9e1717b4229a06b626a1dcc75db4e1f2beb3884c3e9", + "sha256:98914de2c4d7f0f9f4a8c6ea4bf05841f4175796941e3ef7d47eb718f22311fb", + "sha256:9a2a8a50a93dee0268a860a07fa3b4bd968f8ce4dbd794957da772f395368526", + "sha256:9cbfff4423eef4cc6cafc021469641a2b835f610b2647a6c5281903e21b8670d", + "sha256:9e9ab13760aa8b6d0881ae7cb04fd891d8d490cd2554ea8e79bb278399169bcc", + "sha256:9f3551b8a35c1df3e7ea4d2d86edee15f0dde1bddd434a71744048683544d0ef", + "sha256:9f86f7259efe2c951f43e57d471c9b41daa5bfc7db9f67189059cf1ae6d77fd9", + "sha256:9fb0a5be8d9aa213150e8d8148a42aca4984b285bcad1e69587dc4298edd929b", + "sha256:a219f0ac59817a9114dd2aa57c13180f993e819ba658c7ddab4b66ed1ee0d370", + "sha256:a419ee85e654927baabda3929c03c0cc1112bf472ff0dfd6142f4e3a81ca4162", + "sha256:a4d7a54719b67338a305dca2ce6aafe366817df94ddfd4b5514374356f5ca546", + "sha256:a5793c7698a53f56f4a1889a4737c7eeb1b7ad0842fa6b1abca22913ff79c8c1", + "sha256:a5e8ef588c109725dc713ba69aadcac00a1ef90c2ce9c0a8c7075128f569f47f", + "sha256:a74bfa37147cc08fb29df10bd9c16f40fa7f860cd3a6d2fff853323a94f6e17f", + "sha256:ada748108a43d29b7c328ba7db3755327cd94f028bcc1a7ee3f0addcfacd9c38", + "sha256:ae58f361bd5dae942717c65d3413b478c70aea9c462599e7b9adad3731db3894", + "sha256:b28f41fa3b8c6900457f858ec5b03998f3a6d535fbc1bb2edec5961ea05ec429", + "sha256:b3083bfe87f95c756e610bd8025f26cbd1cd4aaa03a422f2d65efb7a97cd53d8", + "sha256:b61805357d966680acf68b3b6d49772631ed9df44ebece10ff1460e117a7da8a", + "sha256:b77c313314524ca9c38fbd70f73515d04597ac58c40c939bc0e71eeb4abff680", + "sha256:bee7d3aed13d56f54e681df38c3a23031bc9e3863f687d9d598825c9146acd7d", + "sha256:c02c0e570c5c7e077b0181a9f3cdb7d4c3617d1cda6b5c95bd5d34022923d82c", + "sha256:c174bfd1c48a1b51a3078e95586dde718374bac79719ab3541ec9e74aec40574", + "sha256:c2ba30a89035b57b73e00475de948521602f543d79ce01db10b04b36c4c76fc8", + "sha256:c3e98c55bde2bcf7db3c70d1aed7ae9aa8aebbf19a250c66645cde44cdb8b867", + "sha256:c3ef2818d63bc86071e9d2989ae75a1bc32b8f7059cfd9f5abbbee70c32e2ed6", + "sha256:c83acbce9f2b5e3f5f5eda9e53d2001fed22fcdfef81274a9e02d8fd53b70a30", + "sha256:c9281e922c072158c91974d4589f1dbe0fee6d467f284c28e463f9f5a4d933f4", + "sha256:cc07876cfb079b6f6f36d21ce75784ad6c2c6b563eeac0ed26c2fa2669b85df9", + "sha256:ccf4f7a79e26bb7efb06ecd50c177833b71df05cbc748701372325e6bcc17f6f", + "sha256:cdee8205a44d0be91bbac4c41b95d86641b72dfc7aef1279400e4fda3f26a937", + "sha256:ceb3e879afac028f93d272c957814695dc5569e4904262dbee92f6c41bd5e4a3", + "sha256:d1f5a500bfcbb2c0ab85e98a0dcd70f5899d34efe365a0187700369a79603031", + "sha256:d42a9a856a4a6e2f6c10f1318c07e7daa498d6593abe745c71dae4521a26ca39", + "sha256:d83b12902eb8bce151259c86c03ba746600b2d994543de46e370cecf96c452f2", + "sha256:d8e017eeb7482bed34cdb0d61cf2bcfc88d104bbab296a17cd16a6af8aabc70e", + "sha256:db3ae52ccc150dbc84704e9d642743897f3e1c54742ff34cacb661e52e3818a9", + "sha256:dbab5f5ff6897c81f355d079010cdae85b02e5a0b518b5251523b8ad8ae9ac3c", + "sha256:dc4242ca653c9b30ab51c5f8193323e7bc0928f897ee9103201e59a43abcb72e", + "sha256:dcbf346a318a5e30063f547630b02bb787ce2f45b6368d5da143660b6a3835d8", + "sha256:dd2ac8f5b643454c2cc6b6118b13da16e88f4a6434fc3ba61aca384029f04f36", + "sha256:e1d52a05dc417279f7e5c7618c5dfbbc29923aaf9bc0a5c1802ddcebf54c61a0", + "sha256:e6720ba44ad7e72174314d0e1fb0172494cff5c73a3a8a2159c3d2402ff15565", + "sha256:e738ab81179510ce79b2eac9a6ecf47feffd9e76d1c72e403005dddb6e36c06c", + "sha256:e904d4d01f36bd6e197590be1533c44e06058771e0746dd073a8ebb3ef880858", + "sha256:e9f165403b81fea7e89c932d89046a1e3d9a3a60e8d7ef2f249dccdcb0982bf5", + "sha256:ec6a85f424afa8d23e0d9a094e5dbb6eda01da91c92b9183cd433768247ffc97", + "sha256:ee19113bce2f3acd46432050688b70f61acd6857d75abb9ec96341b7e9ced123", + "sha256:ef3b928d9c984322b5c44e6964d8dbc653da87d2d8ee1647fa6da43072e650a9", + "sha256:f273dcf7149a50527c4fd1f55cfe9eac0f60753f5af544b4c9352578e20c0874", + "sha256:f5470694918830da62fac9e69133b53d23b736d7070e587b27a4a2be37e08e68", + "sha256:f574e460d1c8a08384a016fdb09ccf3543433263ed6b2f97104f979e64ea57c2", + "sha256:f85915e00dcb1cd9f2f890ead064ed40a27df06f0db65be427b29482ae357572", + "sha256:fc2461ecc45f17893f8207e73b46ea8ba93e33630e51cf4af3fbc21d47462b1a", + "sha256:ff6b113f50bc066a698db5d944d2c6dc7507168dd3341e255a8892fd0715a558" ], - "markers": "python_version >= '3.9'", - "version": "==0.4.1" + "markers": "python_version >= '3.10'", + "version": "==0.5.4" }, "psycogreen": { "hashes": [ @@ -1575,12 +1683,12 @@ }, "python-dotenv": { "hashes": [ - "sha256:b7e3b04a59693c42c36f9ab1cc2acc46fa5df8c78e178fc33a8d4cd05c8d498f", - "sha256:d92a187be61fe482e4fd675b6d52200e7be63a12b724abbf931a40ce4fa92938" + "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", + "sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3" ], "index": "pypi", - "markers": "python_version >= '3.5'", - "version": "==0.20.0" + "markers": "python_version >= '3.10'", + "version": "==1.2.2" }, "python-magic": { "hashes": [ @@ -1593,11 +1701,11 @@ }, "python-multipart": { "hashes": [ - "sha256:2b2cd894c83d21bf49d702499531c7bafd057d730c201782048f7945d82de155", - "sha256:7340bef99a7e0032613f56dc36027b959fd3b30a787ed62d310e951f7c3a3a58" + "sha256:be54b7f3fa167bb83e4fcd936b887b708f4e57fe75911c02aebf53efaf8d938e", + "sha256:ff6d3f776f16878c894e52e107296ffc890e913c611b1a4ec6c44e2821fe2e23" ], "markers": "python_version >= '3.10'", - "version": "==0.0.22" + "version": "==0.0.32" }, "pytz": { "hashes": [ @@ -1705,11 +1813,11 @@ }, "requests": { "hashes": [ - "sha256:18817f8c57c6263968bc123d237e3b8b08ac046f5456bd1e307ee8f4250d3517", - "sha256:4e6d1ef462f3626a1f0a0a9c42dd93c63bad33f9f1c1937509b8c5c8718ab56a" + "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0", + "sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed" ], "markers": "python_version >= '3.10'", - "version": "==2.33.1" + "version": "==2.34.2" }, "result": { "hashes": [ @@ -1721,124 +1829,125 @@ }, "rpds-py": { "hashes": [ - "sha256:07ae8a593e1c3c6b82ca3292efbe73c30b61332fd612e05abee07c79359f292f", - "sha256:0a59119fc6e3f460315fe9d08149f8102aa322299deaa5cab5b40092345c2136", - "sha256:0c0e95f6819a19965ff420f65578bacb0b00f251fefe2c8b23347c37174271f3", - "sha256:0d08f00679177226c4cb8c5265012eea897c8ca3b93f429e546600c971bcbae7", - "sha256:0ed177ed9bded28f8deb6ab40c183cd1192aa0de40c12f38be4d59cd33cb5c65", - "sha256:12f90dd7557b6bd57f40abe7747e81e0c0b119bef015ea7726e69fe550e394a4", - "sha256:1726859cd0de969f88dc8673bdd954185b9104e05806be64bcd87badbe313169", - "sha256:1ab5b83dbcf55acc8b08fc62b796ef672c457b17dbd7820a11d6c52c06839bdf", - "sha256:1b151685b23929ab7beec71080a8889d4d6d9fa9a983d213f07121205d48e2c4", - "sha256:1f3587eb9b17f3789ad50824084fa6f81921bbf9a795826570bda82cb3ed91f2", - "sha256:250fa00e9543ac9b97ac258bd37367ff5256666122c2d0f2bc97577c60a1818c", - "sha256:2771c6c15973347f50fece41fc447c054b7ac2ae0502388ce3b6738cd366e3d4", - "sha256:27f4b0e92de5bfbc6f86e43959e6edd1425c33b5e69aab0984a72047f2bcf1e3", - "sha256:2e6ecb5a5bcacf59c3f912155044479af1d0b6681280048b338b28e364aca1f6", - "sha256:32c8528634e1bf7121f3de08fa85b138f4e0dc47657866630611b03967f041d7", - "sha256:33f559f3104504506a44bb666b93a33f5d33133765b0c216a5bf2f1e1503af89", - "sha256:3896fa1be39912cf0757753826bc8bdc8ca331a28a7c4ae46b7a21280b06bb85", - "sha256:389a2d49eded1896c3d48b0136ead37c48e221b391c052fba3f4055c367f60a6", - "sha256:39c02563fc592411c2c61d26b6c5fe1e51eaa44a75aa2c8735ca88b0d9599daa", - "sha256:3adbb8179ce342d235c31ab8ec511e66c73faa27a47e076ccc92421add53e2bb", - "sha256:3d4a69de7a3e50ffc214ae16d79d8fbb0922972da0356dcf4d0fdca2878559c6", - "sha256:3e62880792319dbeb7eb866547f2e35973289e7d5696c6e295476448f5b63c87", - "sha256:3e8eeb0544f2eb0d2581774be4c3410356eba189529a6b3e36bbbf9696175856", - "sha256:422c3cb9856d80b09d30d2eb255d0754b23e090034e1deb4083f8004bd0761e4", - "sha256:4559c972db3a360808309e06a74628b95eaccbf961c335c8fe0d590cf587456f", - "sha256:46e83c697b1f1c72b50e5ee5adb4353eef7406fb3f2043d64c33f20ad1c2fc53", - "sha256:47b0ef6231c58f506ef0b74d44e330405caa8428e770fec25329ed2cb971a229", - "sha256:47e77dc9822d3ad616c3d5759ea5631a75e5809d5a28707744ef79d7a1bcfcad", - "sha256:47f236970bccb2233267d89173d3ad2703cd36a0e2a6e92d0560d333871a3d23", - "sha256:47f9a91efc418b54fb8190a6b4aa7813a23fb79c51f4bb84e418f5476c38b8db", - "sha256:495aeca4b93d465efde585977365187149e75383ad2684f81519f504f5c13038", - "sha256:4c5f36a861bc4b7da6516dbdf302c55313afa09b81931e8280361a4f6c9a2d27", - "sha256:4cc2206b76b4f576934f0ed374b10d7ca5f457858b157ca52064bdfc26b9fc00", - "sha256:4e7fc54e0900ab35d041b0601431b0a0eb495f0851a0639b6ef90f7741b39a18", - "sha256:51a1234d8febafdfd33a42d97da7a43f5dcb120c1060e352a3fbc0c6d36e2083", - "sha256:55f66022632205940f1827effeff17c4fa7ae1953d2b74a8581baaefb7d16f8c", - "sha256:58edca431fb9b29950807e301826586e5bbf24163677732429770a697ffe6738", - "sha256:5965af57d5848192c13534f90f9dd16464f3c37aaf166cc1da1cae1fd5a34898", - "sha256:5ba103fb455be00f3b1c2076c9d4264bfcb037c976167a6047ed82f23153f02e", - "sha256:5d4c2aa7c50ad4728a094ebd5eb46c452e9cb7edbfdb18f9e1221f597a73e1e7", - "sha256:61046904275472a76c8c90c9ccee9013d70a6d0f73eecefd38c1ae7c39045a08", - "sha256:613aa4771c99f03346e54c3f038e4cc574ac09a3ddfb0e8878487335e96dead6", - "sha256:626a7433c34566535b6e56a1b39a7b17ba961e97ce3b80ec62e6f1312c025551", - "sha256:669b1805bd639dd2989b281be2cfd951c6121b65e729d9b843e9639ef1fd555e", - "sha256:679ae98e00c0e8d68a7fda324e16b90fd5260945b45d3b824c892cec9eea3288", - "sha256:67b02ec25ba7a9e8fa74c63b6ca44cf5707f2fbfadae3ee8e7494297d56aa9df", - "sha256:68f19c879420aa08f61203801423f6cd5ac5f0ac4ac82a2368a9fcd6a9a075e0", - "sha256:692bef75a5525db97318e8cd061542b5a79812d711ea03dbc1f6f8dbb0c5f0d2", - "sha256:6abc8880d9d036ecaafe709079969f56e876fcf107f7a8e9920ba6d5a3878d05", - "sha256:6bdfdb946967d816e6adf9a3d8201bfad269c67efe6cefd7093ef959683c8de0", - "sha256:6de2a32a1665b93233cde140ff8b3467bdb9e2af2b91079f0333a0974d12d464", - "sha256:73c67f2db7bc334e518d097c6d1e6fed021bbc9b7d678d6cc433478365d1d5f5", - "sha256:74a3243a411126362712ee1524dfc90c650a503502f135d54d1b352bd01f2404", - "sha256:76fec018282b4ead0364022e3c54b60bf368b9d926877957a8624b58419169b7", - "sha256:7c64d38fb49b6cdeda16ab49e35fe0da2e1e9b34bc38bd78386530f218b37139", - "sha256:7cee9c752c0364588353e627da8a7e808a66873672bcb5f52890c33fd965b394", - "sha256:7e6ecfcb62edfd632e56983964e6884851786443739dbfe3582947e87274f7cb", - "sha256:806f36b1b605e2d6a72716f321f20036b9489d29c51c91f4dd29a3e3afb73b15", - "sha256:858738e9c32147f78b3ac24dc0edb6610000e56dc0f700fd5f651d0a0f0eb9ff", - "sha256:8d6d1cc13664ec13c1b84241204ff3b12f9bb82464b8ad6e7a5d3486975c2eed", - "sha256:9027da1ce107104c50c81383cae773ef5c24d296dd11c99e2629dbd7967a20c6", - "sha256:922e10f31f303c7c920da8981051ff6d8c1a56207dbdf330d9047f6d30b70e5e", - "sha256:945dccface01af02675628334f7cf49c2af4c1c904748efc5cf7bbdf0b579f95", - "sha256:946fe926af6e44f3697abbc305ea168c2c31d3e3ef1058cf68f379bf0335a78d", - "sha256:95f0802447ac2d10bcc69f6dc28fe95fdf17940367b21d34e34c737870758950", - "sha256:9854cf4f488b3d57b9aaeb105f06d78e5529d3145b1e4a41750167e8c213c6d3", - "sha256:993914b8e560023bc0a8bf742c5f303551992dcb85e247b1e5c7f4a7d145bda5", - "sha256:99b47d6ad9a6da00bec6aabe5a6279ecd3c06a329d4aa4771034a21e335c3a97", - "sha256:9a4e86e34e9ab6b667c27f3211ca48f73dba7cd3d90f8d5b11be56e5dbc3fb4e", - "sha256:9cf69cdda1f5968a30a359aba2f7f9aa648a9ce4b580d6826437f2b291cfc86e", - "sha256:a090322ca841abd453d43456ac34db46e8b05fd9b3b4ac0c78bcde8b089f959b", - "sha256:a1010ed9524c73b94d15919ca4d41d8780980e1765babf85f9a2f90d247153dd", - "sha256:a161f20d9a43006833cd7068375a94d035714d73a172b681d8881820600abfad", - "sha256:a1d0bc22a7cdc173fedebb73ef81e07faef93692b8c1ad3733b67e31e1b6e1b8", - "sha256:a2bffea6a4ca9f01b3f8e548302470306689684e61602aa3d141e34da06cf425", - "sha256:a452763cc5198f2f98898eb98f7569649fe5da666c2dc6b5ddb10fde5a574221", - "sha256:a4796a717bf12b9da9d3ad002519a86063dcac8988b030e405704ef7d74d2d9d", - "sha256:a51033ff701fca756439d641c0ad09a41d9242fa69121c7d8769604a0a629825", - "sha256:a8fa71a2e078c527c3e9dc9fc5a98c9db40bcc8a92b4e8858e36d329f8684b51", - "sha256:ac37f9f516c51e5753f27dfdef11a88330f04de2d564be3991384b2f3535d02e", - "sha256:ac98b175585ecf4c0348fd7b29c3864bda53b805c773cbf7bfdaffc8070c976f", - "sha256:acd7eb3f4471577b9b5a41baf02a978e8bdeb08b4b355273994f8b87032000a8", - "sha256:ad1fa8db769b76ea911cb4e10f049d80bf518c104f15b3edb2371cc65375c46f", - "sha256:b40fb160a2db369a194cb27943582b38f79fc4887291417685f3ad693c5a1d5d", - "sha256:b4dc1a6ff022ff85ecafef7979a2c6eb423430e05f1165d6688234e62ba99a07", - "sha256:ba3af48635eb83d03f6c9735dfb21785303e73d22ad03d489e88adae6eab8877", - "sha256:ba81a9203d07805435eb06f536d95a266c21e5b2dfbf6517748ca40c98d19e31", - "sha256:c2262bdba0ad4fc6fb5545660673925c2d2a5d9e2e0fb603aad545427be0fc58", - "sha256:c77afbd5f5250bf27bf516c7c4a016813eb2d3e116139aed0096940c5982da94", - "sha256:ca28829ae5f5d569bb62a79512c842a03a12576375d5ece7d2cadf8abe96ec28", - "sha256:cdc62c8286ba9bf7f47befdcea13ea0e26bf294bda99758fd90535cbaf408000", - "sha256:d948b135c4693daff7bc2dcfc4ec57237a29bd37e60c2fabf5aff2bbacf3e2f1", - "sha256:d96c2086587c7c30d44f31f42eae4eac89b60dabbac18c7669be3700f13c3ce1", - "sha256:d9a0ca5da0386dee0655b4ccdf46119df60e0f10da268d04fe7cc87886872ba7", - "sha256:da279aa314f00acbb803da1e76fa18666778e8a8f83484fba94526da5de2cba7", - "sha256:dbd936cde57abfee19ab3213cf9c26be06d60750e60a8e4dd85d1ab12c8b1f40", - "sha256:dc4f992dfe1e2bc3ebc7444f6c7051b4bc13cd8e33e43511e8ffd13bf407010d", - "sha256:dc824125c72246d924f7f796b4f63c1e9dc810c7d9e2355864b3c3a73d59ade0", - "sha256:dd8ff7cf90014af0c0f787eea34794ebf6415242ee1d6fa91eaba725cc441e84", - "sha256:dea5b552272a944763b34394d04577cf0f9bd013207bc32323b5a89a53cf9c2f", - "sha256:dff13836529b921e22f15cb099751209a60009731a68519630a24d61f0b1b30a", - "sha256:e0b65193a413ccc930671c55153a03ee57cecb49e6227204b04fae512eb657a7", - "sha256:e5d3e6b26f2c785d65cc25ef1e5267ccbe1b069c5c21b8cc724efee290554419", - "sha256:e7536cd91353c5273434b4e003cbda89034d67e7710eab8761fd918ec6c69cf8", - "sha256:eb0b93f2e5c2189ee831ee43f156ed34e2a89a78a66b98cadad955972548be5a", - "sha256:eb2c4071ab598733724c08221091e8d80e89064cd472819285a9ab0f24bcedb9", - "sha256:ec7c4490c672c1a0389d319b3a9cfcd098dcdc4783991553c332a15acf7249be", - "sha256:ee454b2a007d57363c2dfd5b6ca4a5d7e2c518938f8ed3b706e37e5d470801ed", - "sha256:ee6af14263f25eedc3bb918a3c04245106a42dfd4f5c2285ea6f997b1fc3f89a", - "sha256:f14fc5df50a716f7ece6a80b6c78bb35ea2ca47c499e422aa4463455dd96d56d", - "sha256:f207f69853edd6f6700b86efb84999651baf3789e78a466431df1331608e5324", - "sha256:f251c812357a3fed308d684a5079ddfb9d933860fc6de89f2b7ab00da481e65f", - "sha256:f83424d738204d9770830d35290ff3273fbb02b41f919870479fab14b9d303b2", - "sha256:f8d1736cfb49381ba528cd5baa46f82fdc65c06e843dab24dd70b63d09121b3f", - "sha256:fe5fa731a1fa8a0a56b0977413f8cacac1768dad38d16b3a296712709476fbd5" + "sha256:0be972be84cfcaf46c8c6edf690ca0f154ac17babf1f6a955a51579b34ad2dc5", + "sha256:127565fead0a10943b282957bd5447804ff3160ad79f2ad2635e6d249e380680", + "sha256:127e08c0642d880cf32ca47ec2a4a77b901f7e2dd1ad9762adb13955d72ffcc9", + "sha256:166cf54d9f44fc6ceb53c7860258dde44a81406646de79f8ed3234fca3b6e538", + "sha256:168c733a7112e071bb7a66460e667edfcff06c017a3c523f7a8a8e08d0140804", + "sha256:1967debc37f64f2c4dc90a7f563aec558b471966e12adcac4e1c4240496b6ebf", + "sha256:1cebd1337c242e4ec2293e541f712b2da849b29f48f0c293684b71c0632625d4", + "sha256:1cf01971c4f2c5553b772a542e4aaf191789cd331bc2cd4ff0e6e65ba49e1e97", + "sha256:1e5822dfc2f0d4ab7e745eaa6d85945069329beeccef965af3f3bb26058fcab6", + "sha256:22bffe6042b9bcb0822bcd1955ec00e245daf17b4344e4ed8e9551b976b63e96", + "sha256:23a439f31ccbeff1574e24889128821d1f7917470e830cf6544dced1c662262a", + "sha256:24e9c5386e16669b674a69c156c8eeefcb578f3b3397b713b08e6d60f3c7b187", + "sha256:270b293dae9058fc9fcedab50f13cebf46fb8ed1d1d54e0521a9da5d6b211975", + "sha256:29dfa0533a5d4c94d4dfa1b694fcb56c9c63aad8330ffdd816fd225d0a7a162f", + "sha256:2a9c6f195058cb45335e8cc3802745c603d716eb96bc9625950c1aac71c0c703", + "sha256:2bfd04c19ddbd6640de0b51894d764bd2758854d5b75bd102d2ef10cb9c293a9", + "sha256:2c54a076ca4d370980ab57bc0e31df57bbe8d41340436a90ef8b1219a3cbb127", + "sha256:2c958bf94822e9290a40aaf2a822d4bc5c88099093e3948ad6c571eca9272e5f", + "sha256:2c99f7e8ccb3dd6e3e4bfeac657a7b208c9bac8075f4b078c02d7404c34107fa", + "sha256:2f7c26fbc5acd2522b95d4177fe4710ffd8e9b20529e703ffbf8db4d93903f05", + "sha256:30c6dc199b24a5e3e81d50da0f00858c5bbdb2617a750395687f4339c5818171", + "sha256:38a2fea2787428f811719ceb9114cb78964a3138838320c29ac39526c79c16ba", + "sha256:3a83ae6c67b7676b9878378547ca8e93ed77a580037bcbcd1d32f739e1e6089c", + "sha256:3cfe765c1da0072636ca06628261e0ea05688e160d5c8a03e0217c3854037223", + "sha256:421aba32367055614287a4292b6a17f1939c9452299f7a0209c117e990b646d4", + "sha256:425560c6fa0415f27261727bb20bd097568485e5eb0c121f1949417d1c516885", + "sha256:4470ce197d4090875cf6affbf1f853338387428df97c4fb7b7106317b8214698", + "sha256:4cf2d36a2357e4d07bb5a4f98801265327b48256867816cfd2ceb001e9754a8f", + "sha256:4f4bca01b63096f606e095734dd56e74e175f94cfbf24ff3d63281cec61f7bb7", + "sha256:501f9f04a588d6a09179368c57071301445191767c64e4b52a6aa9871f1ef5ed", + "sha256:536bceea4fa4acf7e1c61da2b5786304367c816c8895be71b8f537c480b0ea1f", + "sha256:538949e262e46caa31ac01bdb3c1e8f642622922cacbabbae6a8445d9dc33eaf", + "sha256:539d75de9e0d536c84ff18dfeb805398e58227001ce09231a26a08b9aed1ee0e", + "sha256:54f45a148e28767bf343d33a684693c70e451c6f4c0e9904709a723fafbdfc1f", + "sha256:55927d532399c2c646100ff7feb48eaa940ad70f42cd68e1328f3ded9f81ca24", + "sha256:58eadac9cd119677b60e1cf8ac4052f35949d71b8a9e5556efccbe82533cf22a", + "sha256:5e8d07bddee435a2ff6f1920e18feff28d0bc4533e42f4bf6927fbd073312c41", + "sha256:62698275682bf121181861295c9181e789030a2d516071f5b8f3c23c170cd0fc", + "sha256:639c8929aa0afe81be836b04de888460d6bed38b9c54cfc18da8f6bfabf5af5d", + "sha256:67e3a721ffc5d8d2210d3671872298c4a84e4b8035cfe42ffd7cde35d772b146", + "sha256:6de4744d05bd1aa1be4ed7ea1189e3979196808008113bbbf899a460966b925e", + "sha256:6e84adbcf4bf841aed8116a8264b9f50b4cb3e7bd89b516122e616ac56ca269e", + "sha256:7491ee23305ac3eb59e492b6945881f5cd77a6f731061a3f25b77fd40f9e99a4", + "sha256:79486287de1730dbaff3dbd124d0ca4d2ef7f9d29bf2544f1f93c09b5bcbbd12", + "sha256:7b689145a1485c335569bd056464f3243a29af7ed3871c7be31ad624ba239bc7", + "sha256:7f88d653e7b3b779d71ae7454e20dcc9b6bae903f33c269db9f2be41bda3f261", + "sha256:8020133a74bd81b4572dd8e4be028a6b1ebcd70e6726edc3918008c08bee6ee6", + "sha256:808345f53cb952433ca2816f1604ff3515608a81784954f38d4452acfe8e61d5", + "sha256:83e35b57523816c8613fd0776b40cd8bb9f596b37ddd2692eb4a6bb5ab2f8c93", + "sha256:842e7b070435622248c7a2c44ae53fa1440e073cc3023bc919fed570884097a7", + "sha256:847927daf4cffbd4e90e42bc890069897101edd015f956cb8721b3473372edda", + "sha256:882076c00c0a608b131187055ddc5ae29f2e7eaf870d6168980420d58528a5c8", + "sha256:8b95977e7211527ab0ba576e286d023389fbeeb32a6b7b771665d333c60e5342", + "sha256:8bb68f03f395eb793220b45c097bd4d8c32944393da0fad8b999efac0868fc8c", + "sha256:8c2642a7603ec0b16ed77da4555db3b4b472341904873788327c0b0d7b95f1bb", + "sha256:8c3d1e9c15b9d51ca0391e13da1a25a0a4df3c58a37c9dc368e0736cf7f69df0", + "sha256:8c6e5a2f750cc71c3e3b11d71661f21d6f9bc6cebc6564b1466417a1ec03ec77", + "sha256:8d2294a31386bfa251d8c8a39472beee17db67d4f1a6eabea665d35c9a4461c3", + "sha256:8e4320744c1ffdd95a603def63344bfab2d33edeab301c5007e7de9f9f5b3885", + "sha256:8e65860d238379ed982fd9ba690579b5e95af2f4840f99c772816dbe573cb826", + "sha256:8f2e5c5ee828d42cb11760761c0af6507927bec42d0ad5458f97c9203b054617", + "sha256:900a67df3fd1660b035a4761c4ce73c382ea6b35f90f9863c36c6fd8bf8b09bb", + "sha256:913ca42ccad3f8cc6e292b587ae8ae49c8c823e5dce51a736252fc7c7cdfa577", + "sha256:9250a9a0a6fd4648b3f868da8d91a4c52b5811a62df58e753d50ae4454a36f80", + "sha256:931908d9fc855d8f74783377822be318edb6dcb19e47169dc038f9a1bf60b06e", + "sha256:9826217f048f620d9a712672818bf231442c1b35d96b227a07eabd11b4bb6945", + "sha256:9891e594296ab9dada6551c8e7b387b2721f27a67eecd528412e8906247a7b90", + "sha256:9c1255b302953c86a486b81d330d5ee1d5bd937691ce271b6be0ef0e299eaab7", + "sha256:a0811d33247c3d6128a3001d763f2aa056bb3425204335400ac54f89eec3a0d0", + "sha256:a136d453475ac0fcbda502ef1e6504bd28d6d904700915d278deeab0d00fe140", + "sha256:a214c993455f99a89aaeadc9b21241900037adc9d97203e374d75513c5911822", + "sha256:a3086b538543802f84c843911242db20447de00d8752dd0efc936dbcf02218ba", + "sha256:a3450b693fde92133e9f51060568a4c31fcca76d5e53bbd611e689ca446517e9", + "sha256:a550fb4950a06dde3beb4721f5ad4b25bf4513784665b0a8522c792e2bd822a4", + "sha256:a9f4645593036b81bbdb36b9c8e0ea0d1c3fee968c4d59db0344c14087ef143a", + "sha256:aca6c1ef08a82bfe327cc156da694660f599923e2e6665b6d81c9c2d0ac9ffc8", + "sha256:acac386b453c2516111b50985d60ce46e7fadb5ea71ae7b25f4c946935bf27cf", + "sha256:acc992ab27b15f852c76755eb2ab7dce86585ddadba6fa5946e58556088845b4", + "sha256:ae3d4fe8c0b9213624fdce7279d70e3b148b682ca20719ebd193a23ebfa47324", + "sha256:ae50181a047c871561212bb97f7932a2d45fb53e947bd9b57ebad85b529cbc53", + "sha256:ae6dd8f10bd17aad820876d24caec9efdafd80a318d16c0a48edb5e136902c6b", + "sha256:af05d726809bff6b141be124d4c7ce998f9c9c7f30edb1f46c07aa103d540b41", + "sha256:afd70d95892096cdb26f15a00c45907b17817577aa8d1c76b2dcc2788391f9e9", + "sha256:b5c2dc92304aa48a4a60443b548bb12f12e119d4b72f314015e67b9e1be97fca", + "sha256:bc0011654b91cc4fb2ae701bec0a0ba1e552c0714247fa7af6c59e0ccfa3a4e1", + "sha256:bcfbcf66006befb9fd2aeaa9e01feaf881b4dc330a02ba07d2322b1c11be7b5d", + "sha256:bdbd97738551fca3917c1bd7188bec1920bb520104f28e7e1007f9ceb17b7690", + "sha256:c60924535c75f1566b6eb75b5c31a48a43fef04fa2d0d201acbad8a9969c6107", + "sha256:c7b9a2f8f4d8e90af72571d3d495deebdd7e3c75451f5b41719aee166e940fc2", + "sha256:ca6546b66be9dc4738b1b043d5ebd5488c66c578c5ff0fd0e8065313fe3afb76", + "sha256:ccffae9a092a00deb7efd545fe5e2c33c33b88e7c054337e9a74c179347d0b7d", + "sha256:cdc7e35386f3847df728fbcb5e887e2d79c19e2fa1eba9e51b6621d23e3243af", + "sha256:d15fde0e6fb0d88a60d221204873743e5d9f0b7d29165e62cd86d0413ad74ba6", + "sha256:d34c20167764fbcf927194d532dd7e0c56772f0a5f943fa5ef9e9afbba8fb9db", + "sha256:d483fe17f01ad64b7bf7cc38fcefff1ca9fb83f8c2b2542b68f97ffe0611b369", + "sha256:d7469697dce35be237db177d42e2a2ee26e6dcc5fc052078a6fefabd288c6edd", + "sha256:db08f45aecde626498fb3df07bcf6d2ec040af42e859a4f5040d79c200342911", + "sha256:dc319e5a1de4b6913aac94bf6a2f9e847371e0a140a43dd4991db1a09bc2d504", + "sha256:de3eceba0b683bcbb1ab93da016d0270df1f9ae7be716b40214c5dafac6ea45a", + "sha256:dfcc8b909769d19db55c7cc9541eb64b9b774b1057ffffb4f1048070475bb9f9", + "sha256:e059c5dde6452b44424bd1834557556c226b57781dee1227af23518459722b13", + "sha256:e4316bf32babbed84e691e352faf967ce2f0f024174a8643c37c94a1080374fc", + "sha256:e52655eaf81e32593abedaa4bfe33170c8cfedf3365ed9be6e11e07f148f0278", + "sha256:e55d236be29255554da47abe5c577637db7c24a02b8b46f0ca9524c855801868", + "sha256:ea7bb13b7c9a29791f87a0387ba7d3ad3a6d783d827e4d3f27b40a0ff44495e2", + "sha256:ea964164cc9afa72d4d9b23cc28dafae93693c0a53e0b42acbff15b22c3f9ddd", + "sha256:ec829541c45bca16e61c7ae50c20501f213605beb75d1aba91a6ee37fbbb56a4", + "sha256:ecabd69db66de867690f9797f2f8fa27ba501bbc24540cbdbdc649cd15888ba6", + "sha256:ed0c1e5d10cdc7135537988c74a0188da68e2f3c30813ba3744ab1e42e0480f9", + "sha256:f0840b5b17057f7fd918b76183a4b5a0635f43e14eb2ce60dce1d4ee4707ea00", + "sha256:f4d78253f6996be4901669ad25319f842f740eccf4d58e3c7f3dd39e6dde1d8f", + "sha256:f56f1695bc5c0871cbc33dc0130fcf503aab0c57dcc5a6700a4f49eba4f2652e", + "sha256:f826877d462181e5eb1c26a0026b8d0cab05d99844ecb6d8bf3627a2ca0c0442", + "sha256:f8f23ead891a3b762f35ab3b04623da7056545b48aa60d59957e6789914545da", + "sha256:f90938e92afda60266da758ee7d363447f7f0138c9559f9e1811629580582d90", + "sha256:faa679d19a6696fd54259ad321251ad77a13e70e03dd834daa762a44fb6196ef" ], - "markers": "python_version >= '3.10'", - "version": "==0.30.0" + "markers": "python_version >= '3.11'", + "version": "==2026.6.3" }, "safe": { "hashes": [ @@ -1859,11 +1968,11 @@ }, "setuptools": { "hashes": [ - "sha256:7d872682c5d01cfde07da7bccc7b65469d3dca203318515ada1de5eda35efbf9", - "sha256:a59e362652f08dcd477c78bb6e7bd9d80a7995bc73ce773050228a348ce2e5bb" + "sha256:51a52592b3b99e102b609654876bd65f19f999935166d1352678931132b0c670", + "sha256:f4695c21257f0d9b537ec2692c941d02ee143b7cc1276941349a546573b2ef73" ], - "markers": "python_version >= '3.9'", - "version": "==82.0.1" + "markers": "python_version >= '3.10'", + "version": "==84.0.0" }, "shapely": { "hashes": [ @@ -2011,20 +2120,20 @@ }, "tzdata": { "hashes": [ - "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1", - "sha256:de39c2ca5dc7b0344f2eba86f49d614019d29f060fc4ebc8a417896a620b56a7" + "sha256:c2169a8b0a7a5e9674da5a135ccdfb2b3e671b333ed9fed17b41f73c34476e81", + "sha256:f1b8bd365d8d210c55353f4d7f8d6d8561c0ba50d704b700d195a9424bba0d79" ], "markers": "python_version >= '2'", - "version": "==2025.3" + "version": "==2026.4" }, "urllib3": { "hashes": [ - "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472", - "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168" + "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", + "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897" ], "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==2.2.2" + "markers": "python_version >= '3.10'", + "version": "==2.7.0" }, "vine": { "hashes": [ @@ -2036,27 +2145,46 @@ }, "wcwidth": { "hashes": [ - "sha256:1a3a1e510b553315f8e146c54764f4fb6264ffad731b3d78088cdb1478ffbdad", - "sha256:cdc4e4262d6ef9a1a57e018384cbeb1208d8abbc64176027e2c2455c81313159" + "sha256:03cfca3dcbffa86564290fe3c9978a6191ba003e8ced7f7dbda315fcb3fbe725", + "sha256:0665ee822ea04e25801e6e82e5407528be0863e88a17b0e7ca038843a4a3ac0c", + "sha256:0d68a30d504c68cfdff2a5f804675c1e7ab4c0bbe878024c8b680ec5579cde67", + "sha256:10b00ba23482e352f874d2e8135e7ace9da838646c7dd800566246bbd46125ff", + "sha256:356376852357b8fca71fe5415808ec421679e04b4a98eb7c9cb6a7984b911a05", + "sha256:40d936d72c9bdc10df43f93a8be502bc5024b487259139f66a328722c07f34a9", + "sha256:5823209b0d43af322ce698c689380d7c15ca31fa8e6e3be8459f27031bef0af5", + "sha256:61bd7aef9cafb6cb77a37a169998d7928ce82a51522146d11f60db9e7d1cb43a", + "sha256:69bb970cf5652b88cfdb9d3fdd1764fc15e5f8ad531643e7bb3e894cd969740e", + "sha256:6e1272b7986cefe79783737e38bdb9eaae0682b333c7bd132024441193dd5ce7", + "sha256:708158c082364af442f9983de7b6ec9ac0d2e1b825ada25f0911b1f138d55405", + "sha256:747fb724223f417a17541a95a17c1dac3a8ef9a0cf41684950f0eab191a35f65", + "sha256:991d1c8834f548e9c1f16432075ee84638e122312556bbf1ed595ea8fffc4673", + "sha256:9f1636c5075ffd5c2e835b4561874f6e5dd2bbeba3c6c2c99f067d0d16883af8", + "sha256:b5da43d6967668982e44a52fb551967d293f86d26cd86036ac95bbdd34394ed9", + "sha256:bcb9ed4a367cc025bf1092ac679a156759605182d60b7ed3c28f7221a42ddf55", + "sha256:c4cead196551112cb8f43cdd1f80c235ef2456e34b1a9955c424537ec99961b2", + "sha256:dc10e262c3ac0abbfd0a2a51e45a848b1b7f500b21ff512630277973ba25674d", + "sha256:e0c3a1c45c5b9550c6919a4449e95f5b177f6e165786376981db8f1addae9b21", + "sha256:eab587e18e7cadf1a750b0098fc8bebfb62c125eb9306f2268f0443a282a3d78", + "sha256:fe021c4d8de9d36c31a0cb41d0d2546dadd3b0708a301f1a0c66ce200851831f" ], - "markers": "python_version >= '3.8'", - "version": "==0.6.0" + "markers": "python_version >= '3.9'", + "version": "==0.9.1" }, "werkzeug": { "hashes": [ - "sha256:4b314d81163a3e1a169b6a0be2a000a0e204e8873c5de6586f453c55688d422f", - "sha256:fb8c01fe6ab13b9b7cdb46892b99b1d66754e1d7ab8e542e865ec13f526b5351" + "sha256:55ca7c70a75689be937aa27f8ff4b018f06ff4838fc73045560bf0f5a1291060", + "sha256:6392e50c78460ba618e5b21f08a71f59c99ce99cdc6cf6e3dd7e6ccca8754fab" ], "markers": "python_version >= '3.9'", - "version": "==3.1.7" + "version": "==3.1.9" }, "wheel": { "hashes": [ - "sha256:4b399d56c9d9338230118d705d9737a2a468ccca63d5e813e2a4fc7815d8bc4d", - "sha256:e3e79874b07d776c40bd6033f8ddf76a7dad46a7b8aa1b2787a83083519a1803" + "sha256:3217dcc807155e45db462d7ef2431f5ddda0d7273b700d05a67b271ceb1287ab", + "sha256:94800765601e9171bf5d58d066e640662842bcedcbab982b2c90787a2c987322" ], "markers": "python_version >= '3.9'", - "version": "==0.46.3" + "version": "==0.48.0" }, "wtforms": { "extras": [ @@ -2078,190 +2206,210 @@ }, "yarl": { "hashes": [ - "sha256:03214408cfa590df47728b84c679ae4ef00be2428e11630277be0727eba2d7cc", - "sha256:041b1a4cefacf65840b4e295c6985f334ba83c30607441ae3cf206a0eed1a2e4", - "sha256:0793e2bd0cf14234983bbb371591e6bea9e876ddf6896cdcc93450996b0b5c85", - "sha256:0e1fdaa14ef51366d7757b45bde294e95f6c8c049194e793eedb8387c86d5993", - "sha256:0e40111274f340d32ebcc0a5668d54d2b552a6cca84c9475859d364b380e3222", - "sha256:115136c4a426f9da976187d238e84139ff6b51a20839aa6e3720cd1026d768de", - "sha256:13a563739ae600a631c36ce096615fe307f131344588b0bc0daec108cdb47b25", - "sha256:16c6994ac35c3e74fb0ae93323bf8b9c2a9088d55946109489667c510a7d010e", - "sha256:170e26584b060879e29fac213e4228ef063f39128723807a312e5c7fec28eff2", - "sha256:17235362f580149742739cc3828b80e24029d08cbb9c4bda0242c7b5bc610a8e", - "sha256:1932b6b8bba8d0160a9d1078aae5838a66039e8832d41d2992daa9a3a08f7860", - "sha256:1b6b572edd95b4fa8df75de10b04bc81acc87c1c7d16bcdd2035b09d30acc957", - "sha256:1c3a3598a832590c5a3ce56ab5576361b5688c12cb1d39429cf5dba30b510760", - "sha256:1c57676bdedc94cd3bc37724cf6f8cd2779f02f6aba48de45feca073e714fe52", - "sha256:1dc702e42d0684f42d6519c8d581e49c96cefaaab16691f03566d30658ee8788", - "sha256:21d1b7305a71a15b4794b5ff22e8eef96ff4a6d7f9657155e5aa419444b28912", - "sha256:23f371bd662cf44a7630d4d113101eafc0cfa7518a2760d20760b26021454719", - "sha256:2569b67d616eab450d262ca7cb9f9e19d2f718c70a8b88712859359d0ab17035", - "sha256:263cd4f47159c09b8b685890af949195b51d1aa82ba451c5847ca9bc6413c220", - "sha256:2803ed8b21ca47a43da80a6fd1ed3019d30061f7061daa35ac54f63933409412", - "sha256:2a6940a074fb3c48356ed0158a3ca5699c955ee4185b4d7d619be3c327143e05", - "sha256:2e27c8841126e017dd2a054a95771569e6070b9ee1b133366d8b31beb5018a41", - "sha256:31c9921eb8bd12633b41ad27686bbb0b1a2a9b8452bfdf221e34f311e9942ed4", - "sha256:34b6cf500e61c90f305094911f9acc9c86da1a05a7a3f5be9f68817043f486e4", - "sha256:3650dc2480f94f7116c364096bc84b1d602f44224ef7d5c7208425915c0475dd", - "sha256:389871e65468400d6283c0308e791a640b5ab5c83bcee02a2f51295f95e09748", - "sha256:39004f0ad156da43e86aa71f44e033de68a44e5a31fc53507b36dd253970054a", - "sha256:394906945aa8b19fc14a61cf69743a868bb8c465efe85eee687109cc540b98f4", - "sha256:3ceb13c5c858d01321b5d9bb65e4cf37a92169ea470b70fec6f236b2c9dd7e34", - "sha256:411225bae281f114067578891bc75534cfb3d92a3b4dfef7a6ca78ba354e6069", - "sha256:44bb7bef4ea409384e3f8bc36c063d77ea1b8d4a5b2706956c0d6695f07dcc25", - "sha256:4503053d296bc6e4cbd1fad61cf3b6e33b939886c4f249ba7c78b602214fabe2", - "sha256:4764a6a7588561a9aef92f65bda2c4fb58fe7c675c0883862e6df97559de0bfb", - "sha256:4966242ec68afc74c122f8459abd597afd7d8a60dc93d695c1334c5fd25f762f", - "sha256:4a42e651629dafb64fd5b0286a3580613702b5809ad3f24934ea87595804f2c5", - "sha256:4a59ba56f340334766f3a4442e0efd0af895fae9e2b204741ef885c446b3a1a8", - "sha256:4c41e021bc6d7affb3364dc1e1e5fa9582b470f283748784bd6ea0558f87f42c", - "sha256:5023346c4ee7992febc0068e7593de5fa2bf611848c08404b35ebbb76b1b0512", - "sha256:50f9d8d531dfb767c565f348f33dd5139a6c43f5cbdf3f67da40d54241df93f6", - "sha256:51430653db848d258336cfa0244427b17d12db63d42603a55f0d4546f50f25b5", - "sha256:531ef597132086b6cf96faa7c6c1dcd0361dd5f1694e5cc30375907b9b7d3ea9", - "sha256:53ad387048f6f09a8969631e4de3f1bf70c50e93545d64af4f751b2498755072", - "sha256:53b1ea6ca88ebd4420379c330aea57e258408dd0df9af0992e5de2078dc9f5d5", - "sha256:575aa4405a656e61a540f4a80eaa5260f2a38fff7bfdc4b5f611840d76e9e277", - "sha256:578110dd426f0d209d1509244e6d4a3f1a3e9077655d98c5f22583d63252a08a", - "sha256:5ec2f42d41ccbd5df0270d7df31618a8ee267bfa50997f5d720ddba86c4a83a6", - "sha256:5ee586fb17ff8f90c91cf73c6108a434b02d69925f44f5f8e0d7f2f260607eae", - "sha256:5f10fd85e4b75967468af655228fbfd212bdf66db1c0d135065ce288982eda26", - "sha256:609d3614d78d74ebe35f54953c5bbd2ac647a7ddb9c30a5d877580f5e86b22f2", - "sha256:62694e275c93d54f7ccedcfef57d42761b2aad5234b6be1f3e3026cae4001cd4", - "sha256:63e92247f383c85ab00dd0091e8c3fa331a96e865459f5ee80353c70a4a42d70", - "sha256:682bae25f0a0dd23a056739f23a134db9f52a63e2afd6bfb37ddc76292bbd723", - "sha256:6b41389c19b07c760c7e427a3462e8ab83c4bb087d127f0e854c706ce1b9215c", - "sha256:6e87a6e8735b44816e7db0b2fbc9686932df473c826b0d9743148432e10bb9b9", - "sha256:6f0fd84de0c957b2d280143522c4f91a73aada1923caee763e24a2b3fda9f8a5", - "sha256:70efd20be968c76ece7baa8dafe04c5be06abc57f754d6f36f3741f7aa7a208e", - "sha256:71d006bee8397a4a89f469b8deb22469fe7508132d3c17fa6ed871e79832691c", - "sha256:73309162a6a571d4cbd3b6a1dcc703c7311843ae0d1578df6f09be4e98df38d4", - "sha256:75e3026ab649bf48f9a10c0134512638725b521340293f202a69b567518d94e0", - "sha256:76855800ac56f878847a09ce6dba727c93ca2d89c9e9d63002d26b916810b0a2", - "sha256:7c6b9461a2a8b47c65eef63bb1c76a4f1c119618ffa99ea79bc5bb1e46c5821b", - "sha256:803a3c3ce4acc62eaf01eaca1208dcf0783025ef27572c3336502b9c232005e7", - "sha256:80e6d33a3d42a7549b409f199857b4fb54e2103fc44fb87605b6663b7a7ff750", - "sha256:8419ebd326430d1cbb7efb5292330a2cf39114e82df5cc3d83c9a0d5ebeaf2f2", - "sha256:85610b4f27f69984932a7abbe52703688de3724d9f72bceb1cca667deff27474", - "sha256:85e9beda1f591bc73e77ea1c51965c68e98dafd0fec72cdd745f77d727466716", - "sha256:877b0738624280e34c55680d6054a307aa94f7d52fa0e3034a9cc6e790871da7", - "sha256:88f9fb0116fbfcefcab70f85cf4b74a2b6ce5d199c41345296f49d974ddb4123", - "sha256:8c4fe09e0780c6c3bf2b7d4af02ee2394439d11a523bbcf095cf4747c2932007", - "sha256:93a784271881035ab4406a172edb0faecb6e7d00f4b53dc2f55919d6c9688595", - "sha256:94f8575fbdf81749008d980c17796097e645574a3b8c28ee313931068dad14fe", - "sha256:95451e6ce06c3e104556d73b559f5da6c34a069b6b62946d3ad66afcd51642ea", - "sha256:99c8a9ed30f4164bc4c14b37a90208836cbf50d4ce2a57c71d0f52c7fb4f7598", - "sha256:9a18d6f9359e45722c064c97464ec883eb0e0366d33eda61cb19a244bf222679", - "sha256:9cbf44c5cb4a7633d078788e1b56387e3d3cf2b8139a3be38040b22d6c3221c8", - "sha256:9ee33b875f0b390564c1fb7bc528abf18c8ee6073b201c6ae8524aca778e2d83", - "sha256:a0e317df055958a0c1e79e5d2aa5a5eaa4a6d05a20d4b0c9c3f48918139c9fc6", - "sha256:a2df6afe50dea8ae15fa34c9f824a3ee958d785fd5d089063d960bae1daa0a3f", - "sha256:a31de1613658308efdb21ada98cbc86a97c181aa050ba22a808120bb5be3ab94", - "sha256:a3d2bff8f37f8d0f96c7ec554d16945050d54462d6e95414babaa18bfafc7f51", - "sha256:a41bcf68efd19073376eb8cf948b8d9be0af26256403e512bb18f3966f1f9120", - "sha256:a82836cab5f197a0514235aaf7ffccdc886ccdaa2324bc0aafdd4ae898103039", - "sha256:a8d00f29b42f534cc8aa3931cfe773b13b23e561e10d2b26f27a8d309b0e82a1", - "sha256:aafe5dcfda86c8af00386d7781d4c2181b5011b7be3f2add5e99899ea925df05", - "sha256:ab5f043cb8a2d71c981c09c510da013bc79fd661f5c60139f00dd3c3cc4f2ffb", - "sha256:ac09d42f48f80c9ee1635b2fcaa819496a44502737660d3c0f2ade7526d29144", - "sha256:aecfed0b41aa72b7881712c65cf764e39ce2ec352324f5e0837c7048d9e6daaa", - "sha256:b2c6b50c7b0464165472b56b42d4c76a7b864597007d9c085e8b63e185cf4a7a", - "sha256:b35d13d549077713e4414f927cdc388d62e543987c572baee613bf82f11a4b99", - "sha256:b39cb32a6582750b6cc77bfb3c49c0f8760dc18dc96ec9fb55fbb0f04e08b928", - "sha256:b5405bb8f0e783a988172993cfc627e4d9d00432d6bbac65a923041edacf997d", - "sha256:baaf55442359053c7d62f6f8413a62adba3205119bcb6f49594894d8be47e5e3", - "sha256:bd654fad46d8d9e823afbb4f87c79160b5a374ed1ff5bde24e542e6ba8f41434", - "sha256:be61f6fff406ca40e3b1d84716fde398fc08bc63dd96d15f3a14230a0973ed86", - "sha256:bf49a3ae946a87083ef3a34c8f677ae4243f5b824bfc4c69672e72b3d6719d46", - "sha256:c4a80f77dc1acaaa61f0934176fccca7096d9b1ff08c8ba9cddf5ae034a24319", - "sha256:c75eb09e8d55bceb4367e83496ff8ef2bc7ea6960efb38e978e8073ea59ecb67", - "sha256:c7f8dc16c498ff06497c015642333219871effba93e4a2e8604a06264aca5c5c", - "sha256:c8aa34a5c864db1087d911a0b902d60d203ea3607d91f615acd3f3108ac32169", - "sha256:cbb0fef01f0c6b38cb0f39b1f78fc90b807e0e3c86a7ff3ce74ad77ce5c7880c", - "sha256:cde9a2ecd91668bcb7f077c4966d8ceddb60af01b52e6e3e2680e4cf00ad1a59", - "sha256:cff6d44cb13d39db2663a22b22305d10855efa0fa8015ddeacc40bc59b9d8107", - "sha256:d1009abedb49ae95b136a8904a3f71b342f849ffeced2d3747bf29caeda218c4", - "sha256:d38c1e8231722c4ce40d7593f28d92b5fc72f3e9774fe73d7e800ec32299f63a", - "sha256:d53834e23c015ee83a99377db6e5e37d8484f333edb03bd15b4bc312cc7254fb", - "sha256:d7504f2b476d21653e4d143f44a175f7f751cd41233525312696c76aa3dbb23f", - "sha256:dbf507e9ef5688bada447a24d68b4b58dd389ba93b7afc065a2ba892bea54769", - "sha256:dc52310451fc7c629e13c4e061cbe2dd01684d91f2f8ee2821b083c58bd72432", - "sha256:dd00607bffbf30250fe108065f07453ec124dbf223420f57f5e749b04295e090", - "sha256:dda608c88cf709b1d406bdfcd84d8d63cff7c9e577a403c6108ce8ce9dcc8764", - "sha256:debe9c4f41c32990771be5c22b56f810659f9ddf3d63f67abfdcaa2c6c9c5c1d", - "sha256:e09fd068c2e169a7070d83d3bde728a4d48de0549f975290be3c108c02e499b4", - "sha256:e0fd068364a6759bc794459f0a735ab151d11304346332489c7972bacbe9e72b", - "sha256:e4c53f8347cd4200f0d70a48ad059cabaf24f5adc6ba08622a23423bc7efa10d", - "sha256:e5723c01a56c5028c807c701aa66722916d2747ad737a046853f6c46f4875543", - "sha256:e7b0460976dc75cb87ad9cc1f9899a4b97751e7d4e77ab840fc9b6d377b8fd24", - "sha256:e9d9a4d06d3481eab79803beb4d9bd6f6a8e781ec078ac70d7ef2dcc29d1bea5", - "sha256:ead11956716a940c1abc816b7df3fa2b84d06eaed8832ca32f5c5e058c65506b", - "sha256:ed5f69ce7be7902e5c70ea19eb72d20abf7d725ab5d49777d696e32d4fc1811d", - "sha256:f2af5c81a1f124609d5f33507082fc3f739959d4719b56877ab1ee7e7b3d602b", - "sha256:f40e782d49630ad384db66d4d8b73ff4f1b8955dc12e26b09a3e3af064b3b9d6", - "sha256:f514f6474e04179d3d33175ed3f3e31434d3130d42ec153540d5b157deefd735", - "sha256:f69f57305656a4852f2a7203efc661d8c042e6cc67f7acd97d8667fb448a426e", - "sha256:fb1e8b8d66c278b21d13b0a7ca22c41dd757a7c209c6b12c313e445c31dd3b28", - "sha256:fb4948814a2a98e3912505f09c9e7493b1506226afb1f881825368d6fb776ee3", - "sha256:fda207c815b253e34f7e1909840fd14299567b1c0eb4908f8c2ce01a41265401", - "sha256:fe8f8f5e70e6dbdfca9882cd9deaac058729bcf323cf7a58660901e55c9c94f6", - "sha256:fffc45637bcd6538de8b85f51e3df3223e4ad89bccbfca0481c08c7fc8b7ed7d" + "sha256:0136d640dfa9b0523853e411430a99f8a91eca85774c6420285a33b755bc6de3", + "sha256:03dd38de09bc213e9a8b29761eec33ee1d5318dac0e49d8af36e4d27830e23a7", + "sha256:0a191bfdb30a79b98e5d175d75285f9fcb78bf0e46ba5efda042e1c72071a0de", + "sha256:0a66db89ea473abeac4b70523cafd94db3772380e565f9d28af7a179b7af71fa", + "sha256:0ae12ff2b805fa02c4dab838005caef735e39986322698c48588d3beacb65c62", + "sha256:0f12afda4eea8c8994a76d4df1875c765194f5fbe8a9d197929ea303caee29ec", + "sha256:10b2fd95332f0d716d5eee3c9fb2ce8eada19082de7fee83d32e37992fd75c26", + "sha256:126a2533570c554719ca40a1288fdee1700b6bc82e7131aa69fa85252d92e651", + "sha256:12b6bc4906e11f5e1a1cdcb12296e7afbd366c783cc8073403cd2fb74334e453", + "sha256:142c06c4d6a35ee3ec5da08499805e879cb3ca7c1fbfbecb0140fe72403818d6", + "sha256:14b79a30a93a3ce2e8832603fd0ab780ada281b0ba5110b519a634f2d7d7d1fc", + "sha256:17c9877a89fb6e2bca6f9087eb24cd7fb434653946ef5075e470d23d49b52287", + "sha256:192a866877a49993949ef1975864ad8728bea28ee810f6abe1a0729c2b500426", + "sha256:1ab7618921a93767387a4b83776f751588f5b5ae9bb5bc96620e2e2e00bca868", + "sha256:1e80dcf1446e1b080b1932b0d103c464a04112f5bc31f0f983ad418172063cde", + "sha256:1f51020b2eb8a003c84925638ec63c21a750a4bddd3a22ec8eac6a742dadf1b9", + "sha256:1fb2a01ba8cd9c5d2c5dc1ec35e0fc951d04b4f037541d4ac090c993ce58b3d7", + "sha256:2239a02249d9326655419e0168a28ca9008938eaab31dc29fc875c217927a6c0", + "sha256:23bf5b403c879a54964e0feac7285688e04bb220074878d737d331522da0a5bf", + "sha256:24ce942011a61953e7d313438038f4d32ff21387b775f58a957f7a07dd55ef95", + "sha256:25868beca8b6765f8f7d0e11fe6dd7c66dd4b0793b9500286d20cc92352126a5", + "sha256:287e99ff5aa4dc1c7630bfc683ded6f106d756c99dec432a2d7f197a784f51c6", + "sha256:29273edf1530e397bd07cb784db1fbe0d2590b77569f2e24679a9c0a2d763b94", + "sha256:2b49375d22299b0a834c2bca72f39aaecc270d96fb24c30424899676f487b22a", + "sha256:30eec96e8a91bd588ce897c9543f6d5d8d34b28fbcba28a4dedf20ebeae9fe57", + "sha256:319e070a01db9920fb63761843f96a104c8e2b9427266731810dc1e22595b17c", + "sha256:35dcbea443fafb3eece757ad4e514560ddeb6c34cfae1582c620d7b293d7feee", + "sha256:3f4d48a6112712973e676bd792121fee470e432d749177162d9949d5c9460a1b", + "sha256:3feb99222553a8cbedfa52c2f59dd84c3f50d5b582c728d522caf8d72769a54b", + "sha256:419f392a1da624877975709e3864dfe833af6cc7671b39318086d456e288380c", + "sha256:42a66563d8cc056ee32e6191e05097a7b2b3bc302e0bc3133daf8710eb18bd26", + "sha256:48796ea00a303961507dc6c8437c4b325a6fc3f95f7c36c71b91ea9a8150963c", + "sha256:4bd6340d20ae2c7ca719b87b426e808e90743b676d05d4c26c4fb5ca71f41184", + "sha256:4ca89e4e21854ed27ec753297dde84b16c9f8e53b14a4866fb44457d643c19f8", + "sha256:4d781294bb815ecb5ea57ff6bbf8038e0a31a95fdf3e1788f66e0dc100d64b58", + "sha256:4f1c91f5a5980a937ff8e238e98e6897e1ad74a4b1e2c0d68c73b5ffbb3f5c0b", + "sha256:564fdc7085d2245ab84f88882fdb1d6ac0723124bff6ded35bfb1c00f812630d", + "sha256:59ba3a6e1aa8cfe5adf4bd270fd965db21955401b7ca6f1696010c55ed4daec2", + "sha256:5df89f769cc8ff94c3d7e7603386fba309d25ce5240132d26c15baa8d0e96c4c", + "sha256:632da579b2d879f6bad20f2cfa35ded1efe2f4f77f8abb26a6234a5b236acd2f", + "sha256:65b5b2066651b7432d389e9799d979c703bcc6ef44266bb8153ef54e91e4aab3", + "sha256:664ec6a520b74a1df2810666eb67695fcb77fa663e6ea0a25aaf2e529cb24dfa", + "sha256:681c758b0490f9e96b78e5fa8e8dc6e648e9185bb6eaebe73183c33ea0c445f3", + "sha256:683e362b8ba453080f7489c66f4ea794e751c35b72e7eab3575ef784c2fbc7fb", + "sha256:68782fdb4027b8d1eee25ec35e9a6db05e863b899eb0310b3a33b6c3fef55707", + "sha256:6efaf45df6a849cef613a03a94c845647456662f85438c886bb67a9c027c8c2c", + "sha256:71f42c5b9a948c113bbdebfa544598321431d064ff959d32e99b1feb61d68345", + "sha256:72849d892954be4d09e569b8b831ac39ce58417fedc767d4308a0fe542018a40", + "sha256:72c34ac7ad4314c19362d5ce27626dcc8429bd30bbf8c179f4234078851f9492", + "sha256:734f6e5400352ac4254456003d462866c684703570929cff7a7bde015d0cb371", + "sha256:75baa6cf9b6d1c52f3e111a130e202fd8cf0a5b3a066c3f73d615e885092e4ec", + "sha256:77716e245c90f058466a05e6a465bb8600f767a8f4b18b4d40f3aff958e5f73c", + "sha256:77e5099b99b37f3cf79c246998ca9f7313a78054cd1809ec46bc1afad47e1c4c", + "sha256:783dd1467083f4d3f7722ad6a313f24c173e7571372738fcb7a6e6d1ba48df25", + "sha256:7a5c3115595995779ee21f2567035793911c3802a43c74f3fbb0314929ec67ac", + "sha256:7c88edaec8c349ad4c5ad4c486a3defcc4b80ceb2f074436ffa0a87caf5e76a6", + "sha256:7cb414a73e21a7ab58254926073f2930cb22f5b4314ea4260a687e2b3fd4dce3", + "sha256:7d42e7e3ca399555578b4d617e3a6ecf13371b3743a115995fa010c7bf341459", + "sha256:7d575b54cb3863ef9bc290ea4b009999d55dc237326131e4853cf33e888fee03", + "sha256:7e4de3ac4adbad3d0bc7c6f4360a7dbff5de2f15e3b723be3198074e17fd9c40", + "sha256:7efc9f082dfed77c316edffa9deb52888e1bc6789171887cc1f68e06d65465c8", + "sha256:80a063f8297fc796296f00f100be520f209b23dc98f93ce8eba6ee7122598209", + "sha256:80e47012e730da131c9f059c80936783f9659aae22dc31c03c0595590d11ed54", + "sha256:83d4a37e4b95da4d8bda930d6d35b75b4cdadbacbb4980cae290ea3100b5d51d", + "sha256:83e9f4a25085bd4b7214701a0794ff1f50fc633ffb8bdfebf07abdd81c2db126", + "sha256:85a18376073f8a39aa07be34f9fc77e2869aa72c55c441efdd2cf79a0407504d", + "sha256:87796fedc3ba97ec14fab55acb48584276e6c1e4c1e89c422bda62c838e754a9", + "sha256:882569ff613758cac762a457a5d72d6e211b28d4bcfea89d1d71ea942b02eac0", + "sha256:8ce4d6ccafb33d39bd78444612d14938ead674c25702ded2ee9c54a47735d225", + "sha256:8e7d98cdbb6d71e726f7d525952867096053d1f290dd4e3c50d7d313a136f414", + "sha256:8ee202350cf57abf0e9502a41601841019c25d3db7ff52d980aaf31446254059", + "sha256:8fb0eb4955adf0579001581f2f71a126e8781ba61bcd120f127b0401163c6c2d", + "sha256:90c30ed53546da833c700115c0064c22120d1b1560f474699fd31f22dd668233", + "sha256:9489e6abf47ba37f332075a91444c7cfedb03e6ce99fbb2f116bfe1ce810da3b", + "sha256:94d7aa6debf92a1dd14cb5280b083a764169a13cfb23a452111160274ed989f4", + "sha256:98d370568f393215d605304cdb77b3d5539bd192c75b623c7304c42c8d6d8273", + "sha256:9b1bdaae98bc016825dd3c9d8ee1832f829b3341f9cc6ebd1a1b0a7fef7367cc", + "sha256:9d693bf4bf534e9ba3ae2780cfd577f5135629f7b5ac653490859d0b77864865", + "sha256:9d6ed3d17bccce4c05343e1ca8da13bc5c02c812a4e7282ddd05e8769322d3fc", + "sha256:9e23c82b63cd7652fc24d33ed6cc17099d607aa3b4fc4ddc75e95062f3d82df4", + "sha256:a1daf47cd95a7c3a63456336bc5aaa8c86dd3a47d07ed3d0e76132ae4666a5a1", + "sha256:a1e32763e641a1566507d90a8d3b19bfc3cc04a9d4e5ae3e32189874ed4b58a3", + "sha256:a2059a2d891bd156bc5184e7ab7a56e78a84dfcfdeac8c501b552533ad1c36ee", + "sha256:a2ed0ba415ccdf08f14bf544cb78346d0f76086707ffee24921a2c84dbf1305a", + "sha256:a3faadac7d812ddac258feb57b9846b60c1b437c4f4b9ad42595c6f6fe4390df", + "sha256:a5877f2255aab518ebe528289037699201d5dc5f045f2396cb30aa02db22f57f", + "sha256:a78b50b4f7918a3de71105d5c0b93bbc57bb8339a4d03a9dfd449f9068e76f3d", + "sha256:a8c2b841478068440d8b733005d13a5ef535b9928cbc05f17182d410f32ba449", + "sha256:a9ca696eb02e5c02a8afd872ada510eba9b7fe6e68b9572c2e9a9b1941e31e2e", + "sha256:aa4ed3dd308548f9e707d9caaf005d2d7f8c1e7868f858dfeb47fe76e16b391d", + "sha256:ab2054c5531af2a9ba7b69b8ec91e4f884420e83a8c5e579b013084cb57e5e5d", + "sha256:abb1384477f5901d436b5d2e5465954de46ea6098f59163d243660b5c4461d35", + "sha256:acae6b45d1ace09b6ba3876da43b88366ef368f73b988c7f57e14231753d4420", + "sha256:acfa7e22aa6c6e7a5996a41d275bfa01efa7ea56ab890590280e9063e2cf5c1b", + "sha256:af4ea5b37403ef4e30f3927eaed540db942bde01d8d3ff083527c0704d1c9c68", + "sha256:b10dd0557ba422715b5206b3743192135a6022acca8baec51aa127d0a75db8fe", + "sha256:b13b88747769537f3d32e89e3a735da10c0a9e35d7322928c701b5f93d3afffd", + "sha256:b51c159a9794633f5e0db7ecec7b2b6e3734eca1f5d17dc989ff3552a43ff78b", + "sha256:b5402a340723fa7da00b5cff987ddab61276be6d11251ea71ae02bcac54890d8", + "sha256:b7abffdf37af1cec6a2ad69b827aa84320db5894791bc8ed932dc93fb274b7e9", + "sha256:b8075fe90bc08e40b8b8a1874fab42ee4c7b56af05c5886e9cc841397f916908", + "sha256:bc3ac7bf569f6b64dad04dd7808c7872dae8a97df657856eac05e9b7e3614a85", + "sha256:bd0912757081f89b107d6c00b2ff8a194401b0b87eadcf4481de2b865a8fd44f", + "sha256:bdc8d8b8c22e9e43ac68316b5e6cf083dec537f4ec213cb4aa967b583bc3fa64", + "sha256:be80550d9bfe83d9b62398a37081a90434e6df2d978ec345c3d2820de6beddab", + "sha256:c6f117789d22dce188e5754e8bc65b7e6ebf8cb73963b9fa761f672a5883769d", + "sha256:ca32926d7d77bcc8838425c4c95e040a3ace1cb7dfdae599013458dcda2607ca", + "sha256:cce0727fd5ac04d372fa9bbfde9febc2bcf209aadfcf0468e45dec72719895d1", + "sha256:d0f1489233a254bb3643d2f05de7d59019254d81daeca6b9162fe9edef57e0c7", + "sha256:d1c557dfd5e3db046053a0bdc72261ade790ebe8e2c7a41b36b0ca1f14cb95f3", + "sha256:d21f0fa80a02d05299207eeaafef345d812ace96d5306e4ef265e1d419a615fa", + "sha256:d45673badd08456d0340e9364eddafe1c53a9d2896424294de4d7dd71ad3ee57", + "sha256:d5add7b4ca7afeea91d52e4d4e4db3b1fe9885b71f07054560d8c4296b7441a2", + "sha256:d5f90e44653c4e0f78501ed9bb7d3fce835a8d62b7c6ed0cb16557534087e743", + "sha256:d7306dee25b8a0e737363f347362b875094b4dc4e367311470656ae420fdbf8e", + "sha256:dbcef5a9119ef653653132cccaf999b30a0af6f33bb0a4ba80bec30056868487", + "sha256:def538065f9e4d4cf1ae164bd59aba00dfa84f03923e0de4c3788f252d6bcd17", + "sha256:df23df54b5114a17c2d0ef192433e2e5a9f0c5178c32375e90b7cfc965f349d0", + "sha256:dfbf531053a0935f2e871bcd4753f90313688772ff8c017f5ea402e315a78c1f", + "sha256:e029648f9c951db30e98a7d7ec90835db88ec4b32820efe2a9bdc2287e032eb6", + "sha256:e07595c7d6f4db270ceede356a1bd1c07a34f1c26f958d1ed0cd7b48e0d2bba3", + "sha256:e12c538e00e7c1b286a07061046b90e8124e6a9793efae2c70db6a4aad07faad", + "sha256:e546fe1d4a93ebc2910f0d768baff19faa09843ab3f2036a67ed6e69fae4419d", + "sha256:e5637ca8d0bd7fb72648a6c7934af4baaccb697657f7438c9d264fc2abb8b0b1", + "sha256:e636b64d24fd9c38053c5e389a1174c66361fa49dcfd220f4dd35b4abde7cb89", + "sha256:e7011b8fb8c4054bf0c12e5edc6cd83778b0028e99ce59b18586ed036f92cfdc", + "sha256:e80f557716fd765439577131e526b8942ffc2c07bdbc5e39fa62f660ba1e963f", + "sha256:e92b6bcc741b86d67606c40d3cb9c7cc8e6c737f81e31f4a94efc204456c92e3", + "sha256:eb96ed1ae6c7d072d60840c0434aef07a2df611812810807fbc54263a6053e9a", + "sha256:eda19ea5ee88742f47a2340816e6f2d40b53bed3ab5b69794769f36af9f35bb4", + "sha256:ef74070ac553c59eb4f04258722066d6c6135b7baa03b2e9f2da65c096e96d98", + "sha256:efb01a106f971cb3752856bca2318bbdf7f01bd8823779c461586cbe5ffd5258", + "sha256:f074e8d4aa0a5798920ddb6de3d08b228c614ff3724c3e8bd7577f4bafea867b", + "sha256:f38a70074041d3b7e138e452799f5174198bae5bd5ab2000917badf403908c5f", + "sha256:f41753a76f4f63927d03a0d8ba8f5ce0f2083bec29a8cfaccc55371b1564b96b", + "sha256:f53dcd26694f148f738edc052b5a69234833e739f10f4c3287bdfd8ec0f7b326", + "sha256:f61964f235a43738bfac50da46fc4254943a7eea3051aeb0b6fc7c992c29fadc", + "sha256:fe01645169a2112aa1d4ebc3e4c5f029c5c8f97adfc32e5d37c993b39a994d75" ], "markers": "python_version >= '3.10'", - "version": "==1.23.0" + "version": "==1.25.1" }, "zipp": { "hashes": [ - "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e", - "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166" + "sha256:25ad4e16390cd314347dd8f1de67a2ac538ae658ed4ab9db16029c07c188e97f", + "sha256:4cb57381f544315db7688e976e922a2b18cdb513d21cc194eb42232ba2a3e602" ], - "markers": "python_version >= '3.9'", - "version": "==3.23.0" + "markers": "python_version >= '3.10'", + "version": "==4.1.0" }, "zope.event": { "hashes": [ - "sha256:0ca78b6391b694272b23ec1335c0294cc471065ed10f7f606858fc54566c25a0", - "sha256:6052a3e0cb8565d3d4ef1a3a7809336ac519bc4fe38398cb8d466db09adef4f0" + "sha256:5e755153ac4faf64c10a4b6dd3307680166a3edf65b38df22df592610f8fa874", + "sha256:b97d5d6327067ee6b9dfcbdf606ade9ade70991e19c162e808ea39e5fcf0f8d3" ], "markers": "python_version >= '3.10'", - "version": "==6.1" + "version": "==6.2" }, "zope.interface": { "hashes": [ - "sha256:0009d2d3c02ea783045d7804da4fd016245e5c5de31a86cebba66dd6914d59a2", - "sha256:05a0e42d6d830f547e114de2e7cd15750dc6c0c78f8138e6c5035e51ddfff37c", - "sha256:0723507127f8269b8f3f22663168f717e9c9742107d1b6c9f419df561b71aa6d", - "sha256:16c69da19a06566664ddd4785f37cad5693a51d48df1515d264c20d005d322e2", - "sha256:2499de92e8275d0dd68f84425b3e19e9268cd1fa8507997900fa4175f157733c", - "sha256:2bf9cf275468bafa3c72688aad8cfcbe3d28ee792baf0b228a1b2d93bd1d541a", - "sha256:34f877d1d3bb7565c494ed93828fa6417641ca26faf6e8f044e0d0d500807028", - "sha256:3bf73a910bb27344def2d301a03329c559a79b308e1e584686b74171d736be4e", - "sha256:46c7e4e8cbc698398a67e56ca985d19cb92365b4aafbeb6a712e8c101090f4cb", - "sha256:532367553e4420c80c0fc0cabcc2c74080d495573706f66723edee6eae53361d", - "sha256:561ce42390bee90bae51cf1c012902a8033b2aaefbd0deed81e877562a116d48", - "sha256:6068322004a0158c80dfd4708dfb103a899635408c67c3b10e9acec4dbacefec", - "sha256:624b6787fc7c3e45fa401984f6add2c736b70a7506518c3b537ffaacc4b29d4c", - "sha256:6f4b4dfcfdfaa9177a600bb31cebf711fdb8c8e9ed84f14c61c420c6aa398489", - "sha256:788c293f3165964ec6527b2d861072c68eef53425213f36d3893ebee89a89623", - "sha256:845d14e580220ae4544bd4d7eb800f0b6034fe5585fc2536806e0a26c2ee6640", - "sha256:8f094bfb49179ec5dc9981cb769af1275702bd64720ef94874d9e34da1390d4c", - "sha256:9a4e785097e741a1c953b3970ce28f2823bd63c00adc5d276f2981dd66c96c15", - "sha256:9b05a919fdb0ed6ea942e5a7800e09a8b6cdae6f98fee1bef1c9d1a3fc43aaa0", - "sha256:a1ef4b43659e1348f35f38e7d1a6bbc1682efde239761f335ffc7e31e798b65b", - "sha256:a87fc7517f825a97ff4a4ca4c8a950593c59e0f8e7bfe1b6f898a38d5ba9f9cf", - "sha256:aae807efc7bd26302eb2fea05cd6de7d59269ed6ae23a6de1ee47add6de99b8c", - "sha256:afb20c371a601d261b4f6edb53c3c418c249db1a9717b0baafc9a9bb39ba1224", - "sha256:bc9ded9e97a0ed17731d479596ed1071e53b18e6fdb2fc33af1e43f5fd2d3aaa", - "sha256:c31acfa3d7cde48bec45701b0e1f4698daffc378f559bfb296837d8c834732f6", - "sha256:c65ade7ea85516e428651048489f5e689e695c79188761de8c622594d1e13322", - "sha256:ccc62b5712dd7bd64cfba3ee63089fb11e840f5914b990033beeae3b2180b6cb", - "sha256:ccf52f7d44d669203c2096c1a0c2c15d52e36b2e7a9413df50f48392c7d4d080", - "sha256:d2bb8e7364e18f083bf6744ccf30433b2a5f236c39c95df8514e3c13007098ce", - "sha256:dfc4f44e8de2ff4eba20af4f0a3ca42d3c43ab24a08e49ccd8558b7a4185b466", - "sha256:f777e68c76208503609c83ca021a6864902b646530a1a39abb9ed310d1100664" + "sha256:00fd6a6da085beb90cdcdce6ed6e6973edf338d1ea63a807e213b1eb7013833d", + "sha256:09522cdc6a77376bc36988b531db3b568c8cb0b6ca7286d8316aab283888770f", + "sha256:105da41198a1990b18d566bd30656a19064d4c313e4c0dd8f0dd9714026e47f1", + "sha256:192bb756a8f62395b4fe47cbb853c171f20389d5226fbfa97128bb2f76abad8d", + "sha256:23ae710094fdcfcf715dae7054cd5abfefa4a527c5853d7b76ebb2541499c41a", + "sha256:27e6de8e593736210d2a9f1bbf766a5653aa4819c184f864ab9d1f8bd3590a60", + "sha256:28b68c24131545c1d13fd2178bbd065e67f09db885d8426adf1fbdf2b6b66372", + "sha256:3e0383361da2793ea332e2d12b753a32ac57b3b89c8c3a9c6dd04374ae142c0f", + "sha256:3f7f6da49911ffe75ae3f7a9a45619f205420cc6578aff02f8ca29ed1de10f14", + "sha256:42fb95008784a3b50c4b79e4488845d1950c57eef17ebc9c53a680084fb93da2", + "sha256:449727fc79f0b1317ec190632e13699b732d3f4704ea90c8e1339bb78e451bee", + "sha256:47030c08e39d690299e02973ac845d0f534121b3618efa9ce9599a512a1c97fa", + "sha256:5dbe120cfcfc8e6aed418f340c3d1ad4072253e17176503e363ddac27fcb2ac6", + "sha256:5ef166337880b0e78138bbd32fcbc5ab1da3337febe8d2a247f3690bcae3ede5", + "sha256:5fbd9deb0477aea769b7d83a4d953d77ef38972d5eddd5b922b614ee708b2104", + "sha256:6246f7a4b196bd054469f4fd4ffdac307974061f0d2b1ef4da87ddff13a7f885", + "sha256:64ed939d725876071823505b1c90074a86847a6e9be8617cec7ba759e0b86a7e", + "sha256:66ab8c5d8820aa378968c16b7a3cb051aca342eafa649c9a363182f572d75ccb", + "sha256:6df4bd16923d247c34e12dc394dab20d99d96aa2e15a6b163c2dda1dd582fff6", + "sha256:780a66db884c0e2b0e6b34b4900f86916945a7c03d3be40ec845b051fcc052cd", + "sha256:81793c9b12816ac7f8b71b366be36b7025fcf7205ec4a236642b15a82cb027ef", + "sha256:826f99c38f4bfcf7165885a0c59f03c6c25e0df8cdb0544f882cda61616fe845", + "sha256:919510e0d470c189cb84164b953f81e8a513aa2593fdc9e4982340838cd1099b", + "sha256:9217b1123f6aeec9ddf1789bffd83da3123546d551c164a99f862a5d1f5ac0f8", + "sha256:a2c5963a26e1fe47bdb3494ba2aa91904c7898873af400dc3bdcaa808a57783a", + "sha256:a38b221cc649a2daacaff9d629a2ba9c4a8967669d253f9a6a597f46d46732f0", + "sha256:a43e669d68fd8c10fe315812f7e1d262c6c00e9667f29f799a3771f9a3b5b41d", + "sha256:a84ac0010f054f3516710804a0c22026b4b0d30085d7666cfc2f30545775bf99", + "sha256:a91eb220d9ae6aa6d746d6dac5b4db35b1417903301b3315ba3275b19570be0b", + "sha256:add6e226c6568de6d0ea9f6abe6353072387afcf5f817610ea266495d0c1ee72", + "sha256:b08808d1196810f76928ad13d37dae18d92b1c9485c113628f41dbd6351413de", + "sha256:b40ef9b4873afb5d0dec02b8d2dfde1cf18c72337b60c99cb735961e0bac05c0", + "sha256:c2bf932006229788d6bb41963dfc0345cba6ee24141a39316bd52a283a7d115f", + "sha256:d97c96c79c389d1031c86f8e797b94db4fe647dfbfebdbe48247c1899dc930bb", + "sha256:dd25d6da3b3c8216080a0eefb3c01719913782690427fb9ba2ddad98ed8970f4", + "sha256:e36adea8ab93eb4d2076a47d5f4c7d7e1267eb9a4e33202da7ea71439a3bcaef", + "sha256:ebb513c9e47702525897148e38271f7b6bf12c61bd084cdddfd0e03b542f8100", + "sha256:ec5a5c01a54fc06b69da71164c9bba8cc71fde79bdd1b835bb734f96bca693f2", + "sha256:edf1bd7ed576319241b2b314eaa549cee3e3e0f81f46911086b387d03a303ad3", + "sha256:ef15a2f6258f809334a19c1fcce64648813066ceebe3f3f6077871483fd0f50d", + "sha256:fcc86414ee0e6b77416de81b8dead5900719b3f71b7875d8d1f87ae4e166a11f" ], "markers": "python_version >= '3.10'", - "version": "==8.2" + "version": "==8.6" } }, "develop": { @@ -2313,11 +2461,11 @@ }, "certifi": { "hashes": [ - "sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa", - "sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7" + "sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775", + "sha256:741e2c3b351ddf169a738da9f2c048608ff7f2c5cc02f1ebc6b118bb090d5d55" ], "markers": "python_version >= '3.7'", - "version": "==2026.2.25" + "version": "==2026.7.22" }, "cfgv": { "hashes": [ @@ -2329,262 +2477,320 @@ }, "charset-normalizer": { "hashes": [ - "sha256:06a7e86163334edfc5d20fe104db92fcd666e5a5df0977cb5680a506fe26cc8e", - "sha256:0c173ce3a681f309f31b87125fecec7a5d1347261ea11ebbb856fa6006b23c8c", - "sha256:0e28d62a8fc7a1fa411c43bd65e346f3bce9716dc51b897fbe930c5987b402d5", - "sha256:0e901eb1049fdb80f5bd11ed5ea1e498ec423102f7a9b9e4645d5b8204ff2815", - "sha256:11afb56037cbc4b1555a34dd69151e8e069bee82e613a73bef6e714ce733585f", - "sha256:150b8ce8e830eb7ccb029ec9ca36022f756986aaaa7956aad6d9ec90089338c0", - "sha256:172985e4ff804a7ad08eebec0a1640ece87ba5041d565fff23c8f99c1f389484", - "sha256:197c1a244a274bb016dd8b79204850144ef77fe81c5b797dc389327adb552407", - "sha256:1ae6b62897110aa7c79ea2f5dd38d1abca6db663687c0b1ad9aed6f6bae3d9d6", - "sha256:1cf0a70018692f85172348fe06d3a4b63f94ecb055e13a00c644d368eb82e5b8", - "sha256:1ed80ff870ca6de33f4d953fda4d55654b9a2b340ff39ab32fa3adbcd718f264", - "sha256:22c6f0c2fbc31e76c3b8a86fba1a56eda6166e238c29cdd3d14befdb4a4e4815", - "sha256:231d4da14bcd9301310faf492051bee27df11f2bc7549bc0bb41fef11b82daa2", - "sha256:259695e2ccc253feb2a016303543d691825e920917e31f894ca1a687982b1de4", - "sha256:2a24157fa36980478dd1770b585c0f30d19e18f4fb0c47c13aa568f871718579", - "sha256:2b1a63e8224e401cafe7739f77efd3f9e7f5f2026bda4aead8e59afab537784f", - "sha256:2bd9d128ef93637a5d7a6af25363cf5dec3fa21cf80e68055aad627f280e8afa", - "sha256:2e1d8ca8611099001949d1cdfaefc510cf0f212484fe7c565f735b68c78c3c95", - "sha256:2ef7fedc7a6ecbe99969cd09632516738a97eeb8bd7258bf8a0f23114c057dab", - "sha256:2f7fdd9b6e6c529d6a2501a2d36b240109e78a8ceaef5687cfcfa2bbe671d297", - "sha256:30f445ae60aad5e1f8bdbb3108e39f6fbc09f4ea16c815c66578878325f8f15a", - "sha256:31215157227939b4fb3d740cd23fe27be0439afef67b785a1eb78a3ae69cba9e", - "sha256:34315ff4fc374b285ad7f4a0bf7dcbfe769e1b104230d40f49f700d4ab6bbd84", - "sha256:3516bbb8d42169de9e61b8520cbeeeb716f12f4ecfe3fd30a9919aa16c806ca8", - "sha256:3778fd7d7cd04ae8f54651f4a7a0bd6e39a0cf20f801720a4c21d80e9b7ad6b0", - "sha256:39f5068d35621da2881271e5c3205125cc456f54e9030d3f723288c873a71bf9", - "sha256:404a1e552cf5b675a87f0651f8b79f5f1e6fd100ee88dc612f89aa16abd4486f", - "sha256:419a9d91bd238052642a51938af8ac05da5b3343becde08d5cdeab9046df9ee1", - "sha256:423fb7e748a08f854a08a222b983f4df1912b1daedce51a72bd24fe8f26a1843", - "sha256:4482481cb0572180b6fd976a4d5c72a30263e98564da68b86ec91f0fe35e8565", - "sha256:461598cd852bfa5a61b09cae2b1c02e2efcd166ee5516e243d540ac24bfa68a7", - "sha256:47955475ac79cc504ef2704b192364e51d0d473ad452caedd0002605f780101c", - "sha256:48696db7f18afb80a068821504296eb0787d9ce239b91ca15059d1d3eaacf13b", - "sha256:4be9f4830ba8741527693848403e2c457c16e499100963ec711b1c6f2049b7c7", - "sha256:4d1d02209e06550bdaef34af58e041ad71b88e624f5d825519da3a3308e22687", - "sha256:4f41da960b196ea355357285ad1316a00099f22d0929fe168343b99b254729c9", - "sha256:517ad0e93394ac532745129ceabdf2696b609ec9f87863d337140317ebce1c14", - "sha256:51fb3c322c81d20567019778cb5a4a6f2dc1c200b886bc0d636238e364848c89", - "sha256:5273b9f0b5835ff0350c0828faea623c68bfa65b792720c453e22b25cc72930f", - "sha256:530d548084c4a9f7a16ed4a294d459b4f229db50df689bfe92027452452943a0", - "sha256:530e8cebeea0d76bdcf93357aa5e41336f48c3dc709ac52da2bb167c5b8271d9", - "sha256:54fae94be3d75f3e573c9a1b5402dc593de19377013c9a0e4285e3d402dd3a2a", - "sha256:572d7c822caf521f0525ba1bce1a622a0b85cf47ffbdae6c9c19e3b5ac3c4389", - "sha256:58c948d0d086229efc484fe2f30c2d382c86720f55cd9bc33591774348ad44e0", - "sha256:5d11595abf8dd942a77883a39d81433739b287b6aa71620f15164f8096221b30", - "sha256:5f8ddd609f9e1af8c7bd6e2aca279c931aefecd148a14402d4e368f3171769fd", - "sha256:5feb91325bbceade6afab43eb3b508c63ee53579fe896c77137ded51c6b6958e", - "sha256:60c74963d8350241a79cb8feea80e54d518f72c26db618862a8f53e5023deaf9", - "sha256:613f19aa6e082cf96e17e3ffd89383343d0d589abda756b7764cf78361fd41dc", - "sha256:659a1e1b500fac8f2779dd9e1570464e012f43e580371470b45277a27baa7532", - "sha256:695f5c2823691a25f17bc5d5ffe79fa90972cc34b002ac6c843bb8a1720e950d", - "sha256:69dd852c2f0ad631b8b60cfbe25a28c0058a894de5abb566619c205ce0550eae", - "sha256:6cceb5473417d28edd20c6c984ab6fee6c6267d38d906823ebfe20b03d607dc2", - "sha256:71be7e0e01753a89cf024abf7ecb6bca2c81738ead80d43004d9b5e3f1244e64", - "sha256:74119174722c4349af9708993118581686f343adc1c8c9c007d59be90d077f3f", - "sha256:74a2e659c7ecbc73562e2a15e05039f1e22c75b7c7618b4b574a3ea9118d1557", - "sha256:7504e9b7dc05f99a9bbb4525c67a2c155073b44d720470a148b34166a69c054e", - "sha256:79090741d842f564b1b2827c0b82d846405b744d31e84f18d7a7b41c20e473ff", - "sha256:7a6967aaf043bceabab5412ed6bd6bd26603dae84d5cb75bf8d9a74a4959d398", - "sha256:7bda6eebafd42133efdca535b04ccb338ab29467b3f7bf79569883676fc628db", - "sha256:7edbed096e4a4798710ed6bc75dcaa2a21b68b6c356553ac4823c3658d53743a", - "sha256:7f9019c9cb613f084481bd6a100b12e1547cf2efe362d873c2e31e4035a6fa43", - "sha256:802168e03fba8bbc5ce0d866d589e4b1ca751d06edee69f7f3a19c5a9fe6b597", - "sha256:80d0a5615143c0b3225e5e3ef22c8d5d51f3f72ce0ea6fb84c943546c7b25b6c", - "sha256:82060f995ab5003a2d6e0f4ad29065b7672b6593c8c63559beefe5b443242c3e", - "sha256:836ab36280f21fc1a03c99cd05c6b7af70d2697e374c7af0b61ed271401a72a2", - "sha256:8761ac29b6c81574724322a554605608a9960769ea83d2c73e396f3df896ad54", - "sha256:87725cfb1a4f1f8c2fc9890ae2f42094120f4b44db9360be5d99a4c6b0e03a9e", - "sha256:899d28f422116b08be5118ef350c292b36fc15ec2daeb9ea987c89281c7bb5c4", - "sha256:8bc5f0687d796c05b1e28ab0d38a50e6309906ee09375dd3aff6a9c09dd6e8f4", - "sha256:8bea55c4eef25b0b19a0337dc4e3f9a15b00d569c77211fa8cde38684f234fb7", - "sha256:8e5a94886bedca0f9b78fecd6afb6629142fd2605aa70a125d49f4edc6037ee6", - "sha256:90ca27cd8da8118b18a52d5f547859cc1f8354a00cd1e8e5120df3e30d6279e5", - "sha256:92734d4d8d187a354a556626c221cd1a892a4e0802ccb2af432a1d85ec012194", - "sha256:947cf925bc916d90adba35a64c82aace04fa39b46b52d4630ece166655905a69", - "sha256:95b52c68d64c1878818687a473a10547b3292e82b6f6fe483808fb1468e2f52f", - "sha256:97d0235baafca5f2b09cf332cc275f021e694e8362c6bb9c96fc9a0eb74fc316", - "sha256:9ca4c0b502ab399ef89248a2c84c54954f77a070f28e546a85e91da627d1301e", - "sha256:9cc4fc6c196d6a8b76629a70ddfcd4635a6898756e2d9cac5565cf0654605d73", - "sha256:9cc6e6d9e571d2f863fa77700701dae73ed5f78881efc8b3f9a4398772ff53e8", - "sha256:a056d1ad2633548ca18ffa2f85c202cfb48b68615129143915b8dc72a806a923", - "sha256:a26611d9987b230566f24a0a125f17fe0de6a6aff9f25c9f564aaa2721a5fb88", - "sha256:a4474d924a47185a06411e0064b803c68be044be2d60e50e8bddcc2649957c1f", - "sha256:a4ea868bc28109052790eb2b52a9ab33f3aa7adc02f96673526ff47419490e21", - "sha256:a9e68c9d88823b274cf1e72f28cb5dc89c990edf430b0bfd3e2fb0785bfeabf4", - "sha256:aa9cccf4a44b9b62d8ba8b4dd06c649ba683e4bf04eea606d2e94cfc2d6ff4d6", - "sha256:ab30e5e3e706e3063bc6de96b118688cb10396b70bb9864a430f67df98c61ecc", - "sha256:ac2393c73378fea4e52aa56285a3d64be50f1a12395afef9cce47772f60334c2", - "sha256:ad8faf8df23f0378c6d527d8b0b15ea4a2e23c89376877c598c4870d1b2c7866", - "sha256:b35b200d6a71b9839a46b9b7fff66b6638bb52fc9658aa58796b0326595d3021", - "sha256:b3694e3f87f8ac7ce279d4355645b3c878d24d1424581b46282f24b92f5a4ae2", - "sha256:b4ff1d35e8c5bd078be89349b6f3a845128e685e751b6ea1169cf2160b344c4d", - "sha256:bbc8c8650c6e51041ad1be191742b8b421d05bbd3410f43fa2a00c8db87678e8", - "sha256:bc72863f4d9aba2e8fd9085e63548a324ba706d2ea2c83b260da08a59b9482de", - "sha256:bf625105bb9eef28a56a943fec8c8a98aeb80e7d7db99bd3c388137e6eb2d237", - "sha256:c2274ca724536f173122f36c98ce188fd24ce3dad886ec2b7af859518ce008a4", - "sha256:c45a03a4c69820a399f1dda9e1d8fbf3562eda46e7720458180302021b08f778", - "sha256:c8ae56368f8cc97c7e40a7ee18e1cedaf8e780cd8bc5ed5ac8b81f238614facb", - "sha256:c907cdc8109f6c619e6254212e794d6548373cc40e1ec75e6e3823d9135d29cc", - "sha256:ca0276464d148c72defa8bb4390cce01b4a0e425f3b50d1435aa6d7a18107602", - "sha256:cd5e2801c89992ed8c0a3f0293ae83c159a60d9a5d685005383ef4caca77f2c4", - "sha256:d08ec48f0a1c48d75d0356cea971921848fb620fdeba805b28f937e90691209f", - "sha256:d1a2ee9c1499fc8f86f4521f27a973c914b211ffa87322f4ee33bb35392da2c5", - "sha256:d5f5d1e9def3405f60e3ca8232d56f35c98fb7bf581efcc60051ebf53cb8b611", - "sha256:d60377dce4511655582e300dc1e5a5f24ba0cb229005a1d5c8d0cb72bb758ab8", - "sha256:d73beaac5e90173ac3deb9928a74763a6d230f494e4bfb422c217a0ad8e629bf", - "sha256:d7de2637729c67d67cf87614b566626057e95c303bc0a55ffe391f5205e7003d", - "sha256:dad6e0f2e481fffdcf776d10ebee25e0ef89f16d691f1e5dee4b586375fdc64b", - "sha256:dda86aba335c902b6149a02a55b38e96287157e609200811837678214ba2b1db", - "sha256:df01808ee470038c3f8dc4f48620df7225c49c2d6639e38f96e6d6ac6e6f7b0e", - "sha256:e1f6e2f00a6b8edb562826e4632e26d063ac10307e80f7461f7de3ad8ef3f077", - "sha256:e25369dc110d58ddf29b949377a93e0716d72a24f62bad72b2b39f155949c1fd", - "sha256:e3c701e954abf6fc03a49f7c579cc80c2c6cc52525340ca3186c41d3f33482ef", - "sha256:e5bcc1a1ae744e0bb59641171ae53743760130600da8db48cbb6e4918e186e4e", - "sha256:e68c14b04827dd76dcbd1aeea9e604e3e4b78322d8faf2f8132c7138efa340a8", - "sha256:e8aeb10fcbe92767f0fa69ad5a72deca50d0dca07fbde97848997d778a50c9fe", - "sha256:e985a16ff513596f217cee86c21371b8cd011c0f6f056d0920aa2d926c544058", - "sha256:ecbbd45615a6885fe3240eb9db73b9e62518b611850fdf8ab08bd56de7ad2b17", - "sha256:ee4ec14bc1680d6b0afab9aea2ef27e26d2024f18b24a2d7155a52b60da7e833", - "sha256:ef5960d965e67165d75b7c7ffc60a83ec5abfc5c11b764ec13ea54fbef8b4421", - "sha256:f0cdaecd4c953bfae0b6bb64910aaaca5a424ad9c72d85cb88417bb9814f7550", - "sha256:f1ce721c8a7dfec21fcbdfe04e8f68174183cf4e8188e0645e92aa23985c57ff", - "sha256:f50498891691e0864dc3da965f340fada0771f6142a378083dc4608f4ea513e2", - "sha256:f5ea69428fa1b49573eef0cc44a1d43bebd45ad0c611eb7d7eac760c7ae771bc", - "sha256:f61aa92e4aad0be58eb6eb4e0c21acf32cf8065f4b2cae5665da756c4ceef982", - "sha256:f6e4333fb15c83f7d1482a76d45a0818897b3d33f00efd215528ff7c51b8e35d", - "sha256:f820f24b09e3e779fe84c3c456cb4108a7aa639b0d1f02c28046e11bfcd088ed", - "sha256:f98059e4fcd3e3e4e2d632b7cf81c2faae96c43c60b569e9c621468082f1d104", - "sha256:fcce033e4021347d80ed9c66dcf1e7b1546319834b74445f561d2e2221de5659" + "sha256:01077390b03f7988f11d700a2194e69b119741a86b1a638b1db88891e3eced8e", + "sha256:01b0c0d2262a9e28e8484a278c7e1b5d650e3ac8cf2683d2967e25899f208bdf", + "sha256:04851f73ae72b8413dddadb16a49dfee95263553741fd42d546f7d66907e6be5", + "sha256:0521c5665880b33d603717defa76c094048900010897909952397feb3039da56", + "sha256:0774bf9bf620249fee3e0b8b9fd3065de213be30f3aa94ce2494b3b638949e26", + "sha256:0891b9d3903c5571c03771ca669a4b0ec5618ca722a5c957d3d29cd4e5062848", + "sha256:0c951d5e6dd9c2ff60609476752bee49da4206adde960ebc247766937f72e718", + "sha256:0fed1d06615f022ee3b13caf5e8b180cfea32bb2c5aded8a9d44277afc040f93", + "sha256:114e4d0c92d618409ed82a99e22b5c5e768fe995f2973f78265f4524f49d4640", + "sha256:11912e4bb14baae7c5d8791aa55ba0a3a03ec6729073307b0f57270abaa713d3", + "sha256:11a4d68a6ecda3292cb1e50239e111543ba5d709bb62a6b4ea1afcfa729d8875", + "sha256:124fbf1a8ff966d87ae05bb8bd45a71f966055ed8bba320d0c7cf450bc5f4d0e", + "sha256:1461ac396c4fdb983a675f20aa555624f0ee18ac83d832b9244ffff3d8055275", + "sha256:1503bccbeb36d5527790c3930327704c39af22de3112f1b1666a9f3ce15ee204", + "sha256:15bb4005af6320d259dc7593ca84a38d7fe06a421dbcf7b910ae23979101e787", + "sha256:15c44f7edfd477b06f517a5cc317fc1707edb9de2c865f43d4b6513907473234", + "sha256:16fa0eccf81304b79c5cd87f9271c3b85dd9dd99245e4422ae9c0dd45e0f99d3", + "sha256:183b88127acdb4fabe59d951ab424faf1af7b63cdbb5f776186c1ea2ffcaed98", + "sha256:195c26fb65950f8fce54e26349852b7bdd7c5f120aeefbcc440b8a20faaed4a3", + "sha256:1afb975bd5d68d5ce9f6b6d44fdf2f7e34b895a35e95708a7a91b20a3b51d187", + "sha256:1b4cbc7c3491ccb4aa17fcd8165649d01cf39f76de1696da8631b5f71b85401d", + "sha256:1bc0baf5ef96b6ede57d47f4b8fe4d9d84019c3bfcbeb20a41edc6a6ee341f1f", + "sha256:1c50fe28bbc2ced33386f298650d91218076c05420e6cbd790b913adc41659e7", + "sha256:1db38f4c5496827c1a501846d64d14c3b80c7e6714e406cd7dc36a9899fa1011", + "sha256:211d5a3eb6af8f513b8d4ca19a8c1b7accab1b5f0d3175f9826b03c1a920dc1f", + "sha256:23851fb4e1b85ed3f6c2a27b777cdfe2e19fb5b38429a8faf38c7542b7665869", + "sha256:254eb48b9fa5ee9898a3c445825a1f340fe53712a098904b39b0bddba8ea3cb1", + "sha256:2625388c6c754520c37abaf3b41eb34d1cc4a373f457898f08606c8e362b891d", + "sha256:281cb91036248400f4cc957495cccd44c275c2e0c5854f7e45ac5cf7dc193847", + "sha256:28a15fdad492a99b6eccfaaed66ef3f74050680545ea61ec8b2f4c538f1f1320", + "sha256:28b4f0d66fb834ff90f28209ac7bce77868c45d8c93e26f906709d9b7c2e1af9", + "sha256:2a925889534b3748302dae5dead07cc13480de1dac3aea80a941b729b471ef93", + "sha256:2b7b3bbfb4fe8ef40600792d762fbaa9057559f9d3fad209525b7a22b99e91fd", + "sha256:2c9ad19a6cfcd5ea5c0d41161d22f9df1dcc277e9bef2751391334546a314c00", + "sha256:2cc961b171b3f3440f410489ab3573e86aea8736134ebbb40ea1338b7f0831bc", + "sha256:2ce45c6627b22c47e390bc91a41c3d13032192e699fa0bea96e9671b373d69b0", + "sha256:2e06a3a98f916dd41d27f3105e02e7a40181c98c94b9158733d03a6f80506c09", + "sha256:304d5463e65a35d7bb0850550e0780395395f6fcf452f04db7d5ca7cecc425ac", + "sha256:304d8e4d493af723536393eee0c689eb7813f4a474c8b479dee63f1fdd98f621", + "sha256:30fcd120b732aa79317f08dee04d7de0847822e4cf7ee0e9f445bb958832252c", + "sha256:31f3930700408d211f13378ccbe1c40845d8da54bd0681fac3a9b5aae81c7aa8", + "sha256:34276fd796040bf0993ab33a369aa572e6979c7aab225a88893667ad8eac8f7a", + "sha256:355ad8011081dec5412240c087a9a0c9d4d5039f3ed11a3f13e18c2b29b56c51", + "sha256:38a873987f3be698494da8b2e3085e29da02da7b633dce73e79c699a113d7bf0", + "sha256:39de2a259fc954455c57274dc94c79d5842774e1247a016aff30bc0efed0f4ef", + "sha256:3d14b50de6bf4d0edf857a9386836846f982b8f524e188e2e68b96d702bcf4aa", + "sha256:3d21b8b13c7592db2ac5e544a6d83187b995257472b0c9e8351b6d507ae37ed6", + "sha256:3d31298449090ab8d47b7b1b2a555ff73cac7ed438a08b7ac160980c7ebed649", + "sha256:3ddacd27458c45bdacd6bd6db644bfb730efbf9e830310186e3045c9c5be8fb2", + "sha256:3df041de8887954562c9b261cba85ca0e9ded74048daf125f45edcfaa4832229", + "sha256:40ab6bffa02ae10a0581e6c198be7d2d8ca5c2a0c64e4ed3465d766df457573e", + "sha256:4275811936e2f06feff5e598fb42a1b7ae852da8e39605211892b56b81a34efd", + "sha256:443eae2bf318abeaf6f15d785138f71fd6de770e99a92158b8b814265e079115", + "sha256:447441e76ec720b15e64418d32e092297340387053047c7c694f579efb0ee1d9", + "sha256:4495c5002a7b28557e7e222e77e0b661183e432b7d6d2e788101e3f240e05b8c", + "sha256:44bd4fbb29dfbeba60e7d2bd000c59e4b21ddb3cc53912b14048d37092706d7c", + "sha256:4685902cf26edf013ed7a3da0f426ebba7a00ebb9541386d835afbf002c11cab", + "sha256:498dc3188ca05a68231ac3fdbfc7f57eb67e1343c30e0fea17f8218c1599b253", + "sha256:4c2b5031f63e331e3839b40aed2dd6f191e9c07edbde303e7876846ea1946995", + "sha256:4d48f2d08b9de5864e2c8744d4461b862fb149a18274abc8b698c45975573438", + "sha256:4f87960d57feabfb618e4e0af6e7371645fa26a277860739d6e5d6e0012c92f0", + "sha256:50e3adfb96fc189eb27b1cf62d3b598b89b4bb0420d93a3d3e42e137409011be", + "sha256:51cf45226a9b588d0d2b4880c62d686934b63ab0bd79ca23ab0e9762eb27441b", + "sha256:52aa6992700996af31f375de0c6bacd402b0097fe40b53c426b9f51a90ebabc7", + "sha256:55ea99acb17b9325618de155a0cd6a2e8f5d10be008113e1d433bbb58db543b2", + "sha256:56bc200a365efb37383b7852e4cc5898d3b2da5987289b543956cf8cad71018a", + "sha256:588461c2e8384d309bd63e5826019b6977bc66d629b99ac8737bb795d7b2cb5a", + "sha256:58ca3755ee7ff7f59b57789ec9833c9de9ea275405cdd240eda1f193112e398a", + "sha256:58f361dcbab699cf8f42db3f47c8e7fd1036f138c23a5d08de9fde5f425a730c", + "sha256:598a11a2c7ebaa5334bf698bf29568c9c390abac6a154d8170fedecd1cea38c5", + "sha256:59f63901b0031c3136cf64704dcb21de0bbae62ce2c9529bc39d27665463de37", + "sha256:5cde776b7cc66e4f6c99612cea4aa7269aa65863f7a15841b2c264f103822f4e", + "sha256:5e2b6b57e9733d39f0c9fd3185efa6b8e29652c4cd8fe94180272cf6ed9a78c4", + "sha256:5fb29fb8cd1a46c27a1bf9613ad5ec2599310d46b4025d9556404a6b6a292800", + "sha256:6045373d5a89a5ec71afde535db987ca28e76dfa276c2d4c818265b375d4b055", + "sha256:619799369eeef6366ed3e8755a5670f4f2f0fb6b30a0fd7264dc0fdc2357058e", + "sha256:62588a277bfb59def052abd940703fa35107152bf479781a878617d60faf8fb5", + "sha256:62603db9a7caa0802eaa28c1c46fecd7b3a263a774069c24c3c28c302448721c", + "sha256:65cd72beeeca9d3aaea1201e5923859f308f952f9c71de93f06063c79f0f7a3b", + "sha256:68eb192d85ab8e5f6ec69c2bc6ac0179fbf04a5ac1569d12fbef74883fe102d0", + "sha256:6bd128f206a7752ae1f2ab6c61bf8a24ba28913a10df8b14c2637b973ff97a80", + "sha256:6be488a102b8cf28d0391d8c4ba7748938ae28b78ad901f8585520fca33ead1a", + "sha256:7218e8f32b0956cfcd048fd42d9d5779809745ca1d86113ca56f66e7ae1549c4", + "sha256:7441d755b7ab94f8d4eb3e43ec05482d760842fd263d003a99102d742cd835e2", + "sha256:749e97e1b32313717a565abbe321bc2190bc8b35f1a67e4cdbc7c56c8d8ffe58", + "sha256:75a3ceed0724d625d64b86ca20aba182e4df462e04c2414fc941c0f523f06aac", + "sha256:780fbe7cab297b81dad9fb8dc5eb003c0468ffb0d9e5f65068c53a34661a96bc", + "sha256:78456a747de8dc58360ffa581f30a002baf5aa28cb262536545e91f113ed7639", + "sha256:7967d08cf06dee78443b874f98c98036f624f3a4e73e11f9f64f5be4d25393cf", + "sha256:7a881931aa470808df94a8c380eed2bbbc76cd9dc622310f99665658c821eb6d", + "sha256:7dcd882da75ef9adf94903b1e3b9419e8aa8fb4c7396822b834b9ef7fb96954f", + "sha256:7e841fb9010836c992c9f12fcbd43a831de93a5f726fc1ccd8ca1d0268c5014c", + "sha256:7fdde2c9fd9e3eca40631e024664cf2584272cc8f96308cbe5fdfc930f51d8bc", + "sha256:8024d00c3faf3fc0c16e07a69f4405e8eac7cc0ab15f65fe6cf43827c4cf72b4", + "sha256:80d02b6f04e92601a081dd97b23d3128033098bff5d35d392ddcc0476ea11253", + "sha256:838dcc90063569a0448120554591a1d6c4a4ffe11babf048908793154ab86ade", + "sha256:849df64e889b2e17230d58410a03dba311a65b163508fd33679b2b737d4b7858", + "sha256:87475fabc8d9996fd9c27debb395e642e8c838d78a00b6e932227a0e06b81e26", + "sha256:87e50a3e7cb90af586b6c5faf23e302a970415ac73bd7bd90a515a04b427ef96", + "sha256:89b53f3cda69831909888e0494f4fa0bcd3537e3e138dabeb620bd6ad946bae8", + "sha256:8a893cc101149f80a653f82062ebc95b34525a2614382e1da5458fe7c6997249", + "sha256:8b2bfab86aa71ae13aa41a6a26aab338e0db2b8bc75434b05aea89e011ff35a4", + "sha256:8d86d6fc60743dc916eb79e2eb1ec4818e21e427731543af40a3021851174a13", + "sha256:915563965d418f986e7e145accc592eae9e1a1be3566ff98a05d7a9ec42a76e1", + "sha256:92888bb3187c5ba50500b00b3b310c9f2c651709d28036077680cb5255450a03", + "sha256:93223adc95033dd47133a46ccfc316a0139176fd79085762e27202ec56018f03", + "sha256:9373ad13ef0d2c0fb761e04e55bfdee5a08b52cef2c882c8fbe9935b1517152e", + "sha256:9409a8bf35cf78353942504b24a57de3d75b708997a1e4bd8db71ac8633ce364", + "sha256:9b7f416ff0978e2f2249330527f0ad6fa02f4932e6199692d3b52da2048c19e4", + "sha256:9bde855991b7e362c146535e3136a50bfaffc0487d38b33ca7e5edefc6e23849", + "sha256:9cae88599c7219005d879f98e5ed53341e9a122af585e1091200358a3003d2a0", + "sha256:9cf9b1a857e25c4baceeb3624e92a56df3668f398c4acba74e174d81fb4d1d3a", + "sha256:9f56f72050826f63dcee7a7f55b0a77168cb3bfc553fd405e7f8f9ece75a4036", + "sha256:a090bb2c68df85450502e3e20d665e3a5af9c65a84d6508ed477badd49166fd3", + "sha256:a192e2c40070d92c3ccf777e3a5c4ff515573cd2bb7ed0c537fdadbbec5bbf21", + "sha256:a19a731138fc27d5682277d3b9df22855cea1239bce7fcec5f78f42ef2d1f3c3", + "sha256:a66c3bc5ab1f0ff2164fc9965ddd611ff0802173f4b9d24554c563f6ab7e1d6e", + "sha256:a815775b6c38d4e0ff7bcffbeba67feded90202bb6a226b8dd35f1c855217413", + "sha256:a89012d6d5476ee112d20d998570ed58df2260a852afb1758809cd6900411d21", + "sha256:ae4f5fea5b8b8ccff88238cc8569303e5ee95efae67fa62922a311397a71f346", + "sha256:b6856554c4f44d79fc2307d5768854310a8f0096e501c75637542c82292b0429", + "sha256:b6b751274acb69d77b3323d6b7dbaa3c7fdfc1eb829b7eb61d262f32e1af9685", + "sha256:b736353c0a625bbd5fcec108576e2385db3496f4f771f785ff32e108d3c3bc45", + "sha256:b7fd005a73d9e657273b7a10dc71a9e03c8fb9ee6999798d6918ce095b81ac7f", + "sha256:b91363207bd9dc966a691e959bb47f64b30f7ac4b072be9968b366982f7db77c", + "sha256:ba0b1d2620edf869789c3879223f52bf2afc5d31b3cb47cc57b3a12c05e2aa9d", + "sha256:bbbfc8e28816f19d7c0f1816664980c0a9875d01b27cdf8eedddb639d9e108ad", + "sha256:bd16aabe4a02a297c23417aa17ac6299dbd8c49f673bcd645b4929b11f5a4400", + "sha256:c0afc6800ba57ccc350374c5bd6150419915d95ce93cdbab2d783d75eaf30ecb", + "sha256:c6708715abcf3c73b99508253e961a9967f02fe536532834149574eda6de0d1c", + "sha256:c7c9ab723cde841fefb34efbad91e87f00a674b1fe1cd0784fde742bf2c154dc", + "sha256:c8f3d67aeaf55f017982b73683f0e7342ba2f6635a78f69ce89ebb26aa411e5c", + "sha256:c9790464842f85f437dbbb54417eda1e0e6bfc52dd8d22d6fd1c994b73b2dc74", + "sha256:ca403d7e4798f525fdfc78e258820419cbbd0f0ecbab9de7840e3c017cf6b8cf", + "sha256:d008d90a7f2471519aef0c90dfbe73b3e6e4d5e66ac48e19154c17e89e98b604", + "sha256:d19fbd981a488e22cd04883659ca6b08f50b5974f9fd7c95655ef6a043e5893f", + "sha256:d1befeed746d247c81127bb14de9dc3d30edb6e5976d34f83f86ed262b1d9105", + "sha256:d2374b62878abb00cd8309b32af6c0b715cd02dec0ca74ef12e5069bdc64144a", + "sha256:d376bbd28b3a8999db1a103b3b388aee6f1ddeb3e51bc2172993efdcd86e064d", + "sha256:d4a7319f304a774bed22115bc891618e45f85065ab44ea6acd07d274e750519a", + "sha256:d6734d2ef8a50fbf8445c139477da401f50d62a0606bf00e20ec6d87773fefb1", + "sha256:d760fe2a4d7c3b226cb9026d6a842868d52a7901bd98420e1baf14e80da85cf5", + "sha256:d913de495d90407cd859d263bee2e5d1a4ed3eb6573c04e70d9ec619a7cbed7f", + "sha256:db19d07e2e0129e974a0e65d0064fc222a446cd5122c2fd4184d2af9fc734a9e", + "sha256:dca9ab98072a5a54ebacebdc45f53e645336b320c667410b061be1ca588ae709", + "sha256:ddc7dacc8ece3a182e7f15cb862d1fd616b46d076cb1ae9dd232b2c38b655874", + "sha256:ddf19c062bea7a0cc80f519243d2c01dd091be0cf952a0750d4ad576709559f5", + "sha256:def79fa35ef0cef8d2accec024f4fdc7ead3012ff02f5215c783f39f03ef8cfc", + "sha256:df29a0a7107f7011e77f4eebdddec4c7331e24d787a0b21a46d63bdf7445da95", + "sha256:e09a3942ecbdee5cce73ea9d42da82b81b72ac1bf031ce069b93b5adf4eac8cd", + "sha256:e242bb1c5e76e97dfa9e7f209a71e93a01d7f19ffdd5cfbb2e2d55b4f08f8ab0", + "sha256:e243bd13217235fc7290c621941c3f5cc8b66e4872495be821d7436ba2fb838d", + "sha256:e2af3aad578aa6bd1384bcf4750fc285e5a9de53f40b7d41e5a0bf748edeb2b3", + "sha256:e4e81e09c1578b8df602e3db08b0b3ea0a6947ad612f52bf8dc5ea8d47691f0c", + "sha256:e54da4baf05720032d527874d40b65fa4d7e5c6c6a43d0c3adbeffcaf275a2b3", + "sha256:e80e6c2f55656b4824d72065abb4ddd6a525c74bd78a0aab5d9fc2cf4fb5af50", + "sha256:ed2a239c0ea213acc1908150a3037257083c7c083128f1a4cec2ec4b97dca491", + "sha256:ed905975ab14056a2e5eb1c376cb2e1ebc5396baf84163939c518556fccde9f5", + "sha256:ee21e28f0430bd6dc9086c6e525d5e818a44a5ad19720c8a0ef766792f3eb5e5", + "sha256:ee43c17b173d46a3212baa6ead3ae258eeabdae48c263a01ccf0218c366dd655", + "sha256:ef4fcbf3327382cd4c9f540babd61248208af7b93eec4de397b4d5f58a09e288", + "sha256:eff0ac9dbe711a4aee69bf04a83896aa9b85f19641264053a9f6d48573abb7dd", + "sha256:f0aa869112ef88429ae17820d99c3dd9504c9e9c671d3c246f3d7442cb051084", + "sha256:f3c96f633825733f735c5a9cf21d21a257d8e1edf0b1cee0a064b9c424ca0f7d", + "sha256:f5833ad231be5eb6553de524a70f48d71b2c8563101750531e0b80184e175cd4", + "sha256:f5ec61164adcec446f8969a3358ec3f9b26bbda3b9213e5586d219afa8df2915", + "sha256:f7d486c83842422badd511868fd8a9a20e9407ace71564b6af47ce7e60a336c1", + "sha256:fb9e68df06293761f9fe66ade60a9bc6d0f5e42b8acf2939a9158af86ab0e5bd", + "sha256:fc14a032f813bf5fe624d991960ea83e9715adc27e4c1830a2361eb1d02ac341", + "sha256:fcff63213e8e6e47770541a4607175404f47cbb3ebea7b6058cc82d524a0e424", + "sha256:fd1fbe0f116b6e55da77aca2c6ddcddcfac2186cbf78bdebf40fc156efca389d", + "sha256:fe9753dfee015c570d73df76f899f18444d41388bffcde097deba51c4fadbb9f" ], "markers": "python_version >= '3.7'", - "version": "==3.4.6" + "version": "==3.5.2" }, "click": { "hashes": [ - "sha256:6b303f0b2aa85f1cb4e5303078fadcbcd4e476f114fab9b5007005711839325c", - "sha256:f5452aeddd9988eefa20f90f05ab66f17fce1ee2a36907fd30b05bbb5953814d" + "sha256:398329ad4837b2ff7cbe1dd166a4c0f8900c3ca3a218de04466f38f6497f18a2", + "sha256:a2bf429bb3033c89fa4936ffb35d5cb471e3719e1f3c8a7c3fff0b8314305613" ], "index": "pypi", "markers": "python_version >= '3.10'", - "version": "==8.2.0" + "version": "==8.3.3" }, "coverage": { "extras": [ "toml" ], "hashes": [ - "sha256:012d5319e66e9d5a218834642d6c35d265515a62f01157a45bcc036ecf947256", - "sha256:02ca0eed225b2ff301c474aeeeae27d26e2537942aa0f87491d3e147e784a82b", - "sha256:03ccc709a17a1de074fb1d11f217342fb0d2b1582ed544f554fc9fc3f07e95f5", - "sha256:0428cbef5783ad91fe240f673cc1f76b25e74bbfe1a13115e4aa30d3f538162d", - "sha256:04690832cbea4e4663d9149e05dba142546ca05cb1848816760e7f58285c970a", - "sha256:0590e44dd2745c696a778f7bab6aa95256de2cbc8b8cff4f7db8ff09813d6969", - "sha256:0672854dc733c342fa3e957e0605256d2bf5934feeac328da9e0b5449634a642", - "sha256:084b84a8c63e8d6fc7e3931b316a9bcafca1458d753c539db82d31ed20091a87", - "sha256:0b67af5492adb31940ee418a5a655c28e48165da5afab8c7fa6fd72a142f8740", - "sha256:0cd9ed7a8b181775459296e402ca4fb27db1279740a24e93b3b41942ebe4b215", - "sha256:0cef0cdec915d11254a7f549c1170afecce708d30610c6abdded1f74e581666d", - "sha256:0e223ce4b4ed47f065bfb123687686512e37629be25cc63728557ae7db261422", - "sha256:0e3c426ffc4cd952f54ee9ffbdd10345709ecc78a3ecfd796a57236bfad0b9b8", - "sha256:0ecf12ecb326fe2c339d93fc131816f3a7367d223db37817208905c89bded911", - "sha256:10a0c37f0b646eaff7cce1874c31d1f1ccb297688d4c747291f4f4c70741cc8b", - "sha256:145ede53ccbafb297c1c9287f788d1bc3efd6c900da23bf6931b09eafc931587", - "sha256:1b11eef33edeae9d142f9b4358edb76273b3bfd30bc3df9a4f95d0e49caf94e8", - "sha256:1b88c69c8ef5d4b6fe7dea66d6636056a0f6a7527c440e890cf9259011f5e606", - "sha256:258354455f4e86e3e9d0d17571d522e13b4e1e19bf0f8596bcf9476d61e7d8a9", - "sha256:259b69bb83ad9894c4b25be2528139eecba9a82646ebdda2d9db1ba28424a6bf", - "sha256:2aa055ae1857258f9e0045be26a6d62bdb47a72448b62d7b55f4820f361a2633", - "sha256:2d3807015f138ffea1ed9afeeb8624fd781703f2858b62a8dd8da5a0994c57b6", - "sha256:301e3b7dfefecaca37c9f1aa6f0049b7d4ab8dd933742b607765d757aca77d43", - "sha256:32ca0c0114c9834a43f045a87dcebd69d108d8ffb666957ea65aa132f50332e2", - "sha256:34b02417cf070e173989b3db962f7ed56d2f644307b2cf9d5a0f258e13084a61", - "sha256:356e76b46783a98c2a2fe81ec79df4883a1e62895ea952968fb253c114e7f930", - "sha256:35a31f2b1578185fbe6aa2e74cea1b1d0bbf4c552774247d9160d29b80ed56cc", - "sha256:380e8e9084d8eb38db3a9176a1a4f3c0082c3806fa0dc882d1d87abc3c789247", - "sha256:3ad050321264c49c2fa67bb599100456fc51d004b82534f379d16445da40fb75", - "sha256:3e1bb5f6c78feeb1be3475789b14a0f0a5b47d505bfc7267126ccbd50289999e", - "sha256:3f4818d065964db3c1c66dc0fbdac5ac692ecbc875555e13374fdbe7eedb4376", - "sha256:460cf0114c5016fa841214ff5564aa4864f11948da9440bc97e21ad1f4ba1e01", - "sha256:48c39bc4a04d983a54a705a6389512883d4a3b9862991b3617d547940e9f52b1", - "sha256:4b59148601efcd2bac8c4dbf1f0ad6391693ccf7a74b8205781751637076aee3", - "sha256:4d2afbc5cc54d286bfb54541aa50b64cdb07a718227168c87b9e2fb8f25e1743", - "sha256:505d7083c8b0c87a8fa8c07370c285847c1f77739b22e299ad75a6af6c32c5c9", - "sha256:52f444e86475992506b32d4e5ca55c24fc88d73bcbda0e9745095b28ef4dc0cf", - "sha256:5b13955d31d1633cf9376908089b7cebe7d15ddad7aeaabcbe969a595a97e95e", - "sha256:5ec4af212df513e399cf11610cc27063f1586419e814755ab362e50a85ea69c1", - "sha256:60365289c3741e4db327e7baff2a4aaacf22f788e80fa4683393891b70a89fbd", - "sha256:631efb83f01569670a5e866ceb80fe483e7c159fac6f167e6571522636104a0b", - "sha256:6697e29b93707167687543480a40f0db8f356e86d9f67ddf2e37e2dfd91a9dab", - "sha256:66a80c616f80181f4d643b0f9e709d97bcea413ecd9631e1dedc7401c8e6695d", - "sha256:67e9bc5449801fad0e5dff329499fb090ba4c5800b86805c80617b4e29809b2a", - "sha256:68a4953be99b17ac3c23b6efbc8a38330d99680c9458927491d18700ef23ded0", - "sha256:6c36ddb64ed9d7e496028d1d00dfec3e428e0aabf4006583bb1839958d280510", - "sha256:6e3370441f4513c6252bf042b9c36d22491142385049243253c7e48398a15a9f", - "sha256:7034b5c56a58ae5e85f23949d52c14aca2cfc6848a31764995b7de88f13a1ea0", - "sha256:704de6328e3d612a8f6c07000a878ff38181ec3263d5a11da1db294fa6a9bdf8", - "sha256:7132bed4bd7b836200c591410ae7d97bf7ae8be6fc87d160b2bd881df929e7bf", - "sha256:7300c8a6d13335b29bb76d7651c66af6bd8658517c43499f110ddc6717bfc209", - "sha256:750db93a81e3e5a9831b534be7b1229df848b2e125a604fe6651e48aa070e5f9", - "sha256:777c4d1eff1b67876139d24288aaf1817f6c03d6bae9c5cc8d27b83bcfe38fe3", - "sha256:78e696e1cc714e57e8b25760b33a8b1026b7048d270140d25dafe1b0a1ee05a3", - "sha256:79060214983769c7ba3f0cee10b54c97609dca4d478fa1aa32b914480fd5738d", - "sha256:7c8d4bc913dd70b93488d6c496c77f3aff5ea99a07e36a18f865bca55adef8bd", - "sha256:7f2c47b36fe7709a6e83bfadf4eefb90bd25fbe4014d715224c4316f808e59a2", - "sha256:800bc829053c80d240a687ceeb927a94fd108bbdc68dfbe505d0d75ab578a882", - "sha256:843ea8643cf967d1ac7e8ecd4bb00c99135adf4816c0c0593fdcc47b597fcf09", - "sha256:8769751c10f339021e2638cd354e13adeac54004d1941119b2c96fe5276d45ea", - "sha256:8dd02af98971bdb956363e4827d34425cb3df19ee550ef92855b0acb9c7ce51c", - "sha256:8fdf453a942c3e4d99bd80088141c4c6960bb232c409d9c3558e2dbaa3998562", - "sha256:941617e518602e2d64942c88ec8499f7fbd49d3f6c4327d3a71d43a1973032f3", - "sha256:972a9cd27894afe4bc2b1480107054e062df08e671df7c2f18c205e805ccd806", - "sha256:9adb6688e3b53adffefd4a52d72cbd8b02602bfb8f74dcd862337182fd4d1a4e", - "sha256:9b74db26dfea4f4e50d48a4602207cd1e78be33182bc9cbf22da94f332f99878", - "sha256:9bb2a28101a443669a423b665939381084412b81c3f8c0fcfbac57f4e30b5b8e", - "sha256:9d44d7aa963820b1b971dbecd90bfe5fe8f81cff79787eb6cca15750bd2f79b9", - "sha256:9dacc2ad679b292709e0f5fc1ac74a6d4d5562e424058962c7bb0c658ad25e45", - "sha256:9ddb4f4a5479f2539644be484da179b653273bca1a323947d48ab107b3ed1f29", - "sha256:a1a6d79a14e1ec1832cabc833898636ad5f3754a678ef8bb4908515208bf84f4", - "sha256:a698e363641b98843c517817db75373c83254781426e94ada3197cabbc2c919c", - "sha256:ad14385487393e386e2ea988b09d62dd42c397662ac2dabc3832d71253eee479", - "sha256:ad146744ca4fd09b50c482650e3c1b1f4dfa1d4792e0a04a369c7f23336f0400", - "sha256:b5db73ba3c41c7008037fa731ad5459fc3944cb7452fc0aa9f822ad3533c583c", - "sha256:bd3a2fbc1c6cccb3c5106140d87cc6a8715110373ef42b63cf5aea29df8c217a", - "sha256:bdba0a6b8812e8c7df002d908a9a2ea3c36e92611b5708633c50869e6d922fdf", - "sha256:be3d4bbad9d4b037791794ddeedd7d64a56f5933a2c1373e18e9e568b9141686", - "sha256:bf69236a9a81bdca3bff53796237aab096cdbf8d78a66ad61e992d9dac7eb2de", - "sha256:bff95879c33ec8da99fc9b6fe345ddb5be6414b41d6d1ad1c8f188d26f36e028", - "sha256:c555b48be1853fe3997c11c4bd521cdd9a9612352de01fa4508f16ec341e6fe0", - "sha256:c81f6515c4c40141f83f502b07bbfa5c240ba25bbe73da7b33f1e5b6120ff179", - "sha256:c9136ff29c3a91e25b1d1552b5308e53a1e0653a23e53b6366d7c2dcbbaf8a16", - "sha256:ce1998c0483007608c8382f4ff50164bfc5bd07a2246dd272aa4043b75e61e85", - "sha256:cec2d83125531bd153175354055cdb7a09987af08a9430bd173c937c6d0fba2a", - "sha256:cff784eef7f0b8f6cb28804fbddcfa99f89efe4cc35fb5627e3ac58f91ed3ac0", - "sha256:d2c87e0c473a10bffe991502eac389220533024c8082ec1ce849f4218dded810", - "sha256:d7cfad2d6d81dd298ab6b89fe72c3b7b05ec7544bdda3b707ddaecff8d25c161", - "sha256:d8a7a2049c14f413163e2bdabd37e41179b1d1ccb10ffc6ccc4b7a718429c607", - "sha256:da305e9937617ee95c2e39d8ff9f040e0487cbf1ac174f777ed5eddd7a7c1f26", - "sha256:da86cdcf10d2519e10cabb8ac2de03da1bcb6e4853790b7fbd48523332e3a819", - "sha256:dc022073d063b25a402454e5712ef9e007113e3a676b96c5f29b2bda29352f40", - "sha256:e0723d2c96324561b9aa76fb982406e11d93cdb388a7a7da2b16e04719cf7ca5", - "sha256:e092b9499de38ae0fbfbc603a74660eb6ff3e869e507b50d85a13b6db9863e15", - "sha256:e0b216a19534b2427cc201a26c25da4a48633f29a487c61258643e89d28200c0", - "sha256:e1c85e0b6c05c592ea6d8768a66a254bfb3874b53774b12d4c89c481eb78cb90", - "sha256:e301d30dd7e95ae068671d746ba8c34e945a82682e62918e41b2679acd2051a0", - "sha256:e808af52a0513762df4d945ea164a24b37f2f518cbe97e03deaa0ee66139b4d6", - "sha256:eb07647a5738b89baab047f14edd18ded523de60f3b30e75c2acc826f79c839a", - "sha256:eb7fdf1ef130660e7415e0253a01a7d5a88c9c4d158bcf75cbbd922fd65a5b58", - "sha256:ec10e2a42b41c923c2209b846126c6582db5e43a33157e9870ba9fb70dc7854b", - "sha256:ee2aa19e03161671ec964004fb74b2257805d9710bf14a5c704558b9d8dbaf17", - "sha256:f08fd75c50a760c7eb068ae823777268daaf16a80b918fa58eea888f8e3919f5", - "sha256:f4cd16206ad171cbc2470dbea9103cf9a7607d5fe8c242fdf1edf36174020664", - "sha256:f70c9ab2595c56f81a89620e22899eea8b212a4041bd728ac6f4a28bf5d3ddd0", - "sha256:fbabfaceaeb587e16f7008f7795cd80d20ec548dc7f94fbb0d4ec2e038ce563f" + "sha256:00d3eb96e9988c45f50cccd1f1496571ac5c1f91386ac02c4d55516eeda19a24", + "sha256:01c6908bc613b420c26c818fe948e1b97dfd041a53c98b01c63bd8321f5c9aae", + "sha256:066429634299e14dd2d511e1e85f8f9cecc500781f6b41907c0dd6f1baea7e63", + "sha256:0993d0e90858c03943d3cb152e068a20dd4707924deec84dd2230261baae3b1b", + "sha256:0dcbcfcc059117284c603ff8cb61a65872512882f84a8cf0339241f7f7c2f148", + "sha256:0fd7a86fdda7cb6d616d178654bd0ad6bc0f3f33c2e478aa598500a1a9e34eda", + "sha256:11d28e9123a9156cb405d8d27b44256c9a58fb5decc2073a8f17862057e3aa0f", + "sha256:11e597173af1dc33d5f8a7332ada544199269a223af1ee1770ddd5e245ad0fe8", + "sha256:126d1af8804d7224421fe991ff65d3ce649081560df7a98b1a5ffff07f9923bd", + "sha256:14253fc7bb15749b849795a06f5d3b6d8bc3fb8a4b5ddc341faf7a89dce205fc", + "sha256:152877cdc8a07264882cfcd503ba56a3ef6cba56a70e8c70f6eb8ffd7384789a", + "sha256:17228fbca0f22976f797be94e975dcd237799c657d49551c7de1e0654d1202e9", + "sha256:191803c4996b499fcd78c2ad5e5f767dcc53cb4dc6de6d6a741b443a1821ef02", + "sha256:1a37c6e478cf687e1aa30a593d19c92c02fad9d122b51ab73f51b8dc7a0c0fc9", + "sha256:1c569a9fd25505f1cd6bea90588818f90373ce90e2632e2cacf19ddbd6e14fdb", + "sha256:1d56e4d21c56d2046447733f8b118409597db48c01efe898ee9ac24e858ec2d6", + "sha256:1d5d0e3b660506fb84f995814e3118a21efdc0c8eb80127da1be627d90093c17", + "sha256:1f15254427c9b33eedac4f198eaf9e356eb4f6214551afb43da6194a2c088ad7", + "sha256:218d742afca2b5ad5ca759e93eddedfbcc6eadf8322f080dcefc40b7bd4e2d48", + "sha256:22957cef43ce038641de78ba995de7568d2d6a37c6ddbf7fa0fd7d1ae2344d91", + "sha256:23219888477edd736b6fcaec1272d47d93b926e999641ffea7e53a1738e70b2b", + "sha256:251aed777c47c77aba047096d4542889db089227655711dfc2b9c54ef0e15e35", + "sha256:28ff850182a67d117990fa2ce5ea1032836d8c9630dae867e8bdd3bff4533b79", + "sha256:29309ccc86b7f33df7db12813c299f215bbbc470ed6292d0bedd63ffae1ebf64", + "sha256:2aca0bdfa9e91621d5b09d815357bf63def4fc0e9cb66da67bf2cf93f3b1a6f5", + "sha256:30c1b65d529e46569899fadca59e4a87c1faf2886923f1307ba61e654d4f3c20", + "sha256:35f37886699cb9abd29958247d718628d5bc6f39e623dff66a09e546c42a7e03", + "sha256:382d3346d56b0eec1b793d53a4c88799c8053f516aa3a8d7c44315696954bacf", + "sha256:396bb16e04ce04efbb3df91456ae4e3da918e69ecdf67fb711b0a0fdf35ccce0", + "sha256:3e7f99698ba3a7d13988bdd984b7ebf13af4dbe2166dc8502eef90d77603b0a4", + "sha256:3e861f1071dcc2fec1e88bef0920f6b1eaa66a143555b4f8ab79ba2b0f30ef55", + "sha256:3f43bac1856ba269b905302778d4df433d6006489a192174ad77ac528e395032", + "sha256:40c0f00899fe6181ae7f434ceb200e51f5ee4b8ed10e3b5f0b605f0cae15da87", + "sha256:414c26dfdb96aac2d570a54e03008f001e32eb2d413705365503648c6bd361d8", + "sha256:4358b9c8c0125b460407f3017c6cce8156e904b32772c5630d27112f52bdbfe5", + "sha256:444889f7f66b74e4455c0a97e0e166dd41177f1dca8c0239a47cff25e05ba7e1", + "sha256:44f21e407b278efdfc1ee5e481e00518bd1d500310a30a5fbf2bcbedfef4aaf0", + "sha256:4cc4f73aa3fabc36e32046d6cd2971405948d8a903636508a3d3b2f9128b3a95", + "sha256:4dbbd1155ca46e6e0b6b89d204428c56ef6a459af21333f365d135a2820e5a09", + "sha256:4ee546b9e4872ffa194bf07ac87bfa1202ebb824d0795dc1ef22f175545ca90a", + "sha256:5139009b5efd2194fc168ee9362f0e191ba612ef5d29242f9269c22f9b8f80c7", + "sha256:5375ebd99038021b35e99dc88255022912c06565d316212f4a576e4b08d30f5d", + "sha256:5397e21a90dde0e9c6896b77ded8f0be26b66f8b22b33aed41f6043ed95d55e6", + "sha256:57ff3783f99d75a1e81dd56a9737eb5665e6736a5d93258ba596b6dcad8fd05b", + "sha256:58d4a54c6ea672afef66d49be922a2c69826c5ae1a42a9cd94f0c9c2bacdf800", + "sha256:59c3926585e1cd1f2190f4b2ac9014de1bbeaf0d5d0587b0dc6b0aa90d17896a", + "sha256:5a27b731c171e43dc8b5f32b76a5051dde2ec9b9366c87028f08a7088ebc2c7b", + "sha256:5b3146d2317c75f70df2509066d979dadd941f7021cdf9b5db4bcd8568258e25", + "sha256:5dca0bb66b4c3d624ba047887bf70270030c150692d543cb501293dc38a9f4b5", + "sha256:611a44e5229a59d7483ce830160e1a0e85f700562c7a5651c7c63fb8f4eb528c", + "sha256:648352b94507179d82637292e7ae8802508d95f78e2f00a705a50b6c48011681", + "sha256:6a75180829efb8ae62b4aded25be6ddca1c888d138d2d82e21d93bfbd88f41cb", + "sha256:705e5af11d34647efdc170c7840b6857c81cf74be96419a553f237e68e62cb72", + "sha256:723dcdab91357159b722935b500ee8abc0a66c8c432e1e9fabf4cc7598952de8", + "sha256:724bd0f1e81856b35e59fc98cf7b4e544a3cb662e4e0864dca73d4326ee9d808", + "sha256:732d950e51f3ba4fb6209c73250f3e8924fefca42953ee04a9e65d8c02414d7d", + "sha256:736fde09ea39646d11f8e3b76bd3425c075aa4dd45f24891970bb77c14ff20f5", + "sha256:7a076277ca9f5750cc230f0f578ebd2620cec60255b25707361699fef6fb465c", + "sha256:7b3bce4a0d05401d70b7d0d5ca783e686bc9d30e81dbd7d980d532609bf809e4", + "sha256:7b451c68218c150f616bc9649783ec8de76a59792c759b43aa0c9c0466a465e4", + "sha256:7d0732c83746bc24123c581a85d9dd96b70ddb538c9076020aa1a041790361e9", + "sha256:7ed238d227e23cc300c3d464babdaf9f6ddc740aa1b15a77ae96136e6a7c4516", + "sha256:80d3f7b48d43ee8fc5e8707a8adb43d743a5a1a85256c25a24f9d6d0e2238fa6", + "sha256:80e9fdb4c3d926b6ba721d4bf7435bdb869c3527ae7803290361d0ab73db13b6", + "sha256:848893e1d361448c113dc2f0913503522a6f7be231d0e38333d2a22d9698a011", + "sha256:893ea9cf86cb8d2546812ac93d973aaf2ee1fb45110a873b014214fd23e3725e", + "sha256:8afd9bf35cc6a1f22eb3634808fa8e0b91902459c5721ef2e4461dfe771d7f08", + "sha256:8be099e979fc42559328a21828281b4578304191ae46ed4e80a407048a82eee6", + "sha256:8e209591f7c41ae4a9171335cf6156afda0b21de73b02f73f5aa95b2d5fbb08d", + "sha256:8fc15cc8d0d06e873c00ef18e1372d605f9aaf3de27d8c24e50782e75bc8b843", + "sha256:9174f0af24e5eff248b9dbfe76ec5275a3d19d37edbc2810543f12cf97347a34", + "sha256:921415102a90637fcc2e3f169f61dad7699ecf690e8639fc21b813acbedc0967", + "sha256:967d72c835d7a8cf0af99ec813a2d06e3db6df706402f1fe85b31b437645f495", + "sha256:98d9c97f51b334b0adce7b964442a9af33c1a00c6ac856984cc5dc8d18f81c75", + "sha256:99704f73721e23859112072d522076e11c31744fc96b5652e5dd2018aa4359f7", + "sha256:9a75a4704ff640e46170042eec1f984385a121227c505d5a16ad8e495f452541", + "sha256:9acc7f7ec4a1b5f89bd929fde5b8a714f6fafdc6cc18725413d510aa082b47ad", + "sha256:9c6afdd69218202bc1758c9a14b86b8cf1084f37ed2ca143e567a103772b16d1", + "sha256:9cdf19874e0d247f32f03609200370343c3c7aa260b191d8c2bb251d36198283", + "sha256:9e1d0ced76318bab499693ff25f64faa343415187cb2e4d7befdfdd391a1cf6a", + "sha256:9fd670ac43b709c575aefc25bf52d8a598a3bc5017bddfd0a179152ab06a2deb", + "sha256:a0f2285329dac10ab08f79cb11f5692c497018e6c7c511f95e6fd63a70b8f831", + "sha256:a2fac6895eb299a2e52d7bbb8fb3903502b9da8d3f5309ceb16ec40c646b58ee", + "sha256:a336eec40e3520d369b8a6cdabb4f596e69a8b42927ca074aa1452fed943238a", + "sha256:a4624f80732f6b427ac58f1f59c577a0994a12e8174b5af6a027b4b58795d4c3", + "sha256:a56ac4fa5a75c7e182e8f62600cfb4aff43c5ed7356a034f3557659c3bec1d90", + "sha256:a678c0b6b22086ec2427359d22e37445d4a792f5fdbbc744112c7dade65cad02", + "sha256:a740ea6f083c6db7b926534d159508f80ba275ab35e722522de0d18d0f56e55f", + "sha256:a90700f743e29aa3d75a6ff5f01953176a889c00e526194bc4d281731b88d99d", + "sha256:a9a638be322a8d76a41cdb17781c7f82aaee6a66493d8ffb7e2c09ee22423d99", + "sha256:a9cd3de0a5bfe7b0e21ee10e1a14e3d61bf52efc88217ab1d95d6ace6970bd46", + "sha256:aa62c85046473959c13ba9edca9dc90a77d5c1095b1ba313556314d77fe5b036", + "sha256:aba5c63b7afdc749cc9eae943d5b868cba2b261a176378fa1c5a30bc8bc89982", + "sha256:ac0f3b379c94acc2f7dce5f5f0b24d44fa1cc6a509717ef83dfee07450c2117c", + "sha256:af2a2a8c7c74de0559e0c368d94c8def9e16c58faaee33a0bf081057c4227e3b", + "sha256:af98ad5ed9d6daaca956201e00bb429a7eb2b080426686f70a20353e0f9839f5", + "sha256:afdf43b72ef3876c1fe66423b91466e37877c9e81e8cec70542b7e8525b9d1b7", + "sha256:b88841e654f09732804809e435b3e005a929ffd9998b872b7b213957b8759cb8", + "sha256:bb2fc905bbf4e6b7f40806ea79e31515abf6349594cdf0adf27c4215f0463204", + "sha256:bb4ffe96aa663cee727659db5a2afeb38c95f8677b747d447b90d6d4874ea2c5", + "sha256:bc0b0ac781d489304b741269857f1f8338b7a26b1b89c06c0344658001ec0035", + "sha256:bf1bd822ec4e387ed245bed0d71151582cf7be9e5309bc4145eefe36083d5878", + "sha256:c19cd6d025c1673f22afcd22c7df8a662d779e05d8e3fa6820c22afb895b0206", + "sha256:c3305c38a2fa21a4254f2ace7dd9ef5fc569c9a558b66e7017650b3d637fb95e", + "sha256:c85d54e7e8a2ca932fe8399301af9b8d5907ea2a455ffaff6e7d1208db83b943", + "sha256:ca64d9f1f384f151b9511bec01126072acd2f313439f8ed015a22d8790aab6fa", + "sha256:cce2bc991293f15cc4084ca116827b5900c5f34e1a54dfe83f10ab5c43162eb7", + "sha256:d6276d78f6fca7d0ac066d5da4165c5acd07829e8305c2cb900b738fb3a75a72", + "sha256:d93db87adb6b1c1b408dce4763314b55d76a9f589e96783a84ac9e7689e48bdf", + "sha256:db5f8394e17f877a625b257f2ba0ce8e728a499c2c1579ad66220272cd3df510", + "sha256:db76506aa5416081f3e8974ae0f7965c58ada0bb0ef7339ac86099588dbb20d3", + "sha256:dba2edfb054f6d4a08df9d1637c39a5aa3865bca6617c13c86be21e45658a59c", + "sha256:dcf4bc2aab4e16b1c4c0c2005918f23a7dd5d7821ddae82caed9e3342dc2fcce", + "sha256:e1fa594c887365b69745f25a416806e61085dd07b94c9eae68a6e20730629b23", + "sha256:e6c52d3307824ff93b39efd99e4185d557db40bd841452abfb32e5d9151ca162", + "sha256:eb57acff4a74246ae513c142d4b36e18c389c3aed8661914a53f7cd0071031b2", + "sha256:f80bd9f9633eafc73d0a913ba2645c96ba58bba1befc30590f7c0fbfde59d865", + "sha256:f8475460aa33ee28ac896ab1156d0bb3b6c639f7f8383c2677d3359eb35f8205", + "sha256:fb2bde05838fffae1a1bf75e5d411a6cac3e4e9bb97e6640fed8cd47888b33f0", + "sha256:fb9d92ecfe2d5b494367c67f7446f8b75b68d8d0c8cf3bc3e6997478be25d9e2", + "sha256:fd3d72233eb8b48acc94fa57d44e2d32ce8e7abed02882ccb6d855ccc4ed33ec" ], "markers": "python_version >= '3.10'", - "version": "==7.13.5" + "version": "==7.16.2" }, "dill": { "hashes": [ @@ -2596,34 +2802,34 @@ }, "distlib": { "hashes": [ - "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16", - "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d" + "sha256:4b0ce306c966eb73bc3a7b6abad017c556dadd92c44701562cd528ac7fde4d5b", + "sha256:f152097224a0ae24be5a0f6bae1b9359af82133bce63f98a95f86cae1aede9ed" ], - "version": "==0.4.0" + "version": "==0.4.3" }, "filelock": { "hashes": [ - "sha256:b64ece2b38f4ca29dd3e810287aa8c48182bbecd1ae6e9ae126c9b35f1382694", - "sha256:ca8afb0da15f229774c9ad1b455ed96e85a81373065fb10446672f64444ddf70" + "sha256:a93c4d93269b339a6af4848342c7e940d0f9928ad95eff64764699e5f1bf8a6a", + "sha256:da5915714a70b55d167fdc7e251ad91302b0a36816fb574dfafae8f4f2c9bb21" ], "markers": "python_version >= '3.10'", - "version": "==3.25.2" + "version": "==4.0.7" }, "identify": { "hashes": [ - "sha256:873ac56a5e3fd63e7438a7ecbc4d91aca692eb3fefa4534db2b7913f3fc352fd", - "sha256:8db9d3c8ea9079db92cafb0ebf97abdc09d52e97f4dcf773a2e694048b7cd737" + "sha256:6a16b69b93187244e0548cbfd25b3e4a6f9a7a2ad784625c3bec2b8d27b81aaa", + "sha256:ad729860a923858d26917c2f4fb0a1d83d27a75b1e090c06440c573f048f3285" ], "markers": "python_version >= '3.10'", - "version": "==2.6.18" + "version": "==2.6.20" }, "idna": { "hashes": [ - "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", - "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902" + "sha256:a7db850025b95ded1eae8a46181a1a6c56c92c96f0e2b005d9ff8dc0210cab44", + "sha256:ab7ae7122974553370f0bdb919e1a960b2cd1bc1ef0276416d896db81c14582c" ], - "markers": "python_version >= '3.8'", - "version": "==3.11" + "markers": "python_version >= '3.9'", + "version": "==3.20" }, "iniconfig": { "hashes": [ @@ -2659,35 +2865,35 @@ }, "nodeenv": { "hashes": [ - "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827", - "sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb" + "sha256:3ce8fe5b71d16e8af7039ca65257354100bc772965d6bc549070649e53b1b146", + "sha256:edaa16e6c14d7cf395d75d4bbd5a26390f4dc06501a33b4e76282b02cc688a25" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'", - "version": "==1.10.0" + "version": "==1.11.0" }, "packaging": { "hashes": [ - "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4", - "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529" + "sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79", + "sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c" ], - "markers": "python_version >= '3.8'", - "version": "==26.0" + "markers": "python_version >= '3.9'", + "version": "==26.3" }, "pathspec": { "hashes": [ - "sha256:0210e2ae8a21a9137c0d470578cb0e595af87edaa6ebf12ff176f14a02e0e645", - "sha256:fb6ae2fd4e7c921a165808a552060e722767cfa526f99ca5156ed2ce45a5c723" + "sha256:17db5ecd524104a120e173814c90367a96a98d07c45b2e10c2f3919fff91bf5a", + "sha256:a00ce642f577bf7f473932318056212bc4f8bfdf53128c78bbd5af0b9b20b189" ], "markers": "python_version >= '3.9'", - "version": "==1.0.4" + "version": "==1.1.1" }, "platformdirs": { "hashes": [ - "sha256:1ec356301b7dc906d83f371c8f487070e99d3ccf9e501686456394622a01a934", - "sha256:68a9a4619a666ea6439f2ff250c12a853cd1cbd5158d258bd824a7df6be2f868" + "sha256:29dbf06d96c500bc6bdbce75fb0a14d63279c93b1842f97e72a135b33e856983", + "sha256:eab5f70271a490ef74618bb314fbb86e3c7e82fa3b9c922c2ea0e0a1a155d329" ], "markers": "python_version >= '3.10'", - "version": "==4.9.4" + "version": "==4.12.2" }, "pluggy": { "hashes": [ @@ -2706,6 +2912,14 @@ "markers": "python_version >= '3.9'", "version": "==4.1.0" }, + "pygments": { + "hashes": [ + "sha256:2363c69b61c4a97c838da3b130dcd6468f4848992b21a82f2a63ec34377137d9", + "sha256:610ca751c9bc2492b38eb9a38a7fbc93edbbb2d7182edaf34e66ae493dee5c8c" + ], + "markers": "python_version >= '3.9'", + "version": "==2.21.0" + }, "pylint": { "hashes": [ "sha256:03c8e3baa1d9fb995b12c1dbe00aa6c4bcef210c2a2634374aedeb22fb4a8f8f", @@ -2715,6 +2929,43 @@ "markers": "python_full_version >= '3.8.0'", "version": "==3.2.6" }, + "pysqlite3": { + "hashes": [ + "sha256:193488f62ebafcca1b72beb3daba98e4bc3be62ca6e3adee5bff603eadb535f7", + "sha256:1cc753922baa703496b6edbf92687389490b0e7ad61b7ed4925e6cf2a7def0a1", + "sha256:268fa5873143cccd79f32624c9a25714e4595715795ae09c8366c75cae8f5aed", + "sha256:2886b6ccf9c3c7ce678ea795a2aa9ddb4563c50c81bce399560fdb2c5662e55d", + "sha256:30bc9471bca6cfb35865e1a7ec6383b7fd37271edb7748941329709ef680c478", + "sha256:4a2dd23831c3fef68db0761c685b9ca5286dc8d58b090bc5c055f389d1b319a5", + "sha256:4f03a69a9c64d0476bbf9c619e1024770368b08e6b572c3f5f0fa641f1b67f27", + "sha256:503e570d0c771ea2a79397523443687e5ca149e93530487dd61b9763b393be58", + "sha256:51f24094c55039bd10c0a2d83e3c502039bf4bfa2b199ecf326815c52ec30bfb", + "sha256:5ae52d27b48a634f1015051d791d23a5bd3f0a992099a632bf39bca21a156420", + "sha256:60cc74e051af0bef460950ea975d2d6c80a2145203f23653673a19cc367a6bb7", + "sha256:64d48638e2c787f1e7ca0100294740f4db7f6bce1516ba8076e082d6443925d4", + "sha256:65a9af11004d350538b6bd852b0ec22cdd62928be9ab522d85c0840d5bf92a72", + "sha256:81226436fae52d3bec4ce578104c5bcf4c22d3fcf29d4a590fcbde56b90472ef", + "sha256:86d1a3ab3351984ddfa1a32ce51b378450dc9c53147a0e663febe077436db79a", + "sha256:87368097abc224c25719e186a9173f80b1253cf0d84989791804e9c12440fcd6", + "sha256:97550d7f7b4714a174920799841fa61ddeb340bc662e421e2ebc12d8474fc89c", + "sha256:a7855d3016392fa81571404fc1647a1d07d1128ff862652e1f89e59edcc3405e", + "sha256:adc5faf38dcc1c47818e993c6998ee044643b6863ae89db693b36173d26b2400", + "sha256:b4b1f27e8cfe15a4b13448a3ff48daa0a3cfd0bdb202aeb2378d768c14407b28", + "sha256:b6f768d6e00d4574f5cc1bff174a4703382afe221b04b009bcb8b41164af08a0", + "sha256:c02894e33691c742c62e4219a03b9683e1fdd4bad7d799c3395df8aefcd5ed17", + "sha256:c4f85a31e80520351e7bc8e452e048bbc4470e17ca1882105cfe90833b476361", + "sha256:c86cd86b2833b43fb4c01b8c90e71f70e95105995f4b1e27b8d9d5c906512992", + "sha256:cc9787dc409f800e310c8a457b7c98d1c4d4a76e15821b7fb460c0e63554ddd8", + "sha256:e3e0ff8dfd84926a06cac62905b7659be7152ced4f6c1ac8ea381a1281555cce", + "sha256:e52ec831759304540b53b550a230c698c3c4b9349732e7a2365bda5faa14854f", + "sha256:ec9ec8cb87132f912dead528c8d8e7b71348a5b83b808515114f8b95bd8f742a", + "sha256:ecf5112b62a4e6c04438957e343fe9672707bd3191f789ecae6c95b226aa6bb6", + "sha256:ed0da0211335335900e699f93c7fe7292ab3437b015ee1310ee5199fd9d05c29", + "sha256:f88d0f8f45bf3644ddd3e7c7de4b6b8d5b10a1bfe23db55b5a1ed95cbd4a0cb9" + ], + "markers": "sys_platform != 'linux'", + "version": "==0.6.0" + }, "pysqlite3-binary": { "hashes": [ "sha256:002fcba03fdd5ad190b9438a1c5c648ae8a4d6992d3d54daec2ab8138b1a4183", @@ -2726,16 +2977,17 @@ "sha256:b21717b4df66b3b3f759f31209b1c835edfa1ad7768f7b2847337382b6c6003f" ], "index": "pypi", + "markers": "sys_platform == 'linux'", "version": "==0.5.3" }, "pytest": { "hashes": [ - "sha256:4ba08f9ae7dcf84ded419494d229b48d0903ea6407b030eaec46df5e6a73bba5", - "sha256:c132345d12ce551242c87269de812483f5bcc87cdbb4722e48487ba194f9fdce" + "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", + "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c" ], "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==8.3.2" + "markers": "python_version >= '3.10'", + "version": "==9.1.1" }, "pytest-cov": { "hashes": [ @@ -2756,20 +3008,20 @@ }, "python-discovery": { "hashes": [ - "sha256:180c4d114bff1c32462537eac5d6a332b768242b76b69c0259c7d14b1b680c9e", - "sha256:b6a957b24c1cd79252484d3566d1b49527581d46e789aaf43181005e56201502" + "sha256:cf87d3627dfb4412437fdd5b13eae402607722998d21567993aedbc59b23c15e", + "sha256:d43fcdef879fe795352bd13ccf8d185ba5a9f86f36cfcd00529f596e737442b3" ], "markers": "python_version >= '3.8'", - "version": "==1.2.1" + "version": "==1.6.1" }, "python-dotenv": { "hashes": [ - "sha256:b7e3b04a59693c42c36f9ab1cc2acc46fa5df8c78e178fc33a8d4cd05c8d498f", - "sha256:d92a187be61fe482e4fd675b6d52200e7be63a12b724abbf931a40ce4fa92938" + "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", + "sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3" ], "index": "pypi", - "markers": "python_version >= '3.5'", - "version": "==0.20.0" + "markers": "python_version >= '3.10'", + "version": "==1.2.2" }, "pyyaml": { "hashes": [ @@ -2852,11 +3104,11 @@ }, "requests": { "hashes": [ - "sha256:18817f8c57c6263968bc123d237e3b8b08ac046f5456bd1e307ee8f4250d3517", - "sha256:4e6d1ef462f3626a1f0a0a9c42dd93c63bad33f9f1c1937509b8c5c8718ab56a" + "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0", + "sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed" ], "markers": "python_version >= '3.10'", - "version": "==2.33.1" + "version": "==2.34.2" }, "responses": { "hashes": [ @@ -2869,256 +3121,299 @@ }, "tomlkit": { "hashes": [ - "sha256:592064ed85b40fa213469f81ac584f67a4f2992509a7c3ea2d632208623a3680", - "sha256:cf00efca415dbd57575befb1f6634c4f42d2d87dbba376128adb42c121b87064" + "sha256:177a05aece5a8ca5266fd3c448abb47b8d352f09d477d3ca8332db4d89b24304", + "sha256:e25bbf38843005246210a12982776f27f99cb9be67160e14434d0c0d21ee1e97" ], "markers": "python_version >= '3.9'", - "version": "==0.14.0" + "version": "==0.15.1" }, "urllib3": { "hashes": [ - "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472", - "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168" + "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", + "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897" ], "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==2.2.2" + "markers": "python_version >= '3.10'", + "version": "==2.7.0" }, "virtualenv": { "hashes": [ - "sha256:1720dc3a62ef5b443092e3f499228599045d7fea4c79199770499df8becf9098", - "sha256:1bd755b504931164a5a496d217c014d098426cddc79363ad66ac78125f9d908f" + "sha256:6fd04089fc0dc33549e7abdff70fc3b63d4e15799f2dbf3281f80d13b9fce522", + "sha256:719b189804e66678017d9f63bbfc590c44f6b96ab4829513806394f9b375929c" ], - "markers": "python_version >= '3.8'", - "version": "==21.2.0" + "markers": "python_version >= '3.9'", + "version": "==21.14.1" } }, "telemetry": { "certifi": { "hashes": [ - "sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa", - "sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7" + "sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775", + "sha256:741e2c3b351ddf169a738da9f2c048608ff7f2c5cc02f1ebc6b118bb090d5d55" ], "markers": "python_version >= '3.7'", - "version": "==2026.2.25" + "version": "==2026.7.22" }, "charset-normalizer": { "hashes": [ - "sha256:06a7e86163334edfc5d20fe104db92fcd666e5a5df0977cb5680a506fe26cc8e", - "sha256:0c173ce3a681f309f31b87125fecec7a5d1347261ea11ebbb856fa6006b23c8c", - "sha256:0e28d62a8fc7a1fa411c43bd65e346f3bce9716dc51b897fbe930c5987b402d5", - "sha256:0e901eb1049fdb80f5bd11ed5ea1e498ec423102f7a9b9e4645d5b8204ff2815", - "sha256:11afb56037cbc4b1555a34dd69151e8e069bee82e613a73bef6e714ce733585f", - "sha256:150b8ce8e830eb7ccb029ec9ca36022f756986aaaa7956aad6d9ec90089338c0", - "sha256:172985e4ff804a7ad08eebec0a1640ece87ba5041d565fff23c8f99c1f389484", - "sha256:197c1a244a274bb016dd8b79204850144ef77fe81c5b797dc389327adb552407", - "sha256:1ae6b62897110aa7c79ea2f5dd38d1abca6db663687c0b1ad9aed6f6bae3d9d6", - "sha256:1cf0a70018692f85172348fe06d3a4b63f94ecb055e13a00c644d368eb82e5b8", - "sha256:1ed80ff870ca6de33f4d953fda4d55654b9a2b340ff39ab32fa3adbcd718f264", - "sha256:22c6f0c2fbc31e76c3b8a86fba1a56eda6166e238c29cdd3d14befdb4a4e4815", - "sha256:231d4da14bcd9301310faf492051bee27df11f2bc7549bc0bb41fef11b82daa2", - "sha256:259695e2ccc253feb2a016303543d691825e920917e31f894ca1a687982b1de4", - "sha256:2a24157fa36980478dd1770b585c0f30d19e18f4fb0c47c13aa568f871718579", - "sha256:2b1a63e8224e401cafe7739f77efd3f9e7f5f2026bda4aead8e59afab537784f", - "sha256:2bd9d128ef93637a5d7a6af25363cf5dec3fa21cf80e68055aad627f280e8afa", - "sha256:2e1d8ca8611099001949d1cdfaefc510cf0f212484fe7c565f735b68c78c3c95", - "sha256:2ef7fedc7a6ecbe99969cd09632516738a97eeb8bd7258bf8a0f23114c057dab", - "sha256:2f7fdd9b6e6c529d6a2501a2d36b240109e78a8ceaef5687cfcfa2bbe671d297", - "sha256:30f445ae60aad5e1f8bdbb3108e39f6fbc09f4ea16c815c66578878325f8f15a", - "sha256:31215157227939b4fb3d740cd23fe27be0439afef67b785a1eb78a3ae69cba9e", - "sha256:34315ff4fc374b285ad7f4a0bf7dcbfe769e1b104230d40f49f700d4ab6bbd84", - "sha256:3516bbb8d42169de9e61b8520cbeeeb716f12f4ecfe3fd30a9919aa16c806ca8", - "sha256:3778fd7d7cd04ae8f54651f4a7a0bd6e39a0cf20f801720a4c21d80e9b7ad6b0", - "sha256:39f5068d35621da2881271e5c3205125cc456f54e9030d3f723288c873a71bf9", - "sha256:404a1e552cf5b675a87f0651f8b79f5f1e6fd100ee88dc612f89aa16abd4486f", - "sha256:419a9d91bd238052642a51938af8ac05da5b3343becde08d5cdeab9046df9ee1", - "sha256:423fb7e748a08f854a08a222b983f4df1912b1daedce51a72bd24fe8f26a1843", - "sha256:4482481cb0572180b6fd976a4d5c72a30263e98564da68b86ec91f0fe35e8565", - "sha256:461598cd852bfa5a61b09cae2b1c02e2efcd166ee5516e243d540ac24bfa68a7", - "sha256:47955475ac79cc504ef2704b192364e51d0d473ad452caedd0002605f780101c", - "sha256:48696db7f18afb80a068821504296eb0787d9ce239b91ca15059d1d3eaacf13b", - "sha256:4be9f4830ba8741527693848403e2c457c16e499100963ec711b1c6f2049b7c7", - "sha256:4d1d02209e06550bdaef34af58e041ad71b88e624f5d825519da3a3308e22687", - "sha256:4f41da960b196ea355357285ad1316a00099f22d0929fe168343b99b254729c9", - "sha256:517ad0e93394ac532745129ceabdf2696b609ec9f87863d337140317ebce1c14", - "sha256:51fb3c322c81d20567019778cb5a4a6f2dc1c200b886bc0d636238e364848c89", - "sha256:5273b9f0b5835ff0350c0828faea623c68bfa65b792720c453e22b25cc72930f", - "sha256:530d548084c4a9f7a16ed4a294d459b4f229db50df689bfe92027452452943a0", - "sha256:530e8cebeea0d76bdcf93357aa5e41336f48c3dc709ac52da2bb167c5b8271d9", - "sha256:54fae94be3d75f3e573c9a1b5402dc593de19377013c9a0e4285e3d402dd3a2a", - "sha256:572d7c822caf521f0525ba1bce1a622a0b85cf47ffbdae6c9c19e3b5ac3c4389", - "sha256:58c948d0d086229efc484fe2f30c2d382c86720f55cd9bc33591774348ad44e0", - "sha256:5d11595abf8dd942a77883a39d81433739b287b6aa71620f15164f8096221b30", - "sha256:5f8ddd609f9e1af8c7bd6e2aca279c931aefecd148a14402d4e368f3171769fd", - "sha256:5feb91325bbceade6afab43eb3b508c63ee53579fe896c77137ded51c6b6958e", - "sha256:60c74963d8350241a79cb8feea80e54d518f72c26db618862a8f53e5023deaf9", - "sha256:613f19aa6e082cf96e17e3ffd89383343d0d589abda756b7764cf78361fd41dc", - "sha256:659a1e1b500fac8f2779dd9e1570464e012f43e580371470b45277a27baa7532", - "sha256:695f5c2823691a25f17bc5d5ffe79fa90972cc34b002ac6c843bb8a1720e950d", - "sha256:69dd852c2f0ad631b8b60cfbe25a28c0058a894de5abb566619c205ce0550eae", - "sha256:6cceb5473417d28edd20c6c984ab6fee6c6267d38d906823ebfe20b03d607dc2", - "sha256:71be7e0e01753a89cf024abf7ecb6bca2c81738ead80d43004d9b5e3f1244e64", - "sha256:74119174722c4349af9708993118581686f343adc1c8c9c007d59be90d077f3f", - "sha256:74a2e659c7ecbc73562e2a15e05039f1e22c75b7c7618b4b574a3ea9118d1557", - "sha256:7504e9b7dc05f99a9bbb4525c67a2c155073b44d720470a148b34166a69c054e", - "sha256:79090741d842f564b1b2827c0b82d846405b744d31e84f18d7a7b41c20e473ff", - "sha256:7a6967aaf043bceabab5412ed6bd6bd26603dae84d5cb75bf8d9a74a4959d398", - "sha256:7bda6eebafd42133efdca535b04ccb338ab29467b3f7bf79569883676fc628db", - "sha256:7edbed096e4a4798710ed6bc75dcaa2a21b68b6c356553ac4823c3658d53743a", - "sha256:7f9019c9cb613f084481bd6a100b12e1547cf2efe362d873c2e31e4035a6fa43", - "sha256:802168e03fba8bbc5ce0d866d589e4b1ca751d06edee69f7f3a19c5a9fe6b597", - "sha256:80d0a5615143c0b3225e5e3ef22c8d5d51f3f72ce0ea6fb84c943546c7b25b6c", - "sha256:82060f995ab5003a2d6e0f4ad29065b7672b6593c8c63559beefe5b443242c3e", - "sha256:836ab36280f21fc1a03c99cd05c6b7af70d2697e374c7af0b61ed271401a72a2", - "sha256:8761ac29b6c81574724322a554605608a9960769ea83d2c73e396f3df896ad54", - "sha256:87725cfb1a4f1f8c2fc9890ae2f42094120f4b44db9360be5d99a4c6b0e03a9e", - "sha256:899d28f422116b08be5118ef350c292b36fc15ec2daeb9ea987c89281c7bb5c4", - "sha256:8bc5f0687d796c05b1e28ab0d38a50e6309906ee09375dd3aff6a9c09dd6e8f4", - "sha256:8bea55c4eef25b0b19a0337dc4e3f9a15b00d569c77211fa8cde38684f234fb7", - "sha256:8e5a94886bedca0f9b78fecd6afb6629142fd2605aa70a125d49f4edc6037ee6", - "sha256:90ca27cd8da8118b18a52d5f547859cc1f8354a00cd1e8e5120df3e30d6279e5", - "sha256:92734d4d8d187a354a556626c221cd1a892a4e0802ccb2af432a1d85ec012194", - "sha256:947cf925bc916d90adba35a64c82aace04fa39b46b52d4630ece166655905a69", - "sha256:95b52c68d64c1878818687a473a10547b3292e82b6f6fe483808fb1468e2f52f", - "sha256:97d0235baafca5f2b09cf332cc275f021e694e8362c6bb9c96fc9a0eb74fc316", - "sha256:9ca4c0b502ab399ef89248a2c84c54954f77a070f28e546a85e91da627d1301e", - "sha256:9cc4fc6c196d6a8b76629a70ddfcd4635a6898756e2d9cac5565cf0654605d73", - "sha256:9cc6e6d9e571d2f863fa77700701dae73ed5f78881efc8b3f9a4398772ff53e8", - "sha256:a056d1ad2633548ca18ffa2f85c202cfb48b68615129143915b8dc72a806a923", - "sha256:a26611d9987b230566f24a0a125f17fe0de6a6aff9f25c9f564aaa2721a5fb88", - "sha256:a4474d924a47185a06411e0064b803c68be044be2d60e50e8bddcc2649957c1f", - "sha256:a4ea868bc28109052790eb2b52a9ab33f3aa7adc02f96673526ff47419490e21", - "sha256:a9e68c9d88823b274cf1e72f28cb5dc89c990edf430b0bfd3e2fb0785bfeabf4", - "sha256:aa9cccf4a44b9b62d8ba8b4dd06c649ba683e4bf04eea606d2e94cfc2d6ff4d6", - "sha256:ab30e5e3e706e3063bc6de96b118688cb10396b70bb9864a430f67df98c61ecc", - "sha256:ac2393c73378fea4e52aa56285a3d64be50f1a12395afef9cce47772f60334c2", - "sha256:ad8faf8df23f0378c6d527d8b0b15ea4a2e23c89376877c598c4870d1b2c7866", - "sha256:b35b200d6a71b9839a46b9b7fff66b6638bb52fc9658aa58796b0326595d3021", - "sha256:b3694e3f87f8ac7ce279d4355645b3c878d24d1424581b46282f24b92f5a4ae2", - "sha256:b4ff1d35e8c5bd078be89349b6f3a845128e685e751b6ea1169cf2160b344c4d", - "sha256:bbc8c8650c6e51041ad1be191742b8b421d05bbd3410f43fa2a00c8db87678e8", - "sha256:bc72863f4d9aba2e8fd9085e63548a324ba706d2ea2c83b260da08a59b9482de", - "sha256:bf625105bb9eef28a56a943fec8c8a98aeb80e7d7db99bd3c388137e6eb2d237", - "sha256:c2274ca724536f173122f36c98ce188fd24ce3dad886ec2b7af859518ce008a4", - "sha256:c45a03a4c69820a399f1dda9e1d8fbf3562eda46e7720458180302021b08f778", - "sha256:c8ae56368f8cc97c7e40a7ee18e1cedaf8e780cd8bc5ed5ac8b81f238614facb", - "sha256:c907cdc8109f6c619e6254212e794d6548373cc40e1ec75e6e3823d9135d29cc", - "sha256:ca0276464d148c72defa8bb4390cce01b4a0e425f3b50d1435aa6d7a18107602", - "sha256:cd5e2801c89992ed8c0a3f0293ae83c159a60d9a5d685005383ef4caca77f2c4", - "sha256:d08ec48f0a1c48d75d0356cea971921848fb620fdeba805b28f937e90691209f", - "sha256:d1a2ee9c1499fc8f86f4521f27a973c914b211ffa87322f4ee33bb35392da2c5", - "sha256:d5f5d1e9def3405f60e3ca8232d56f35c98fb7bf581efcc60051ebf53cb8b611", - "sha256:d60377dce4511655582e300dc1e5a5f24ba0cb229005a1d5c8d0cb72bb758ab8", - "sha256:d73beaac5e90173ac3deb9928a74763a6d230f494e4bfb422c217a0ad8e629bf", - "sha256:d7de2637729c67d67cf87614b566626057e95c303bc0a55ffe391f5205e7003d", - "sha256:dad6e0f2e481fffdcf776d10ebee25e0ef89f16d691f1e5dee4b586375fdc64b", - "sha256:dda86aba335c902b6149a02a55b38e96287157e609200811837678214ba2b1db", - "sha256:df01808ee470038c3f8dc4f48620df7225c49c2d6639e38f96e6d6ac6e6f7b0e", - "sha256:e1f6e2f00a6b8edb562826e4632e26d063ac10307e80f7461f7de3ad8ef3f077", - "sha256:e25369dc110d58ddf29b949377a93e0716d72a24f62bad72b2b39f155949c1fd", - "sha256:e3c701e954abf6fc03a49f7c579cc80c2c6cc52525340ca3186c41d3f33482ef", - "sha256:e5bcc1a1ae744e0bb59641171ae53743760130600da8db48cbb6e4918e186e4e", - "sha256:e68c14b04827dd76dcbd1aeea9e604e3e4b78322d8faf2f8132c7138efa340a8", - "sha256:e8aeb10fcbe92767f0fa69ad5a72deca50d0dca07fbde97848997d778a50c9fe", - "sha256:e985a16ff513596f217cee86c21371b8cd011c0f6f056d0920aa2d926c544058", - "sha256:ecbbd45615a6885fe3240eb9db73b9e62518b611850fdf8ab08bd56de7ad2b17", - "sha256:ee4ec14bc1680d6b0afab9aea2ef27e26d2024f18b24a2d7155a52b60da7e833", - "sha256:ef5960d965e67165d75b7c7ffc60a83ec5abfc5c11b764ec13ea54fbef8b4421", - "sha256:f0cdaecd4c953bfae0b6bb64910aaaca5a424ad9c72d85cb88417bb9814f7550", - "sha256:f1ce721c8a7dfec21fcbdfe04e8f68174183cf4e8188e0645e92aa23985c57ff", - "sha256:f50498891691e0864dc3da965f340fada0771f6142a378083dc4608f4ea513e2", - "sha256:f5ea69428fa1b49573eef0cc44a1d43bebd45ad0c611eb7d7eac760c7ae771bc", - "sha256:f61aa92e4aad0be58eb6eb4e0c21acf32cf8065f4b2cae5665da756c4ceef982", - "sha256:f6e4333fb15c83f7d1482a76d45a0818897b3d33f00efd215528ff7c51b8e35d", - "sha256:f820f24b09e3e779fe84c3c456cb4108a7aa639b0d1f02c28046e11bfcd088ed", - "sha256:f98059e4fcd3e3e4e2d632b7cf81c2faae96c43c60b569e9c621468082f1d104", - "sha256:fcce033e4021347d80ed9c66dcf1e7b1546319834b74445f561d2e2221de5659" + "sha256:01077390b03f7988f11d700a2194e69b119741a86b1a638b1db88891e3eced8e", + "sha256:01b0c0d2262a9e28e8484a278c7e1b5d650e3ac8cf2683d2967e25899f208bdf", + "sha256:04851f73ae72b8413dddadb16a49dfee95263553741fd42d546f7d66907e6be5", + "sha256:0521c5665880b33d603717defa76c094048900010897909952397feb3039da56", + "sha256:0774bf9bf620249fee3e0b8b9fd3065de213be30f3aa94ce2494b3b638949e26", + "sha256:0891b9d3903c5571c03771ca669a4b0ec5618ca722a5c957d3d29cd4e5062848", + "sha256:0c951d5e6dd9c2ff60609476752bee49da4206adde960ebc247766937f72e718", + "sha256:0fed1d06615f022ee3b13caf5e8b180cfea32bb2c5aded8a9d44277afc040f93", + "sha256:114e4d0c92d618409ed82a99e22b5c5e768fe995f2973f78265f4524f49d4640", + "sha256:11912e4bb14baae7c5d8791aa55ba0a3a03ec6729073307b0f57270abaa713d3", + "sha256:11a4d68a6ecda3292cb1e50239e111543ba5d709bb62a6b4ea1afcfa729d8875", + "sha256:124fbf1a8ff966d87ae05bb8bd45a71f966055ed8bba320d0c7cf450bc5f4d0e", + "sha256:1461ac396c4fdb983a675f20aa555624f0ee18ac83d832b9244ffff3d8055275", + "sha256:1503bccbeb36d5527790c3930327704c39af22de3112f1b1666a9f3ce15ee204", + "sha256:15bb4005af6320d259dc7593ca84a38d7fe06a421dbcf7b910ae23979101e787", + "sha256:15c44f7edfd477b06f517a5cc317fc1707edb9de2c865f43d4b6513907473234", + "sha256:16fa0eccf81304b79c5cd87f9271c3b85dd9dd99245e4422ae9c0dd45e0f99d3", + "sha256:183b88127acdb4fabe59d951ab424faf1af7b63cdbb5f776186c1ea2ffcaed98", + "sha256:195c26fb65950f8fce54e26349852b7bdd7c5f120aeefbcc440b8a20faaed4a3", + "sha256:1afb975bd5d68d5ce9f6b6d44fdf2f7e34b895a35e95708a7a91b20a3b51d187", + "sha256:1b4cbc7c3491ccb4aa17fcd8165649d01cf39f76de1696da8631b5f71b85401d", + "sha256:1bc0baf5ef96b6ede57d47f4b8fe4d9d84019c3bfcbeb20a41edc6a6ee341f1f", + "sha256:1c50fe28bbc2ced33386f298650d91218076c05420e6cbd790b913adc41659e7", + "sha256:1db38f4c5496827c1a501846d64d14c3b80c7e6714e406cd7dc36a9899fa1011", + "sha256:211d5a3eb6af8f513b8d4ca19a8c1b7accab1b5f0d3175f9826b03c1a920dc1f", + "sha256:23851fb4e1b85ed3f6c2a27b777cdfe2e19fb5b38429a8faf38c7542b7665869", + "sha256:254eb48b9fa5ee9898a3c445825a1f340fe53712a098904b39b0bddba8ea3cb1", + "sha256:2625388c6c754520c37abaf3b41eb34d1cc4a373f457898f08606c8e362b891d", + "sha256:281cb91036248400f4cc957495cccd44c275c2e0c5854f7e45ac5cf7dc193847", + "sha256:28a15fdad492a99b6eccfaaed66ef3f74050680545ea61ec8b2f4c538f1f1320", + "sha256:28b4f0d66fb834ff90f28209ac7bce77868c45d8c93e26f906709d9b7c2e1af9", + "sha256:2a925889534b3748302dae5dead07cc13480de1dac3aea80a941b729b471ef93", + "sha256:2b7b3bbfb4fe8ef40600792d762fbaa9057559f9d3fad209525b7a22b99e91fd", + "sha256:2c9ad19a6cfcd5ea5c0d41161d22f9df1dcc277e9bef2751391334546a314c00", + "sha256:2cc961b171b3f3440f410489ab3573e86aea8736134ebbb40ea1338b7f0831bc", + "sha256:2ce45c6627b22c47e390bc91a41c3d13032192e699fa0bea96e9671b373d69b0", + "sha256:2e06a3a98f916dd41d27f3105e02e7a40181c98c94b9158733d03a6f80506c09", + "sha256:304d5463e65a35d7bb0850550e0780395395f6fcf452f04db7d5ca7cecc425ac", + "sha256:304d8e4d493af723536393eee0c689eb7813f4a474c8b479dee63f1fdd98f621", + "sha256:30fcd120b732aa79317f08dee04d7de0847822e4cf7ee0e9f445bb958832252c", + "sha256:31f3930700408d211f13378ccbe1c40845d8da54bd0681fac3a9b5aae81c7aa8", + "sha256:34276fd796040bf0993ab33a369aa572e6979c7aab225a88893667ad8eac8f7a", + "sha256:355ad8011081dec5412240c087a9a0c9d4d5039f3ed11a3f13e18c2b29b56c51", + "sha256:38a873987f3be698494da8b2e3085e29da02da7b633dce73e79c699a113d7bf0", + "sha256:39de2a259fc954455c57274dc94c79d5842774e1247a016aff30bc0efed0f4ef", + "sha256:3d14b50de6bf4d0edf857a9386836846f982b8f524e188e2e68b96d702bcf4aa", + "sha256:3d21b8b13c7592db2ac5e544a6d83187b995257472b0c9e8351b6d507ae37ed6", + "sha256:3d31298449090ab8d47b7b1b2a555ff73cac7ed438a08b7ac160980c7ebed649", + "sha256:3ddacd27458c45bdacd6bd6db644bfb730efbf9e830310186e3045c9c5be8fb2", + "sha256:3df041de8887954562c9b261cba85ca0e9ded74048daf125f45edcfaa4832229", + "sha256:40ab6bffa02ae10a0581e6c198be7d2d8ca5c2a0c64e4ed3465d766df457573e", + "sha256:4275811936e2f06feff5e598fb42a1b7ae852da8e39605211892b56b81a34efd", + "sha256:443eae2bf318abeaf6f15d785138f71fd6de770e99a92158b8b814265e079115", + "sha256:447441e76ec720b15e64418d32e092297340387053047c7c694f579efb0ee1d9", + "sha256:4495c5002a7b28557e7e222e77e0b661183e432b7d6d2e788101e3f240e05b8c", + "sha256:44bd4fbb29dfbeba60e7d2bd000c59e4b21ddb3cc53912b14048d37092706d7c", + "sha256:4685902cf26edf013ed7a3da0f426ebba7a00ebb9541386d835afbf002c11cab", + "sha256:498dc3188ca05a68231ac3fdbfc7f57eb67e1343c30e0fea17f8218c1599b253", + "sha256:4c2b5031f63e331e3839b40aed2dd6f191e9c07edbde303e7876846ea1946995", + "sha256:4d48f2d08b9de5864e2c8744d4461b862fb149a18274abc8b698c45975573438", + "sha256:4f87960d57feabfb618e4e0af6e7371645fa26a277860739d6e5d6e0012c92f0", + "sha256:50e3adfb96fc189eb27b1cf62d3b598b89b4bb0420d93a3d3e42e137409011be", + "sha256:51cf45226a9b588d0d2b4880c62d686934b63ab0bd79ca23ab0e9762eb27441b", + "sha256:52aa6992700996af31f375de0c6bacd402b0097fe40b53c426b9f51a90ebabc7", + "sha256:55ea99acb17b9325618de155a0cd6a2e8f5d10be008113e1d433bbb58db543b2", + "sha256:56bc200a365efb37383b7852e4cc5898d3b2da5987289b543956cf8cad71018a", + "sha256:588461c2e8384d309bd63e5826019b6977bc66d629b99ac8737bb795d7b2cb5a", + "sha256:58ca3755ee7ff7f59b57789ec9833c9de9ea275405cdd240eda1f193112e398a", + "sha256:58f361dcbab699cf8f42db3f47c8e7fd1036f138c23a5d08de9fde5f425a730c", + "sha256:598a11a2c7ebaa5334bf698bf29568c9c390abac6a154d8170fedecd1cea38c5", + "sha256:59f63901b0031c3136cf64704dcb21de0bbae62ce2c9529bc39d27665463de37", + "sha256:5cde776b7cc66e4f6c99612cea4aa7269aa65863f7a15841b2c264f103822f4e", + "sha256:5e2b6b57e9733d39f0c9fd3185efa6b8e29652c4cd8fe94180272cf6ed9a78c4", + "sha256:5fb29fb8cd1a46c27a1bf9613ad5ec2599310d46b4025d9556404a6b6a292800", + "sha256:6045373d5a89a5ec71afde535db987ca28e76dfa276c2d4c818265b375d4b055", + "sha256:619799369eeef6366ed3e8755a5670f4f2f0fb6b30a0fd7264dc0fdc2357058e", + "sha256:62588a277bfb59def052abd940703fa35107152bf479781a878617d60faf8fb5", + "sha256:62603db9a7caa0802eaa28c1c46fecd7b3a263a774069c24c3c28c302448721c", + "sha256:65cd72beeeca9d3aaea1201e5923859f308f952f9c71de93f06063c79f0f7a3b", + "sha256:68eb192d85ab8e5f6ec69c2bc6ac0179fbf04a5ac1569d12fbef74883fe102d0", + "sha256:6bd128f206a7752ae1f2ab6c61bf8a24ba28913a10df8b14c2637b973ff97a80", + "sha256:6be488a102b8cf28d0391d8c4ba7748938ae28b78ad901f8585520fca33ead1a", + "sha256:7218e8f32b0956cfcd048fd42d9d5779809745ca1d86113ca56f66e7ae1549c4", + "sha256:7441d755b7ab94f8d4eb3e43ec05482d760842fd263d003a99102d742cd835e2", + "sha256:749e97e1b32313717a565abbe321bc2190bc8b35f1a67e4cdbc7c56c8d8ffe58", + "sha256:75a3ceed0724d625d64b86ca20aba182e4df462e04c2414fc941c0f523f06aac", + "sha256:780fbe7cab297b81dad9fb8dc5eb003c0468ffb0d9e5f65068c53a34661a96bc", + "sha256:78456a747de8dc58360ffa581f30a002baf5aa28cb262536545e91f113ed7639", + "sha256:7967d08cf06dee78443b874f98c98036f624f3a4e73e11f9f64f5be4d25393cf", + "sha256:7a881931aa470808df94a8c380eed2bbbc76cd9dc622310f99665658c821eb6d", + "sha256:7dcd882da75ef9adf94903b1e3b9419e8aa8fb4c7396822b834b9ef7fb96954f", + "sha256:7e841fb9010836c992c9f12fcbd43a831de93a5f726fc1ccd8ca1d0268c5014c", + "sha256:7fdde2c9fd9e3eca40631e024664cf2584272cc8f96308cbe5fdfc930f51d8bc", + "sha256:8024d00c3faf3fc0c16e07a69f4405e8eac7cc0ab15f65fe6cf43827c4cf72b4", + "sha256:80d02b6f04e92601a081dd97b23d3128033098bff5d35d392ddcc0476ea11253", + "sha256:838dcc90063569a0448120554591a1d6c4a4ffe11babf048908793154ab86ade", + "sha256:849df64e889b2e17230d58410a03dba311a65b163508fd33679b2b737d4b7858", + "sha256:87475fabc8d9996fd9c27debb395e642e8c838d78a00b6e932227a0e06b81e26", + "sha256:87e50a3e7cb90af586b6c5faf23e302a970415ac73bd7bd90a515a04b427ef96", + "sha256:89b53f3cda69831909888e0494f4fa0bcd3537e3e138dabeb620bd6ad946bae8", + "sha256:8a893cc101149f80a653f82062ebc95b34525a2614382e1da5458fe7c6997249", + "sha256:8b2bfab86aa71ae13aa41a6a26aab338e0db2b8bc75434b05aea89e011ff35a4", + "sha256:8d86d6fc60743dc916eb79e2eb1ec4818e21e427731543af40a3021851174a13", + "sha256:915563965d418f986e7e145accc592eae9e1a1be3566ff98a05d7a9ec42a76e1", + "sha256:92888bb3187c5ba50500b00b3b310c9f2c651709d28036077680cb5255450a03", + "sha256:93223adc95033dd47133a46ccfc316a0139176fd79085762e27202ec56018f03", + "sha256:9373ad13ef0d2c0fb761e04e55bfdee5a08b52cef2c882c8fbe9935b1517152e", + "sha256:9409a8bf35cf78353942504b24a57de3d75b708997a1e4bd8db71ac8633ce364", + "sha256:9b7f416ff0978e2f2249330527f0ad6fa02f4932e6199692d3b52da2048c19e4", + "sha256:9bde855991b7e362c146535e3136a50bfaffc0487d38b33ca7e5edefc6e23849", + "sha256:9cae88599c7219005d879f98e5ed53341e9a122af585e1091200358a3003d2a0", + "sha256:9cf9b1a857e25c4baceeb3624e92a56df3668f398c4acba74e174d81fb4d1d3a", + "sha256:9f56f72050826f63dcee7a7f55b0a77168cb3bfc553fd405e7f8f9ece75a4036", + "sha256:a090bb2c68df85450502e3e20d665e3a5af9c65a84d6508ed477badd49166fd3", + "sha256:a192e2c40070d92c3ccf777e3a5c4ff515573cd2bb7ed0c537fdadbbec5bbf21", + "sha256:a19a731138fc27d5682277d3b9df22855cea1239bce7fcec5f78f42ef2d1f3c3", + "sha256:a66c3bc5ab1f0ff2164fc9965ddd611ff0802173f4b9d24554c563f6ab7e1d6e", + "sha256:a815775b6c38d4e0ff7bcffbeba67feded90202bb6a226b8dd35f1c855217413", + "sha256:a89012d6d5476ee112d20d998570ed58df2260a852afb1758809cd6900411d21", + "sha256:ae4f5fea5b8b8ccff88238cc8569303e5ee95efae67fa62922a311397a71f346", + "sha256:b6856554c4f44d79fc2307d5768854310a8f0096e501c75637542c82292b0429", + "sha256:b6b751274acb69d77b3323d6b7dbaa3c7fdfc1eb829b7eb61d262f32e1af9685", + "sha256:b736353c0a625bbd5fcec108576e2385db3496f4f771f785ff32e108d3c3bc45", + "sha256:b7fd005a73d9e657273b7a10dc71a9e03c8fb9ee6999798d6918ce095b81ac7f", + "sha256:b91363207bd9dc966a691e959bb47f64b30f7ac4b072be9968b366982f7db77c", + "sha256:ba0b1d2620edf869789c3879223f52bf2afc5d31b3cb47cc57b3a12c05e2aa9d", + "sha256:bbbfc8e28816f19d7c0f1816664980c0a9875d01b27cdf8eedddb639d9e108ad", + "sha256:bd16aabe4a02a297c23417aa17ac6299dbd8c49f673bcd645b4929b11f5a4400", + "sha256:c0afc6800ba57ccc350374c5bd6150419915d95ce93cdbab2d783d75eaf30ecb", + "sha256:c6708715abcf3c73b99508253e961a9967f02fe536532834149574eda6de0d1c", + "sha256:c7c9ab723cde841fefb34efbad91e87f00a674b1fe1cd0784fde742bf2c154dc", + "sha256:c8f3d67aeaf55f017982b73683f0e7342ba2f6635a78f69ce89ebb26aa411e5c", + "sha256:c9790464842f85f437dbbb54417eda1e0e6bfc52dd8d22d6fd1c994b73b2dc74", + "sha256:ca403d7e4798f525fdfc78e258820419cbbd0f0ecbab9de7840e3c017cf6b8cf", + "sha256:d008d90a7f2471519aef0c90dfbe73b3e6e4d5e66ac48e19154c17e89e98b604", + "sha256:d19fbd981a488e22cd04883659ca6b08f50b5974f9fd7c95655ef6a043e5893f", + "sha256:d1befeed746d247c81127bb14de9dc3d30edb6e5976d34f83f86ed262b1d9105", + "sha256:d2374b62878abb00cd8309b32af6c0b715cd02dec0ca74ef12e5069bdc64144a", + "sha256:d376bbd28b3a8999db1a103b3b388aee6f1ddeb3e51bc2172993efdcd86e064d", + "sha256:d4a7319f304a774bed22115bc891618e45f85065ab44ea6acd07d274e750519a", + "sha256:d6734d2ef8a50fbf8445c139477da401f50d62a0606bf00e20ec6d87773fefb1", + "sha256:d760fe2a4d7c3b226cb9026d6a842868d52a7901bd98420e1baf14e80da85cf5", + "sha256:d913de495d90407cd859d263bee2e5d1a4ed3eb6573c04e70d9ec619a7cbed7f", + "sha256:db19d07e2e0129e974a0e65d0064fc222a446cd5122c2fd4184d2af9fc734a9e", + "sha256:dca9ab98072a5a54ebacebdc45f53e645336b320c667410b061be1ca588ae709", + "sha256:ddc7dacc8ece3a182e7f15cb862d1fd616b46d076cb1ae9dd232b2c38b655874", + "sha256:ddf19c062bea7a0cc80f519243d2c01dd091be0cf952a0750d4ad576709559f5", + "sha256:def79fa35ef0cef8d2accec024f4fdc7ead3012ff02f5215c783f39f03ef8cfc", + "sha256:df29a0a7107f7011e77f4eebdddec4c7331e24d787a0b21a46d63bdf7445da95", + "sha256:e09a3942ecbdee5cce73ea9d42da82b81b72ac1bf031ce069b93b5adf4eac8cd", + "sha256:e242bb1c5e76e97dfa9e7f209a71e93a01d7f19ffdd5cfbb2e2d55b4f08f8ab0", + "sha256:e243bd13217235fc7290c621941c3f5cc8b66e4872495be821d7436ba2fb838d", + "sha256:e2af3aad578aa6bd1384bcf4750fc285e5a9de53f40b7d41e5a0bf748edeb2b3", + "sha256:e4e81e09c1578b8df602e3db08b0b3ea0a6947ad612f52bf8dc5ea8d47691f0c", + "sha256:e54da4baf05720032d527874d40b65fa4d7e5c6c6a43d0c3adbeffcaf275a2b3", + "sha256:e80e6c2f55656b4824d72065abb4ddd6a525c74bd78a0aab5d9fc2cf4fb5af50", + "sha256:ed2a239c0ea213acc1908150a3037257083c7c083128f1a4cec2ec4b97dca491", + "sha256:ed905975ab14056a2e5eb1c376cb2e1ebc5396baf84163939c518556fccde9f5", + "sha256:ee21e28f0430bd6dc9086c6e525d5e818a44a5ad19720c8a0ef766792f3eb5e5", + "sha256:ee43c17b173d46a3212baa6ead3ae258eeabdae48c263a01ccf0218c366dd655", + "sha256:ef4fcbf3327382cd4c9f540babd61248208af7b93eec4de397b4d5f58a09e288", + "sha256:eff0ac9dbe711a4aee69bf04a83896aa9b85f19641264053a9f6d48573abb7dd", + "sha256:f0aa869112ef88429ae17820d99c3dd9504c9e9c671d3c246f3d7442cb051084", + "sha256:f3c96f633825733f735c5a9cf21d21a257d8e1edf0b1cee0a064b9c424ca0f7d", + "sha256:f5833ad231be5eb6553de524a70f48d71b2c8563101750531e0b80184e175cd4", + "sha256:f5ec61164adcec446f8969a3358ec3f9b26bbda3b9213e5586d219afa8df2915", + "sha256:f7d486c83842422badd511868fd8a9a20e9407ace71564b6af47ce7e60a336c1", + "sha256:fb9e68df06293761f9fe66ade60a9bc6d0f5e42b8acf2939a9158af86ab0e5bd", + "sha256:fc14a032f813bf5fe624d991960ea83e9715adc27e4c1830a2361eb1d02ac341", + "sha256:fcff63213e8e6e47770541a4607175404f47cbb3ebea7b6058cc82d524a0e424", + "sha256:fd1fbe0f116b6e55da77aca2c6ddcddcfac2186cbf78bdebf40fc156efca389d", + "sha256:fe9753dfee015c570d73df76f899f18444d41388bffcde097deba51c4fadbb9f" ], "markers": "python_version >= '3.7'", - "version": "==3.4.6" + "version": "==3.5.2" }, "googleapis-common-protos": { "hashes": [ - "sha256:13114f0e9d2391756a0194c3a8131974ed7bffb06086569ba193364af59163b6", - "sha256:e51f09eb0a43a8602f5a915870972e6b4a394088415c79d79605a46d8e826ee8" + "sha256:c7a866fc34ed29a3b10af627a4b9b1dc2433313ca6e959f0ae4feb132047ed72", + "sha256:d7285525c23039db98f2463e6d5a4f9b958b94d497f03a844ece3259c4e72d5d" ], - "markers": "python_version >= '3.9'", - "version": "==1.73.1" + "markers": "python_version >= '3.10'", + "version": "==1.75.5" }, "grpcio": { "hashes": [ - "sha256:00168469238b022500e486c1c33916acf2f2a9b2c022202cf8a1885d2e3073c1", - "sha256:02e64bb0bb2da14d947a49e6f120a75e947250aebe65f9629b62bb1f5c14e6e9", - "sha256:05d55e1798756282cddd52d56c896b3e7d673e3a8798c2f1cd05ba249a3bb4de", - "sha256:09e5e478b3d14afd23f12e49e8b44c8684ac3c5f08561c43a5b9691c54d136ab", - "sha256:0cb517eb1d0d0aaf1d87af7cc5b801d686557c1d88b2619f5e31fab3c2315921", - "sha256:1b97cd29a8eda100b559b455331c487a80915b6ea6bd91cf3e89836c4ee8d957", - "sha256:256507e2f524092f1473071a05e65a5b10d84b82e3ff24c5b571513cfaa61e2f", - "sha256:29aca15edd0688c22ba01d7cc01cb000d72b2033f4a3c72a81a19b56fd143257", - "sha256:2bea16af2750fd0a899bf1abd9022244418b55d1f37da2202249ba4ba673838d", - "sha256:2dcc70e9f0ba987526e8e8603a610fb4f460e42899e74e7a518bf3c68fe1bf05", - "sha256:2ed770b4c06984f3b47eb0517b1c69ad0b84ef3f40128f51448433be904634cd", - "sha256:31b9ac4ad1aa28ffee5503821fafd09e4da0a261ce1c1281c6c8da0423c83b6e", - "sha256:33eb763f18f006dc7fee1e69831d38d23f5eccd15b2e0f92a13ee1d9242e5e02", - "sha256:367ce30ba67d05e0592470428f0ec1c31714cab9ef19b8f2e37be1f4c7d32fae", - "sha256:3b01e1f5464c583d2f567b2e46ff0d516ef979978f72091fd81f5ab7fa6e2e7f", - "sha256:3cb8130ba457d2aa09fa6b7c3ed6b6e4e6a2685fce63cb803d479576c4d80e21", - "sha256:3d4147a97c8344d065d01bbf8b6acec2cf86fb0400d40696c8bdad34a64ffc0e", - "sha256:43168871f170d1e4ed16ae03d10cd21efa29f190e710a624cee7e5ae07da6f4f", - "sha256:448c884b668b868562b1bda833c5fce6272d26e1926ec46747cda05741d302c1", - "sha256:4560cf0e86514595dbbd330cd65b7afad4b5c4b8c4905c041cfffa138d45e6fd", - "sha256:46c2390b59d67f84e882694d489f5b45707c657832d7934859ceb8c33f467069", - "sha256:4e78c4ac0d97dc2e569b2f4bcbbb447491167cb358d1a389fc4af71ab6f70411", - "sha256:4ed39fbdcf9b87370f6e8df4e39ca7b38b3e5e9d1b0013c7b6be9639d6578d14", - "sha256:50a9871536d71c4fba24ee856abc03a87764570f0c457dd8db0b4018f379fed9", - "sha256:51b4a7189b0bef2aa30adce3c78f09c83526cf3dddb24c6a96555e3b97340440", - "sha256:52d143637e3872633fc7dd7c3c6a1c84e396b359f3a72e215f8bf69fd82084fc", - "sha256:5c07e82e822e1161354e32da2662f741a4944ea955f9f580ec8fb409dd6f6060", - "sha256:627fb7312171cdc52828bd6fac8d7028ff2a64b89f1957b6f3416caa2218d141", - "sha256:68e5851ac4b9afe07e7f84483803ad167852570d65326b34d54ca560bfa53fb6", - "sha256:7b641fc3f1dc647bfd80bd713addc68f6d145956f64677e56d9ebafc0bd72388", - "sha256:8502122a3cc1714038e39a0b071acb1207ca7844208d5ea0d091317555ee7106", - "sha256:873ff5d17d68992ef6605330127425d2fc4e77e612fa3c3e0ed4e668685e3140", - "sha256:886457a7768e408cdce226ad1ca67d2958917d306523a0e21e1a2fdaa75c9c9c", - "sha256:8ac393b58aa16991a2f1144ec578084d544038c12242da3a215966b512904d0f", - "sha256:8eb613f02d34721f1acf3626dfdb3545bd3c8505b0e52bf8b5710a28d02e8aa7", - "sha256:92d787312e613754d4d8b9ca6d3297e69994a7912a32fa38c4c4e01c272974b0", - "sha256:93b6f823810720912fd131f561f91f5fed0fda372b6b7028a2681b8194d5d294", - "sha256:9a6284a5d907c37db53350645567c522be314bac859a64a7a5ca63b77bb7958f", - "sha256:9fe648599c0e37594c4809d81a9e77bd138cc82eb8baa71b6a86af65426723ff", - "sha256:a1dc80fe55685b4a543555e6eef975303b36c8db1023b1599b094b92aa77965f", - "sha256:a361c20ec1ccd3c3953d20fb6d7b4125093bdd10dff44c5e2bbb39e58917cedc", - "sha256:a72d84ad0514db063e21887fbacd1fd7acb4d494a564cae22227cd45c7fbf199", - "sha256:aacdfb4ed3eb919ca997504d27e03d5dba403c85130b8ed450308590a738f7a4", - "sha256:ba0915d51fd4ced2db5ff719f84e270afe0e2d4c45a7bdb1e8d036e4502928c2", - "sha256:ba0db34f7e1d803a878284cd70e4c63cb6ae2510ba51937bf8f45ba997cefcf7", - "sha256:bac1d573dfa84ce59a5547073e28fa7326d53352adda6912e362da0b917fcef4", - "sha256:c51bf8ac4575af2e0678bccfb07e47321fc7acb5049b4482832c5c195e04e13a", - "sha256:c624cc9f1008361014378c9d776de7182b11fe8b2e5a81bc69f23a295f2a1ad0", - "sha256:c71309cfce2f22be26aa4a847357c502db6c621f1a49825ae98aa0907595b193", - "sha256:ce1794f4ea6cc3ca29463f42d665c32ba1b964b48958a66497917fe9069f26e6", - "sha256:d334591df610ab94714048e0d5b4f3dd5ad1bee74dfec11eee344220077a79de", - "sha256:d8e11f167935b3eb089ac9038e1a063e6d7dbe995c0bb4a661e614583352e76f", - "sha256:dc053420fc75749c961e2a4c906398d7c15725d36ccc04ae6d16093167223b58", - "sha256:deb10a1528473c11f72a0939eed36d83e847d7cbb63e8cc5611fb7a912d38614", - "sha256:dfab85db094068ff42e2a3563f60ab3dddcc9d6488a35abf0132daec13209c8a", - "sha256:e172cf795a3ba5246d3529e4d34c53db70e888fa582a8ffebd2e6e48bc0cba50", - "sha256:e9e408fc016dffd20661f0126c53d8a31c2821b5c13c5d67a0f5ed5de93319ad", - "sha256:ec0a592e926071b4abad50c1495cd0d0d513324b3ff5e7267067c33ba27506e4", - "sha256:f14b618fc30de822681ee986cfdcc2d9327229dc4c98aed16896761cacd468b9", - "sha256:f49eddcac43c3bf350c0385366a58f36bed8cc2c0ec35ef7b74b49e56552c0c2", - "sha256:f7691a6788ad9196872f95716df5bc643ebba13c97140b7a5ee5c8e75d1dea81" + "sha256:026d757df86c5b7a41de8200b9a2cda454aaa5004cb0c7e3374c66eb82f61499", + "sha256:06619ba1515e5ee69fb2a514e95dd8be05ce74cb3928d5b34f87f87c86fe3c27", + "sha256:08735e3d08d24ab3132cf87e2e5dea8746cabcc7d676c2b0b7362f195feef9d9", + "sha256:0d532ade4486dad9b302ffa4d4683d67561051c26d17c4023322845e9fa10140", + "sha256:158c1c11cfb61b4849c3caf4d52de6f5ecd376e14446feb4a90dc95a90d616f5", + "sha256:15bb76489e337fc492685c9758e2fd4d4ab516b901ad830dc5a91987decf00be", + "sha256:19aaf172fc2edbefccce3f6e92c5150975dbe56c45744e9e87cf72ebdf85bfbe", + "sha256:209414080da8c20af94df1395b635da52dd57b5edc9e917e1deca0dc1c4bb55e", + "sha256:210e4c32f907045eb8158273e60c6ab69a3947697df6245dbda381f26c59485b", + "sha256:23e6e8e8a75cff88e0a793bfd3becea03a13e2763ae90c1ff573bc19ca5b429a", + "sha256:27b8b36200a9fbee6e120246f4a8a41657549107ef19fb2c819c4b2fd524f39a", + "sha256:28d2609691da93051e998495108bbddd2a9f7a561253bae94828d81290f30c15", + "sha256:2c024da73b296f040b8360e60bd73a659b230093684a438da0e1260f34cc724e", + "sha256:393d8a78bff6731ecc5ad2151a821f8fbc1709b137ebb9c25a4ef399fbdcc914", + "sha256:3d6a82c4fc6c85f2fb7572c86bdb86f84c97b6580e5f6599f711800bac48a5d8", + "sha256:3de427b05f244ba2c2a9bdc67e7a6731c8340811524ecc4435466549f8af1d17", + "sha256:406583b4e8fb2282ebd392e12b963e601c1f82e07125a8c2cb5b144e7e024796", + "sha256:4119efa6519871719ad81f33bc95ab87857dcb1c5801f30a6e592f2c41164169", + "sha256:42959bd50dd660ffc3f2a9bec15a6da4f9aaa0dda555d59ff2d2e80b908456a8", + "sha256:455ed6083353b8e938f1d58c765eab2fbb165731e5b507be30fee344915a2a11", + "sha256:465eef3d17e59ad22a556fc0138f7c7c799df426734344daec42c797d49fda99", + "sha256:47ecf0d9b81d981f07b61bd89eced9d2582f5eaacc3aaa36ad27f81aef70a27f", + "sha256:49717e857899f4136d7657bf5aded61ac479110a075438290923a4d86af7cd02", + "sha256:4aaeceeb7fa7d824c322d1ec3208c8495c88478a927295553235435fc49043ad", + "sha256:57dc36a5ab0e676f5f6e171de2917fd0aef73f32a9aaf23956bfe19997a30bd1", + "sha256:5933a052946873d01a42119a05420d669bdca436aeba2d1851988ccb12b421c0", + "sha256:5deda5b4bf62769eb98c119cca43d40e1231e34846b19db5cdea821d446a2253", + "sha256:61386101ecaa096b694d0dd278caf99a56aeec78440cc17e918eef0b50f2d567", + "sha256:659728f20fc7a0933ed7b1945435e31014b97ab8a5a7edcbaa70da4794aeb191", + "sha256:70bb4ce8be0c5606bec259cbd7152374470396413b7863a658a08c849e6b29ff", + "sha256:71fd60e6e426d293d0a2f685115ad0a0845117602cf13605a4be7524fb5f7bba", + "sha256:756ea5c2da00fa65c930284892d2a9706828704ca3ba40b4c51c4834eb39fcfd", + "sha256:800b7e00d92553313c0463c200087930aa78678ec1d528193aeb50906f55989b", + "sha256:82da34ae4f639c73ac46e521e00c0a49bf86f717b9fb1f405f133e98731e38dc", + "sha256:8e1a45d174b6b8589f51dce1cea804aa6c1f72c9c80cba91ae2caabeb6d90540", + "sha256:8e3f508d0e9e6236ba2f08d56e33355e434e785e813149a1b8477d3edf69779d", + "sha256:986e9751d416d7a6eaa2fecdac38da63153d63a4b340ba7d624889c490451500", + "sha256:9b73836ba0e16fcbb57c31cf6cbc2907c8d8c790b83679df454b74bd15e0be04", + "sha256:9bab4cf571653a8afffb83ce21aa27b51dfe629b526b7b6adec35491fe1fc2ea", + "sha256:a71d24f40b0cc6798feaa978c7411dc1135b7018e9fc0442db611c139bf58344", + "sha256:a9383401d9f116f98cacd4eba6c505a6edb80ba65badfc8e8ed8ae64983bcc44", + "sha256:b44f0a0fc7bc6677d38cc80bca1a32814ce6c8f200fb8b3c1a61c9d77eaefbf3", + "sha256:b5c6f20d657ae09ae4e30d9d3a21edd13f1219d58cc6f999b9d1bb63be9c1baa", + "sha256:b61692f0069b3eee2fc8a3a1b7f6c044df9e03fede6ce69b3ca832e1c39f26c5", + "sha256:b8c62888c3e49debf37ad9773e3c02f77b0c1e811f8fb0962f2b6c3bbab5b97a", + "sha256:bd8ea8eb3817b226057cc1c0e7ec4b378dcda52043b972b6ff12b1152178967d", + "sha256:c5559b492007dc09b4de9b95dab05f0b5e53547aad230cf07e46c7dd017a3be5", + "sha256:d0fdd25faece8a1f95e8a3a8006e29701b5cf8dadb4a8132e68f3134637004a5", + "sha256:e094dd21f077af8194923fc263cad872eaa1802bb0156fd7e5ae18e99cd86715", + "sha256:e41c3993eee896c617dbd8a505085d28b6e84a0445ed9a1f40f95808473cf678", + "sha256:e88d304f094f4937bc27ec6a435e218a084168f11ec630c8d5d39b431d08d81d", + "sha256:e90e3bdf7b5eac005fef631adae9cafde16f922def207b80a7c46b253c18ad20", + "sha256:ed2c1493c44d0932f1e55fdb5d1ead658c68288ec5d51b8c4928422d98633ef9", + "sha256:edb6f87fc60ff438557291501b3e16c7a77c3b01a52d782cf276dccc7c5dd89c", + "sha256:efb29f8633bf6630dc89de4fe0353ac3d7e4b70ef7b6e29fb40f00e68c127fa5", + "sha256:f6c972474ce691aca74e58d17625450cef153dc4760364cadeb167983ea6d589", + "sha256:f6d178ba6dc8e82976c184b65fddde172d054c17237993a3e083efe4f134d55b", + "sha256:f9a456bdbed52a01c9ab8423bdebab04a5363c78676edc55ab9b58bd13bdf9e1", + "sha256:fbdbcd06986ede3ce584083b1dc2afe6808e8943e5cf50ad11183c03aceda25a", + "sha256:fc66cb50c93554b86db0b6625ab5c6e9051dbf8847c08d93c84918e02e413fb7", + "sha256:fff5ef3fe1bba7d6147e5f19e01e5e122ac2c076486887ddcb8d42e663400fbe" ], - "markers": "python_version >= '3.9'", - "version": "==1.80.0" + "markers": "python_version >= '3.10'", + "version": "==1.84.0" }, "idna": { "hashes": [ - "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", - "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902" + "sha256:a7db850025b95ded1eae8a46181a1a6c56c92c96f0e2b005d9ff8dc0210cab44", + "sha256:ab7ae7122974553370f0bdb919e1a960b2cd1bc1ef0276416d896db81c14582c" ], - "markers": "python_version >= '3.8'", - "version": "==3.11" + "markers": "python_version >= '3.9'", + "version": "==3.20" }, "importlib-metadata": { "hashes": [ @@ -3131,146 +3426,146 @@ }, "opentelemetry-api": { "hashes": [ - "sha256:159be641c0b04d11e9ecd576906462773eb97ae1b657730f0ecf64d32071569f", - "sha256:82dd69331ae74b06f6a874704be0cfaa49a1650e1537d4a813b86ecef7d0ecf9" + "sha256:2edd8463432a7f8443edce90972169b195e7d6a05500cd29e6d13898187c9950", + "sha256:fbde8c80e1b937a2c61f20347e91c0c18a1940cecf012d62e65a7caf08967c9c" ], "markers": "python_version >= '3.9'", - "version": "==1.40.0" + "version": "==1.39.1" }, "opentelemetry-distro": { "extras": [ "otlp" ], "hashes": [ - "sha256:975b845f50181ad53753becf4fd4b123b54fa04df5a9d78812264436d6518981", - "sha256:f21d1ac0627549795d75e332006dd068877f00e461b1b2e8fe4568d6eb7b9590" + "sha256:581104a786f5df252f4dfe725e0ae16337a26da902acb92d8b3e7aee29f0c76e", + "sha256:8b7326b83a55ff7b17bb92225a86e2736a004f6af7aff00cb5d87b2d8e5bc283" ], "markers": "python_version >= '3.9'", - "version": "==0.61b0" + "version": "==0.60b1" }, "opentelemetry-exporter-otlp": { "hashes": [ - "sha256:48c87e539ec9afb30dc443775a1334cc5487de2f72a770a4c00b1610bf6c697d", - "sha256:7caa0870b95e2fcb59d64e16e2b639ecffb07771b6cd0000b5d12e5e4fef765a" + "sha256:68ae69775291f04f000eb4b698ff16ff685fdebe5cb52871bc4e87938a7b00fe", + "sha256:7cf7470e9fd0060c8a38a23e4f695ac686c06a48ad97f8d4867bc9b420180b9c" ], "markers": "python_version >= '3.9'", - "version": "==1.40.0" + "version": "==1.39.1" }, "opentelemetry-exporter-otlp-proto-common": { "hashes": [ - "sha256:1cbee86a4064790b362a86601ee7934f368b81cd4cc2f2e163902a6e7818a0fa", - "sha256:7081ff453835a82417bf38dccf122c827c3cbc94f2079b03bba02a3165f25149" + "sha256:08f8a5862d64cc3435105686d0216c1365dc5701f86844a8cd56597d0c764fde", + "sha256:763370d4737a59741c89a67b50f9e39271639ee4afc999dadfe768541c027464" ], "markers": "python_version >= '3.9'", - "version": "==1.40.0" + "version": "==1.39.1" }, "opentelemetry-exporter-otlp-proto-grpc": { "hashes": [ - "sha256:2aa0ca53483fe0cf6405087a7491472b70335bc5c7944378a0a8e72e86995c52", - "sha256:bd4015183e40b635b3dab8da528b27161ba83bf4ef545776b196f0fb4ec47740" + "sha256:772eb1c9287485d625e4dbe9c879898e5253fea111d9181140f51291b5fec3ad", + "sha256:fa1c136a05c7e9b4c09f739469cbdb927ea20b34088ab1d959a849b5cc589c18" ], "markers": "python_version >= '3.9'", - "version": "==1.40.0" + "version": "==1.39.1" }, "opentelemetry-exporter-otlp-proto-http": { "hashes": [ - "sha256:a8d1dab28f504c5d96577d6509f80a8150e44e8f45f82cdbe0e34c99ab040069", - "sha256:db48f5e0f33217588bbc00274a31517ba830da576e59503507c839b38fa0869c" + "sha256:31bdab9745c709ce90a49a0624c2bd445d31a28ba34275951a6a362d16a0b9cb", + "sha256:d9f5207183dd752a412c4cd564ca8875ececba13be6e9c6c370ffb752fd59985" ], "markers": "python_version >= '3.9'", - "version": "==1.40.0" + "version": "==1.39.1" }, "opentelemetry-instrumentation": { "hashes": [ - "sha256:92a93a280e69788e8f88391247cc530fd81f16f2b011979d4d6398f805cfbc63", - "sha256:cb21b48db738c9de196eba6b805b4ff9de3b7f187e4bbf9a466fa170514f1fc7" + "sha256:04480db952b48fb1ed0073f822f0ee26012b7be7c3eac1a3793122737c78632d", + "sha256:57ddc7974c6eb35865af0426d1a17132b88b2ed8586897fee187fd5b8944bd6a" ], "markers": "python_version >= '3.9'", - "version": "==0.61b0" + "version": "==0.60b1" }, "opentelemetry-instrumentation-celery": { "hashes": [ - "sha256:01235733ff0cdf571cb03b270645abb14b9c8d830313dc5842097ec90146320b", - "sha256:0e352a567dc89ed8bc083fc635035ce3c5b96bbbd92831ffd676e93b87f8e94f" + "sha256:896bb9eda2d7c4a39bbc5bee2caae9c06a3a41ba283bafc414b224bc8a0f04c8", + "sha256:ee946f85a3e6893d8edf09402c2c773cacc09854dcea35ae2a694320f85403cf" ], "index": "pypi", "markers": "python_version >= '3.9'", - "version": "==0.61b0" + "version": "==0.60b1" }, "opentelemetry-instrumentation-flask": { "hashes": [ - "sha256:e8ce474d7ce543bfbbb3e93f8a6f8263348af9d7b45502f387420cf3afa71253", - "sha256:e9faf58dfd9860a1868442d180142645abdafc1a652dd73d469a5efd106a7d49" + "sha256:070cb00f3f1214a4b680c7ab6ae1e5a14a54fd05ef163323500326002dfcfed4", + "sha256:88cb0f6178d8a9b66f6aabb008e2735f28e3114def90b28004a2b295ca9b67e8" ], "index": "pypi", "markers": "python_version >= '3.9'", - "version": "==0.61b0" + "version": "==0.60b1" }, "opentelemetry-instrumentation-logging": { "hashes": [ - "sha256:6d87e5ded6a0128d775d41511f8380910a1b610671081d16efb05ac3711c0074", - "sha256:feaa30b700acd2a37cc81db5f562ab0c3a5b6cc2453595e98b72c01dcf649584" + "sha256:98f4b9c7aeb9314a30feee7c002c7ea9abea07c90df5f97fb058b850bc45b89a", + "sha256:f2e18cbc7e1dd3628c80e30d243897fdc93c5b7e0c8ae60abd2b9b6a99f82343" ], "index": "pypi", "markers": "python_version >= '3.9'", - "version": "==0.61b0" + "version": "==0.60b1" }, "opentelemetry-instrumentation-sqlalchemy": { "hashes": [ - "sha256:13a3a159a2043a52f0180b3757fbaa26741b0e08abb50deddce4394c118956e6", - "sha256:f115e0be54116ba4c327b8d7b68db4045ee18d44439d888ab8130a549c50d1c1" + "sha256:486a5f264d264c44e07e0320e33fd19d09cecd2fd4b99c1064046e77a27d9f9f", + "sha256:b614e874a7c0a692838a0da613d1654e81a0612867836a1f0765e40e9c8cc49b" ], "index": "pypi", "markers": "python_version >= '3.9'", - "version": "==0.61b0" + "version": "==0.60b1" }, "opentelemetry-instrumentation-wsgi": { "hashes": [ - "sha256:380f2ae61714e5303275a80b2e14c58571573cd1fddf496d8c39fb9551c5e532", - "sha256:bd33b0824166f24134a3400648805e8d2e6a7951f070241294e8b8866611d7fa" + "sha256:5e7b432778ebf5a39af136227884a6ab2efc3c4e73e2dbb1d05ecf03ea196705", + "sha256:eb553eec7ebfcf2945cc10d787a265e7abadb9ed1d1ebce8b13988d44fa0cf45" ], "markers": "python_version >= '3.9'", - "version": "==0.61b0" + "version": "==0.60b1" }, "opentelemetry-proto": { "hashes": [ - "sha256:03f639ca129ba513f5819810f5b1f42bcb371391405d99c168fe6937c62febcd", - "sha256:266c4385d88923a23d63e353e9761af0f47a6ed0d486979777fe4de59dc9b25f" + "sha256:22cdc78efd3b3765d09e68bfbd010d4fc254c9818afd0b6b423387d9dee46007", + "sha256:6c8e05144fc0d3ed4d22c2289c6b126e03bcd0e6a7da0f16cedd2e1c2772e2c8" ], "markers": "python_version >= '3.9'", - "version": "==1.40.0" + "version": "==1.39.1" }, "opentelemetry-sdk": { "hashes": [ - "sha256:18e9f5ec20d859d268c7cb3c5198c8d105d073714db3de50b593b8c1345a48f2", - "sha256:787d2154a71f4b3d81f20524a8ce061b7db667d24e46753f32a7bc48f1c1f3f1" + "sha256:4d5482c478513ecb0a5d938dcc61394e647066e0cc2676bee9f3af3f3f45f01c", + "sha256:cf4d4563caf7bff906c9f7967e2be22d0d6b349b908be0d90fb21c8e9c995cc6" ], "markers": "python_version >= '3.9'", - "version": "==1.40.0" + "version": "==1.39.1" }, "opentelemetry-semantic-conventions": { "hashes": [ - "sha256:072f65473c5d7c6dc0355b27d6c9d1a679d63b6d4b4b16a9773062cb7e31192a", - "sha256:fa530a96be229795f8cef353739b618148b0fe2b4b3f005e60e262926c4d38e2" + "sha256:87c228b5a0669b748c76d76df6c364c369c28f1c465e50f661e39737e84bc953", + "sha256:9fa8c8b0c110da289809292b0591220d3a7b53c1526a23021e977d68597893fb" ], "markers": "python_version >= '3.9'", - "version": "==0.61b0" + "version": "==0.60b1" }, "opentelemetry-util-http": { "hashes": [ - "sha256:1039cb891334ad2731affdf034d8fb8b48c239af9b6dd295e5fabd07f1c95572", - "sha256:8e715e848233e9527ea47e275659ea60a57a75edf5206a3b937e236a6da5fc33" + "sha256:0d97152ca8c8a41ced7172d29d3622a219317f74ae6bb3027cfbdcf22c3cc0d6", + "sha256:66381ba28550c91bee14dcba8979ace443444af1ed609226634596b4b0faf199" ], "markers": "python_version >= '3.9'", - "version": "==0.61b0" + "version": "==0.60b1" }, "packaging": { "hashes": [ - "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4", - "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529" + "sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79", + "sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c" ], - "markers": "python_version >= '3.8'", - "version": "==26.0" + "markers": "python_version >= '3.9'", + "version": "==26.3" }, "protobuf": { "hashes": [ @@ -3290,11 +3585,11 @@ }, "requests": { "hashes": [ - "sha256:18817f8c57c6263968bc123d237e3b8b08ac046f5456bd1e307ee8f4250d3517", - "sha256:4e6d1ef462f3626a1f0a0a9c42dd93c63bad33f9f1c1937509b8c5c8718ab56a" + "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0", + "sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed" ], "markers": "python_version >= '3.10'", - "version": "==2.33.1" + "version": "==2.34.2" }, "typing-extensions": { "hashes": [ @@ -3307,12 +3602,12 @@ }, "urllib3": { "hashes": [ - "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472", - "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168" + "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", + "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897" ], "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==2.2.2" + "markers": "python_version >= '3.10'", + "version": "==2.7.0" }, "wrapt": { "hashes": [ @@ -3403,11 +3698,11 @@ }, "zipp": { "hashes": [ - "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e", - "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166" + "sha256:25ad4e16390cd314347dd8f1de67a2ac538ae658ed4ab9db16029c07c188e97f", + "sha256:4cb57381f544315db7688e976e922a2b18cdb513d21cc194eb42232ba2a3e602" ], - "markers": "python_version >= '3.9'", - "version": "==3.23.0" + "markers": "python_version >= '3.10'", + "version": "==4.1.0" } } } From e01dcccc8382fc534f33655cb818c6de96282ce2 Mon Sep 17 00:00:00 2001 From: MarcelGeo Date: Wed, 30 Sep 2026 16:14:43 +0200 Subject: [PATCH 07/20] Run tests when server files are changed --- .github/workflows/auto_tests.yml | 8 +++++++- server/mergin/tests/test_cli.py | 12 ++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/.github/workflows/auto_tests.yml b/.github/workflows/auto_tests.yml index b868ae0a..c48a52a4 100644 --- a/.github/workflows/auto_tests.yml +++ b/.github/workflows/auto_tests.yml @@ -1,6 +1,12 @@ name: Auto Tests -on: push +on: + push: + paths: + # Run just when the backend changed + - "server/**" + - "!server/**/*.md" + - ".github/workflows/auto_tests.yml" jobs: tests: diff --git a/server/mergin/tests/test_cli.py b/server/mergin/tests/test_cli.py index 3ba8fa29..e500177e 100644 --- a/server/mergin/tests/test_cli.py +++ b/server/mergin/tests/test_cli.py @@ -286,14 +286,10 @@ def test_check_email( app.config["MAIL_SUPPRESS_SEND"] = suppressed app.config["MAIL_DEFAULT_SENDER"] = "sender@mergin.com" if sender else None - result = runner.invoke( - args=[ - "server", - "send-check-email", - "--email", - f" test@mergin.com " if recipient else None, - ] - ) + args = ["server", "send-check-email"] + if recipient: + args += ["--email", " test@mergin.com "] + result = runner.invoke(args=args) assert output in result.output sent = 1 if output == "Email sent." else 0 assert mock_send_email.call_count == sent From fc15e0001ef1fd700214c72e4d41813fa3456967 Mon Sep 17 00:00:00 2001 From: MarcelGeo Date: Wed, 30 Sep 2026 16:18:11 +0200 Subject: [PATCH 08/20] Run the code styles just when files are changed. --- .github/workflows/code_style.yml | 21 ++++++--------------- .github/workflows/code_style_js.yml | 23 +++++++++++++++++++++++ 2 files changed, 29 insertions(+), 15 deletions(-) create mode 100644 .github/workflows/code_style_js.yml diff --git a/.github/workflows/code_style.yml b/.github/workflows/code_style.yml index 40d16586..11bc019b 100644 --- a/.github/workflows/code_style.yml +++ b/.github/workflows/code_style.yml @@ -1,6 +1,11 @@ name: Code Layout -on: push +on: + push: + paths: + # Run just when python files changed + - "server/**/*.py" + - ".github/workflows/code_style.yml" jobs: code_style_python: @@ -14,17 +19,3 @@ jobs: version: 25.1.0 options: "--check --verbose --diff" src: "./server" - - code_style_js: - name: JavaScript code convention check - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v4 - with: - node-version: '22' - - name: Check JS - run: | - cd web-app - yarn install - yarn run lint:no-legacy diff --git a/.github/workflows/code_style_js.yml b/.github/workflows/code_style_js.yml new file mode 100644 index 00000000..5aeb09a9 --- /dev/null +++ b/.github/workflows/code_style_js.yml @@ -0,0 +1,23 @@ +name: Code Layout JS + +on: + push: + paths: + # Run just when the web app changed + - "web-app/**" + - ".github/workflows/code_style_js.yml" + +jobs: + code_style_js: + name: JavaScript code convention check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v4 + with: + node-version: '22' + - name: Check JS + run: | + cd web-app + yarn install + yarn run lint:no-legacy From 634f3bec93c984d06ecc697141cbcf068c5b7e3b Mon Sep 17 00:00:00 2001 From: Martin Varga Date: Thu, 1 Oct 2026 08:52:41 +0200 Subject: [PATCH 09/20] Address review comments --- server/mergin/auth/app.py | 47 ++++++++++---------------------- server/mergin/auth/controller.py | 13 +++++---- server/mergin/auth/models.py | 6 ++++ server/mergin/tests/test_auth.py | 6 ++-- 4 files changed, 32 insertions(+), 40 deletions(-) diff --git a/server/mergin/auth/app.py b/server/mergin/auth/app.py index 643de9b9..2e05f2a1 100644 --- a/server/mergin/auth/app.py +++ b/server/mergin/auth/app.py @@ -4,7 +4,6 @@ import functools import logging -import secrets from typing import Optional from blinker import signal from flask import current_app, render_template, Flask @@ -141,18 +140,18 @@ def authenticate(login, password): return None -def generate_confirmation_token(app, email, salt): +def generate_confirmation_token(app, data, salt): serializer = URLSafeTimedSerializer(app.config["SECRET_KEY"]) - return serializer.dumps(email, salt=salt) + return serializer.dumps(data, salt=salt) def confirm_token(token, salt, expiration=3600): serializer = URLSafeTimedSerializer(current_app.config["SECRET_KEY"]) try: - email = serializer.loads(token, salt=salt, max_age=expiration) + data = serializer.loads(token, salt=salt, max_age=expiration) except: return - return email + return data def send_confirmation_email(app, user, url, template, header, **kwargs): @@ -163,7 +162,7 @@ def send_confirmation_email(app, user, url, template, header, **kwargs): token = generate_confirmation_token( app, user.email, app.config["SECURITY_EMAIL_SALT"] ) - _send_token_email(app, user, f"{url}/{token}", template, header, **kwargs) + _send_token_email(app, user, url, token, template, header, **kwargs) def send_password_reset_email(app: Flask, user: User) -> None: @@ -175,15 +174,17 @@ def send_password_reset_email(app: Flask, user: User) -> None: _send_token_email( app, user, - f"change-password/{token}", + "change-password", + token, "email/password_reset.html", "Password reset", ) -def _send_token_email(app, user, confirm_url, template, header, **kwargs): +def _send_token_email(app, user, url, token, template, header, **kwargs): from ..celery import send_email_async + confirm_url = f"{url}/{token}" html = render_template( template, subject=header, confirm_url=confirm_url, user=user, **kwargs ) @@ -197,31 +198,11 @@ def _send_token_email(app, user, confirm_url, template, header, **kwargs): def generate_password_reset_token(app: Flask, user: User) -> str: - """Sign a reset token bound to a fresh nonce stored on the user. - - Rotating the nonce revokes previously issued tokens; any password change clears it. - """ - user.password_reset_nonce = secrets.token_urlsafe(32) - serializer = URLSafeTimedSerializer(app.config["SECRET_KEY"]) - payload = {"email": user.email, "nonce": user.password_reset_nonce} - return serializer.dumps(payload, salt=app.config["SECURITY_PASSWORD_SALT"]) - - -def confirm_password_reset_token(token: str) -> Optional[dict]: - """Return a signed, unexpired reset token payload, or None. The nonce still has to be checked against the user.""" - serializer = URLSafeTimedSerializer(current_app.config["SECRET_KEY"]) - try: - payload = serializer.loads( - token, - salt=current_app.config["SECURITY_PASSWORD_SALT"], - max_age=current_app.config["PASSWORD_RESET_TOKEN_EXPIRATION"], - ) - except BadData: - return None - # tokens issued before nonces were introduced carried only the email - if not isinstance(payload, dict): - return None - return payload + """Sign a reset token bound to a fresh nonce, revoking previously issued ones.""" + payload = {"email": user.email, "nonce": user.rotate_password_reset_nonce()} + return generate_confirmation_token( + app, payload, app.config["SECURITY_PASSWORD_SALT"] + ) def generate_unlock_token(app: Flask, user: User) -> str: diff --git a/server/mergin/auth/controller.py b/server/mergin/auth/controller.py index 38bc7865..215ccf24 100644 --- a/server/mergin/auth/controller.py +++ b/server/mergin/auth/controller.py @@ -18,7 +18,6 @@ send_confirmation_email, send_password_reset_email, confirm_token, - confirm_password_reset_token, generate_confirmation_token, confirm_unlock_token, user_created, @@ -387,8 +386,13 @@ def password_reset(): # pylint: disable=W0613,W0612 def confirm_new_password(token): # pylint: disable=W0613,W0612 - payload = confirm_password_reset_token(token) - if not payload: + payload = confirm_token( + token, + salt=current_app.config["SECURITY_PASSWORD_SALT"], + expiration=current_app.config["PASSWORD_RESET_TOKEN_EXPIRATION"], + ) + # tokens issued before nonces were introduced carried only the email + if not isinstance(payload, dict): emit( AuthEventType.USER_PASSWORD_RESET_FAILED, **request_context(), @@ -410,7 +414,7 @@ def confirm_new_password(token): # pylint: disable=W0613,W0612 ) abort(404) # token was already used, superseded by a newer one or revoked by a password change - if user.password_reset_nonce != payload["nonce"]: + if not user.password_reset_nonce or user.password_reset_nonce != payload["nonce"]: emit( AuthEventType.USER_PASSWORD_RESET_FAILED, **request_context(), @@ -440,7 +444,6 @@ def confirm_new_password(token): # pylint: disable=W0613,W0612 form = UserPasswordForm.from_json(request.json) if form.validate(): - # also clears the reset nonce, making the token single-use user.assign_password(form.password.data) user.reset_lockout() db.session.add(user) diff --git a/server/mergin/auth/models.py b/server/mergin/auth/models.py index 96decb37..69a3dddb 100644 --- a/server/mergin/auth/models.py +++ b/server/mergin/auth/models.py @@ -4,6 +4,7 @@ from __future__ import annotations import datetime +import secrets from typing import List, Optional import bcrypt import re @@ -146,6 +147,11 @@ def reset_lockout(self) -> None: """Clear lockout state after a successful login.""" self.locked_until = None + def rotate_password_reset_nonce(self) -> str: + """Set a new password reset nonce, invalidating any previously issued reset token.""" + self.password_reset_nonce = secrets.token_urlsafe(32) + return self.password_reset_nonce + @property def is_authenticated(self): """For Flask-Login""" diff --git a/server/mergin/tests/test_auth.py b/server/mergin/tests/test_auth.py index 815da3c1..47cebd6a 100644 --- a/server/mergin/tests/test_auth.py +++ b/server/mergin/tests/test_auth.py @@ -607,8 +607,10 @@ def test_confirm_password(app, client): resp = client.post( url_for( "/.mergin_auth_controller_confirm_new_password", - token=generate_password_reset_token( - app, SimpleNamespace(email="tests@mergin.com") + token=generate_confirmation_token( + app, + {"email": "tests@mergin.com", "nonce": "nonce"}, + app.config["SECURITY_PASSWORD_SALT"], ), ), data=json.dumps(form_data), From 52c141cfcf31d3f7a6e0d929b0ae9d6386b0ccfe Mon Sep 17 00:00:00 2001 From: Martin Varga Date: Thu, 1 Oct 2026 10:32:21 +0200 Subject: [PATCH 10/20] increase default token expiration --- deployment/community/.env.template | 2 +- deployment/enterprise/.env.template | 2 +- server/mergin/auth/config.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/deployment/community/.env.template b/deployment/community/.env.template index 55842c36..152d970c 100644 --- a/deployment/community/.env.template +++ b/deployment/community/.env.template @@ -57,7 +57,7 @@ SECRET_KEY=fixme #BEARER_TOKEN_EXPIRATION=3600 * 12 # in seconds -#PASSWORD_RESET_TOKEN_EXPIRATION=600 # in seconds +#PASSWORD_RESET_TOKEN_EXPIRATION=900 # in seconds #SECURITY_BEARER_SALT=NODEFAULT SECURITY_BEARER_SALT=fixme diff --git a/deployment/enterprise/.env.template b/deployment/enterprise/.env.template index 1efb6e6a..511a9756 100644 --- a/deployment/enterprise/.env.template +++ b/deployment/enterprise/.env.template @@ -62,7 +62,7 @@ SECRET_KEY=fixme #BEARER_TOKEN_EXPIRATION=3600 * 12 # in seconds -#PASSWORD_RESET_TOKEN_EXPIRATION=600 # in seconds +#PASSWORD_RESET_TOKEN_EXPIRATION=900 # in seconds #SECURITY_BEARER_SALT=NODEFAULT SECURITY_BEARER_SALT=fixme diff --git a/server/mergin/auth/config.py b/server/mergin/auth/config.py index a4f34447..44b8daa1 100644 --- a/server/mergin/auth/config.py +++ b/server/mergin/auth/config.py @@ -14,7 +14,7 @@ class Configuration(object): "BEARER_TOKEN_EXPIRATION", default=3600 * 12, cast=int ) # in seconds PASSWORD_RESET_TOKEN_EXPIRATION = config( - "PASSWORD_RESET_TOKEN_EXPIRATION", default=600, cast=int + "PASSWORD_RESET_TOKEN_EXPIRATION", default=900, cast=int ) # in seconds ACCOUNT_EXPIRATION = config("ACCOUNT_EXPIRATION", default=5, cast=int) # in days BCRYPT_LOG_ROUNDS = config("BCRYPT_LOG_ROUNDS", default=12, cast=int) From 19e0b5eedb92e8c06415d775ee320b97fd7d0d64 Mon Sep 17 00:00:00 2001 From: Herman Snevajs Date: Thu, 1 Oct 2026 13:49:16 +0200 Subject: [PATCH 11/20] List all unsupported file names in v2 push error --- server/mergin/sync/errors.py | 13 +++++++ server/mergin/sync/files.py | 33 ++++++++++------ server/mergin/sync/public_api_v2.yaml | 16 ++++++++ .../mergin/sync/public_api_v2_controller.py | 10 ++++- .../mergin/tests/test_project_controller.py | 4 +- server/mergin/tests/test_public_api_v2.py | 39 ++++++++++++++++++- 6 files changed, 99 insertions(+), 16 deletions(-) diff --git a/server/mergin/sync/errors.py b/server/mergin/sync/errors.py index e12d762f..34b75ebe 100644 --- a/server/mergin/sync/errors.py +++ b/server/mergin/sync/errors.py @@ -92,6 +92,19 @@ def to_dict(self) -> Dict: return data +class UnsupportedFilesDetected(UploadError): + code = "UnsupportedFilesDetected" + + def __init__(self, error: str, unsupported_files: List[str]): + super().__init__(error) + self.unsupported_files = unsupported_files + + def to_dict(self) -> Dict: + data = super().to_dict() + data["unsupported_files"] = self.unsupported_files + return data + + class BigChunkError(ResponseError): code = "BigChunkError" detail = f"Chunk size exceeds maximum allowed size {MAX_CHUNK_SIZE} MB" diff --git a/server/mergin/sync/files.py b/server/mergin/sync/files.py index 880d744f..b7d68425 100644 --- a/server/mergin/sync/files.py +++ b/server/mergin/sync/files.py @@ -168,6 +168,17 @@ class UploadFileSchema(FileSchema): diff = fields.Nested(FileSchema(), many=False, load_default=None) +class UnsupportedFileNamesError(ValidationError): + """Upload changes contain file paths with invalid characters""" + + def __init__(self, paths: List[str]): + self.paths = paths + files = ", ".join(f"'{path}'" for path in paths) + super().__init__( + f"Unsupported files detected: {files}. Please remove the invalid characters." + ) + + class ChangesSchema(ma.Schema): """Schema for upload changes""" @@ -211,28 +222,28 @@ def validate(self, data, **kwargs): if len(set(changes_files)) != len(changes_files): raise ValidationError("Not unique changes") + # collect all unsupported file names so clients can fix them at once + unsupported_files = [] + for file in data["added"] + data["updated"]: + if not is_valid_path(file["path"]): + unsupported_files.append(file["path"]) + diff = file.get("diff") + if diff and not is_valid_path(diff["path"]): + unsupported_files.append(diff["path"]) + if unsupported_files: + raise UnsupportedFileNamesError(unsupported_files) + # check if all files are valid for file in data["added"] + data["updated"]: file_path = file["path"] if is_versioned_file(file_path) and file["size"] == 0: raise ValidationError("File is not valid") - if not is_valid_path(file_path): - raise ValidationError( - f"Unsupported file name detected: '{file_path}'. Please remove the invalid characters." - ) - if not is_supported_extension(file_path): raise ValidationError( f"Unsupported file type detected: '{file_path}'. " f"Please remove the file or try compressing it into a ZIP file before uploading.", ) - - diff = file.get("diff") - if diff and not is_valid_path(diff["path"]): - raise ValidationError( - f"Unsupported file name detected: '{diff['path']}'. Please remove the invalid characters." - ) # new checks must restrict only new files not to block existing projects for file in data["added"]: file_path = file["path"] diff --git a/server/mergin/sync/public_api_v2.yaml b/server/mergin/sync/public_api_v2.yaml index 32b232e7..086ab765 100644 --- a/server/mergin/sync/public_api_v2.yaml +++ b/server/mergin/sync/public_api_v2.yaml @@ -396,6 +396,7 @@ paths: schema: anyOf: - $ref: "#/components/schemas/UploadError" + - $ref: "#/components/schemas/UnsupportedFilesDetected" - $ref: "#/components/schemas/TrialExpired" - $ref: "#/components/schemas/StorageLimitHit" - $ref: "#/components/schemas/DataSyncError" @@ -737,6 +738,21 @@ components: example: code: UploadError detail: "Project version could not be created (UploadError)" + UnsupportedFilesDetected: + allOf: + - $ref: "#/components/schemas/CustomError" + type: object + properties: + unsupported_files: + type: array + items: + type: string + example: + code: UnsupportedFilesDetected + detail: "Unsupported files detected: 'notes:draft.txt', 'photos|old/tree.jpg'. Please remove the invalid characters. (UnsupportedFilesDetected)" + unsupported_files: + - "notes:draft.txt" + - "photos|old/tree.jpg" BatchItemError: type: object properties: diff --git a/server/mergin/sync/public_api_v2_controller.py b/server/mergin/sync/public_api_v2_controller.py index 83cef245..6b143d45 100644 --- a/server/mergin/sync/public_api_v2_controller.py +++ b/server/mergin/sync/public_api_v2_controller.py @@ -30,9 +30,15 @@ ProjectLocked, ProjectVersionExists, StorageLimitHit, + UnsupportedFilesDetected, UploadError, ) -from .files import ChangesSchema, DeltaChangeRespSchema, ProjectFileSchema +from .files import ( + ChangesSchema, + DeltaChangeRespSchema, + ProjectFileSchema, + UnsupportedFileNamesError, +) from .events import SyncEventType from ..audit import emit from ..audit.listeners import actor_context, audit_session_flags @@ -279,6 +285,8 @@ def create_project_version(id): try: ChangesSchema().validate(changes) upload_changes = ChangesSchema().dump(changes) + except UnsupportedFileNamesError as err: + return UnsupportedFilesDetected(err.messages[0], err.paths).response(422) except ValidationError as err: msg = err.messages[0] if type(err.messages) == list else "Invalid input data" return UploadError(error=msg).response(422) diff --git a/server/mergin/tests/test_project_controller.py b/server/mergin/tests/test_project_controller.py index a646ff1b..61dcc2e8 100644 --- a/server/mergin/tests/test_project_controller.py +++ b/server/mergin/tests/test_project_controller.py @@ -2712,7 +2712,7 @@ def test_filepath_manipulation(client): assert resp.status_code == 400 assert ( resp.json["detail"] - == f"Unsupported file name detected: '{manipulated_path}'. Please remove the invalid characters." + == f"Unsupported files detected: '{manipulated_path}'. Please remove the invalid characters." ) @@ -2749,7 +2749,7 @@ def test_diff_filepath_manipulation(client): assert resp.status_code == 400 assert ( resp.json["detail"] - == f"Unsupported file name detected: '{manipulated_diff_path}'. Please remove the invalid characters." + == f"Unsupported files detected: '{manipulated_diff_path}'. Please remove the invalid characters." ) diff --git a/server/mergin/tests/test_public_api_v2.py b/server/mergin/tests/test_public_api_v2.py index 7722f54a..76fc6c26 100644 --- a/server/mergin/tests/test_public_api_v2.py +++ b/server/mergin/tests/test_public_api_v2.py @@ -62,6 +62,7 @@ ProjectVersionExists, AnotherUploadRunning, StorageLimitHit, + UnsupportedFilesDetected, UploadError, ) from mergin.sync.files import ChangesSchema @@ -920,7 +921,7 @@ def _get_changes_with_diff_added(project_dir): "changes": _get_changes_with_diff_updated(test_project_dir), }, 422, - UploadError.code, + UnsupportedFilesDetected.code, ), # contains already uploaded file ( @@ -971,7 +972,7 @@ def _get_changes_with_diff_added(project_dir): ( {"version": "v1", "changes": _get_changes_with_diff_added(test_project_dir)}, 422, - UploadError.code, + UnsupportedFilesDetected.code, ), ( { @@ -1052,6 +1053,40 @@ def test_create_version(client, data, expected, err_code): assert failure.error_type == "project_push" +def test_create_version_unsupported_file_names(client): + """Test all files with unsupported names are listed in the error response""" + project = Project.query.filter_by( + workspace_id=test_workspace_id, name=test_project + ).first() + changes = _get_changes_with_diff_updated(test_project_dir) + changes["added"] = [ + { + "path": path, + "size": 1234, + "checksum": "9adb76bf81a34880209040ffe5ee262a090b62ab", + "chunks": [], + } + for path in ("notes.txt", "notes:draft.txt", "photos|old/tree.jpg") + ] + invalid_diff_path = changes["updated"][2]["diff"]["path"] + + response = client.post( + f"v2/projects/{project.id}/versions", + json={"version": "v1", "changes": changes, "check_only": True}, + ) + assert response.status_code == 422 + assert response.json["code"] == UnsupportedFilesDetected.code + assert response.json["unsupported_files"] == [ + "notes:draft.txt", + "photos|old/tree.jpg", + invalid_diff_path, + ] + assert response.json["detail"] == ( + f"Unsupported files detected: 'notes:draft.txt', 'photos|old/tree.jpg', '{invalid_diff_path}'. " + "Please remove the invalid characters. (UnsupportedFilesDetected)" + ) + + def test_create_version_failures(client): """Test various project push failures beyond invalid payload""" project = Project.query.filter_by( From 867d843638440f693586e0826504f6950be3df69 Mon Sep 17 00:00:00 2001 From: Herman Snevajs Date: Fri, 2 Oct 2026 12:49:58 +0200 Subject: [PATCH 12/20] Collect unsupported file names in the existing validation loop --- server/mergin/sync/files.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/server/mergin/sync/files.py b/server/mergin/sync/files.py index b7d68425..175c4b3a 100644 --- a/server/mergin/sync/files.py +++ b/server/mergin/sync/files.py @@ -222,28 +222,28 @@ def validate(self, data, **kwargs): if len(set(changes_files)) != len(changes_files): raise ValidationError("Not unique changes") - # collect all unsupported file names so clients can fix them at once - unsupported_files = [] - for file in data["added"] + data["updated"]: - if not is_valid_path(file["path"]): - unsupported_files.append(file["path"]) - diff = file.get("diff") - if diff and not is_valid_path(diff["path"]): - unsupported_files.append(diff["path"]) - if unsupported_files: - raise UnsupportedFileNamesError(unsupported_files) - # check if all files are valid + unsupported_files = [] for file in data["added"] + data["updated"]: file_path = file["path"] if is_versioned_file(file_path) and file["size"] == 0: raise ValidationError("File is not valid") + if not is_valid_path(file_path): + unsupported_files.append(file_path) + if not is_supported_extension(file_path): raise ValidationError( f"Unsupported file type detected: '{file_path}'. " f"Please remove the file or try compressing it into a ZIP file before uploading.", ) + + diff = file.get("diff") + if diff and not is_valid_path(diff["path"]): + unsupported_files.append(diff["path"]) + + if unsupported_files: + raise UnsupportedFileNamesError(unsupported_files) # new checks must restrict only new files not to block existing projects for file in data["added"]: file_path = file["path"] From a09cb7352c0d3d85dd80edd044c8dcb2dd874454 Mon Sep 17 00:00:00 2001 From: MarcelGeo Date: Fri, 2 Oct 2026 13:39:13 +0200 Subject: [PATCH 13/20] Fix add target uer id --- server/mergin/sync/private_api_controller.py | 1 + server/mergin/tests/test_audit_events.py | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/server/mergin/sync/private_api_controller.py b/server/mergin/sync/private_api_controller.py index d961d58b..ce29898d 100644 --- a/server/mergin/sync/private_api_controller.py +++ b/server/mergin/sync/private_api_controller.py @@ -124,6 +124,7 @@ def decline_project_access_request(request_id): # noqa: E501 workspace_name=project.workspace.name, project_name=project.name, access_request_id=access_request.id, + target_user_id=requester.id if requester else None, ) return "", 200 abort(403, "You don't have permissions to remove project access request") diff --git a/server/mergin/tests/test_audit_events.py b/server/mergin/tests/test_audit_events.py index eb4a5044..f9340955 100644 --- a/server/mergin/tests/test_audit_events.py +++ b/server/mergin/tests/test_audit_events.py @@ -499,6 +499,10 @@ def test_project_access_request_rejected(client, audit_capture): ] == requester.email ) + assert ( + audit_capture.one(SyncEventType.PROJECT_ACCESS_REQUEST_CANCELED).target_user_id + == requester.id + ) def test_project_version_created(client, audit_capture): From b09fa5a34f6e733417c546555441b6b608f6a7c6 Mon Sep 17 00:00:00 2001 From: MarcelGeo Date: Fri, 2 Oct 2026 16:15:48 +0200 Subject: [PATCH 14/20] Revert chunks lookup to legacy /chunks location --- server/mergin/sync/models.py | 9 ------ server/mergin/sync/utils.py | 4 +-- server/mergin/tests/test_public_api_v2.py | 37 ----------------------- 3 files changed, 2 insertions(+), 48 deletions(-) diff --git a/server/mergin/sync/models.py b/server/mergin/sync/models.py index 7a3231f9..77ea28c4 100644 --- a/server/mergin/sync/models.py +++ b/server/mergin/sync/models.py @@ -2115,19 +2115,10 @@ def process_chunks( # based on API version location for uploaded chunks differs if use_shared_chunk_dir: chunk_file = get_chunk_location(chunk_id) - chunk_file_fallback = get_chunk_location( - chunk_id, "/chunks" - ) else: chunk_file = os.path.join( self.upload_dir, "chunks", chunk_id ) - chunk_file_fallback = None - - if chunk_file_fallback and os.path.exists( - chunk_file_fallback - ): - chunk_file = chunk_file_fallback if not os.path.exists(chunk_file): errors[f.path] = FileSyncErrorType.CORRUPTED.value diff --git a/server/mergin/sync/utils.py b/server/mergin/sync/utils.py index 38150db2..e1c06678 100644 --- a/server/mergin/sync/utils.py +++ b/server/mergin/sync/utils.py @@ -585,14 +585,14 @@ def get_checkpoints(cls, start: int, end: int) -> List[Checkpoint]: return levels -def get_chunk_location(id: str, dir: str | None = None): +def get_chunk_location(id: str): """ Get file location for chunk on FS Splits the given identifier into two parts where the first two characters of the identifier are the small hash, and the remaining characters is a file identifier. """ - chunk_dir = dir or current_app.config.get("UPLOAD_CHUNKS_DIR") + chunk_dir = current_app.config.get("UPLOAD_CHUNKS_DIR") small_hash = id[:2] file_name = id[2:] return os.path.join(chunk_dir, small_hash, file_name) diff --git a/server/mergin/tests/test_public_api_v2.py b/server/mergin/tests/test_public_api_v2.py index 479aff72..f9b2cf73 100644 --- a/server/mergin/tests/test_public_api_v2.py +++ b/server/mergin/tests/test_public_api_v2.py @@ -1144,43 +1144,6 @@ def test_create_version_permanent_error_takes_priority(client): assert project.latest_version == 1 -def test_create_version_legacy_chunks_dir(client): - """Test push with chunks found only in legacy fallback chunks directory""" - project = Project.query.filter_by( - workspace_id=test_workspace_id, name=test_project - ).first() - data = {"version": "v1", "changes": _get_changes_without_added(test_project_dir)} - legacy_dir = os.path.join(TMP_DIR, "legacy_chunks") - - def chunk_location(id, dir=None): - # redirect hardcoded legacy "/chunks" directory to writable tmp location - return get_chunk_location(id, legacy_dir if dir == "/chunks" else dir) - - def push(): - with patch( - "mergin.sync.models.get_chunk_location", side_effect=chunk_location - ), patch( - "mergin.sync.public_api_v2_controller.remove_transaction_chunks.delay" - ): - return client.post(f"v2/projects/{project.id}/versions", json=data) - - # mimic chunks were uploaded to legacy directory only - for f in data["changes"]["updated"]: - with open(os.path.join(test_project_dir, f["path"]), "rb") as in_file: - for chunk in f["chunks"]: - chunk_file = get_chunk_location(chunk, legacy_dir) - os.makedirs(os.path.dirname(chunk_file), exist_ok=True) - with open(chunk_file, "wb") as out_file: - out_file.write(in_file.read(CHUNK_SIZE)) - assert not os.path.exists(get_chunk_location(chunk)) - - response = push() - assert response.status_code == 201 - assert response.json["version"] == "v2" - assert project.latest_version == 2 - shutil.rmtree(legacy_dir) - - def test_upload_chunk(client): """Test pushing a chunk to a project""" project = Project.query.filter_by( From d2943972e5dee8f35cc4e28ace6ed0e7857eee93 Mon Sep 17 00:00:00 2001 From: Herman Snevajs Date: Mon, 5 Oct 2026 15:13:33 +0200 Subject: [PATCH 15/20] Add target_email field for new superadmin audit event --- server/mergin/auth/listeners.py | 2 ++ server/mergin/tests/test_audit_events.py | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/server/mergin/auth/listeners.py b/server/mergin/auth/listeners.py index 6f4d3172..14a5093a 100644 --- a/server/mergin/auth/listeners.py +++ b/server/mergin/auth/listeners.py @@ -62,6 +62,7 @@ def _on_user_created(_mapper: Any, _connection: Any, target: User) -> None: AuthEventType.USER_ADMIN_PANEL_ACCESS_CHANGED, **ctx, target_user_id=target.id, + target_email=target.email, old_is_admin=None, new_is_admin=True, ) @@ -89,6 +90,7 @@ def _on_user_updated(_mapper, _connection, target): AuthEventType.USER_ADMIN_PANEL_ACCESS_CHANGED, **actor_context(), target_user_id=target.id, + target_email=target.email, old_is_admin=old, new_is_admin=new, ) diff --git a/server/mergin/tests/test_audit_events.py b/server/mergin/tests/test_audit_events.py index f9340955..b93fe1d8 100644 --- a/server/mergin/tests/test_audit_events.py +++ b/server/mergin/tests/test_audit_events.py @@ -231,6 +231,28 @@ def test_user_unlocked(app, client, audit_capture): assert len(audit_capture.of_type(AuthEventType.USER_UPDATED)) == 0 +def test_user_admin_panel_access_changed(audit_capture): + user = add_user("promoteme", "pass123") + db.session.refresh(user) + user.is_admin = True + db.session.commit() + + e = audit_capture.one(AuthEventType.USER_ADMIN_PANEL_ACCESS_CHANGED) + assert e.target_user_id == user.id + assert e.metadata["target_email"] == "promoteme@mergin.com" + assert e.metadata["old_is_admin"] is False + assert e.metadata["new_is_admin"] is True + + +def test_user_admin_panel_access_changed_on_create(audit_capture): + user = add_user("newadmin", "pass123", is_admin=True) + + e = audit_capture.one(AuthEventType.USER_ADMIN_PANEL_ACCESS_CHANGED) + assert e.target_user_id == user.id + assert e.metadata["target_email"] == "newadmin@mergin.com" + assert e.metadata["new_is_admin"] is True + + # --------------------------------------------------------------------------- # Sync / project events # --------------------------------------------------------------------------- From 72fee6a29ce3ed90462a865cc9aa7e32b2c6f998 Mon Sep 17 00:00:00 2001 From: MarcelGeo Date: Mon, 5 Oct 2026 16:10:27 +0200 Subject: [PATCH 16/20] Remove spaces --- development.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/development.md b/development.md index 54c50d98..d4a8763c 100644 --- a/development.md +++ b/development.md @@ -32,7 +32,6 @@ Pipenv then creates its own virtualenv on top of that interpreter. ```shell pip install pipenv==2026.8.0 cd server - # pipenv loads server/.env automatically; secrets and salts have no defaults $ cat > .env < Date: Wed, 7 Oct 2026 10:05:16 +0200 Subject: [PATCH 17/20] Invalidate sessions and bearer tokens on password change/reset Legacy cookies and tokens map to version 0, so deploying does not log out existing users. Make PERMANENT_SESSION_LIFETIME configurable. Co-Authored-By: Claude Opus 5.5 --- deployment/community/.env.template | 2 + deployment/enterprise/.env.template | 2 + server/mergin/app.py | 14 ++- server/mergin/auth/app.py | 22 +++- server/mergin/auth/controller.py | 27 ++-- server/mergin/auth/listeners.py | 2 + server/mergin/auth/models.py | 10 +- server/mergin/config.py | 4 + server/mergin/tests/test_auth.py | 115 ++++++++++++++++++ .../d8a2f6c1e5b4_add_user_auth_version.py | 28 +++++ 10 files changed, 203 insertions(+), 23 deletions(-) create mode 100644 server/migrations/community/d8a2f6c1e5b4_add_user_auth_version.py diff --git a/deployment/community/.env.template b/deployment/community/.env.template index 152d970c..908c08d9 100644 --- a/deployment/community/.env.template +++ b/deployment/community/.env.template @@ -75,6 +75,8 @@ SECURITY_UNLOCK_SALT=fixme #WTF_CSRF_TIME_LIMIT=3600 * 24 # in seconds +#PERMANENT_SESSION_LIFETIME=3600 * 24 * 31 # in seconds, lifetime of web session cookie + # Mail configuration diff --git a/deployment/enterprise/.env.template b/deployment/enterprise/.env.template index 511a9756..27b24992 100644 --- a/deployment/enterprise/.env.template +++ b/deployment/enterprise/.env.template @@ -80,6 +80,8 @@ SECURITY_UNLOCK_SALT=fixme #WTF_CSRF_TIME_LIMIT=3600 * 24 # in seconds +#PERMANENT_SESSION_LIFETIME=3600 * 24 * 31 # in seconds, lifetime of web session cookie + # for flask mail diff --git a/server/mergin/app.py b/server/mergin/app.py index 146767a4..e1cc83d8 100644 --- a/server/mergin/app.py +++ b/server/mergin/app.py @@ -191,9 +191,12 @@ def create_app(public_keys: List[str] = None) -> Flask: # adjust login manager @login_manager.user_loader - def load_user(user_id): # pylint: disable=W0613,W0612 + def load_user(session_id): # pylint: disable=W0613,W0612 + user_id, *rest = session_id.split(":") + # legacy session cookies carry only the user id + auth_version = int(rest[0]) if rest else 0 user = User.query.get(user_id) - if user and user.active: + if user and user.active and user.auth_version == auth_version: return user @login_manager.header_loader @@ -209,7 +212,12 @@ def load_user_from_header(header_val): # pylint: disable=W0613,W0612 user = User.query.filter_by( id=data["user_id"], username=data["username"], email=data["email"] ).one_or_none() - if user and user.active: + # legacy tokens were issued without auth version + if ( + user + and user.active + and user.auth_version == data.get("auth_version", 0) + ): return user except (BadSignature, BadTimeSignature, KeyError): pass diff --git a/server/mergin/auth/app.py b/server/mergin/auth/app.py index 2e05f2a1..1fd45efc 100644 --- a/server/mergin/auth/app.py +++ b/server/mergin/auth/app.py @@ -4,13 +4,15 @@ import functools import logging -from typing import Optional +from datetime import datetime, timedelta, timezone +from typing import Optional, Tuple from blinker import signal from flask import current_app, render_template, Flask from flask_login import current_user from itsdangerous import URLSafeTimedSerializer, BadData from sqlalchemy import func +from .bearer import encode_token from .commands import add_commands from .config import Configuration from .listeners import register_listeners @@ -205,6 +207,24 @@ def generate_password_reset_token(app: Flask, user: User) -> str: ) +def generate_bearer_token( + app: Flask, user: User, expiration: int +) -> Tuple[str, datetime]: + """Sign a bearer token valid for expiration seconds, bound to the current user auth version.""" + expire = datetime.now(timezone.utc) + timedelta(seconds=expiration) + token_data = { + "user_id": user.id, + "username": user.username, + "email": user.email, + "expire": str(expire), + "auth_version": user.auth_version, + } + token = encode_token( + app.config["SECRET_KEY"], app.config["SECURITY_BEARER_SALT"], token_data + ) + return token, expire + + def generate_unlock_token(app: Flask, user: User) -> str: """Sign a token binding the current lock episode (email + locked_until) to the user.""" serializer = URLSafeTimedSerializer(app.config["SECRET_KEY"]) diff --git a/server/mergin/auth/controller.py b/server/mergin/auth/controller.py index 215ccf24..bbc3d44e 100644 --- a/server/mergin/auth/controller.py +++ b/server/mergin/auth/controller.py @@ -3,12 +3,10 @@ # SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-MerginMaps-Commercial import os -import pytz -from datetime import datetime, timedelta from connexion import NoContent from sqlalchemy import func, desc, asc from sqlalchemy.sql.operators import is_ -from flask import request, current_app, jsonify, abort, render_template +from flask import request, current_app, jsonify, abort, render_template, session from flask_login import login_user, logout_user, current_user from flask_wtf.csrf import generate_csrf @@ -23,9 +21,9 @@ user_created, user_account_closed, edit_profile_enabled, + generate_bearer_token, CANNOT_EDIT_PROFILE_MSG, ) -from .bearer import encode_token from .models import User, LoginHistory from .schemas import UserSchema, UserSearchSchema, UserProfileSchema, UserInfoSchema from .forms import ( @@ -145,19 +143,8 @@ def login_public(): # noqa: E501 if form.validate(): user = authenticate(form.login.data, form.password.data) if user and user.active: - expire = datetime.now(pytz.utc) + timedelta( - seconds=current_app.config["BEARER_TOKEN_EXPIRATION"] - ) - token_data = { - "user_id": user.id, - "username": user.username, - "email": user.email, - "expire": str(expire), - } - token = encode_token( - current_app.config["SECRET_KEY"], - current_app.config["SECURITY_BEARER_SALT"], - token_data, + token, expire = generate_bearer_token( + current_app, user, current_app.config["BEARER_TOKEN_EXPIRATION"] ) data = user_profile(user) @@ -340,8 +327,13 @@ def change_password(): # pylint: disable=W0613,W0612 form.old_password.errors.append("The old password is incorrect") return jsonify(form.errors), 400 current_user.assign_password(form.password.data) + current_user.revoke_sessions() db.session.add(current_user) db.session.commit() + # keep the session that made the change logged in (bearer token callers need to log in again) + # "_user_id" is flask-login session key, present only for cookie-based authentication + if "_user_id" in session: + login_user(current_user._get_current_object()) emit( AuthEventType.USER_PASSWORD_CHANGED, **actor_context(), @@ -445,6 +437,7 @@ def confirm_new_password(token): # pylint: disable=W0613,W0612 form = UserPasswordForm.from_json(request.json) if form.validate(): user.assign_password(form.password.data) + user.revoke_sessions() user.reset_lockout() db.session.add(user) db.session.commit() diff --git a/server/mergin/auth/listeners.py b/server/mergin/auth/listeners.py index 14a5093a..db52edcf 100644 --- a/server/mergin/auth/listeners.py +++ b/server/mergin/auth/listeners.py @@ -18,6 +18,7 @@ # - lifecycle state fields covered by dedicated events (active, inactive_since) # - is_admin covered by the dedicated user.admin_panel_access.changed event # - locked_until covered by the dedicated user.locked / user.unlocked events +# - auth_version bumped only with password change, covered by user.password_* events # frozenset prevents accidental mutation of module-level state. _EXCLUDED_FROM_USER_UPDATED = frozenset( { @@ -29,6 +30,7 @@ "inactive_since", "is_admin", "locked_until", + "auth_version", } ) diff --git a/server/mergin/auth/models.py b/server/mergin/auth/models.py index 69a3dddb..d8f7462e 100644 --- a/server/mergin/auth/models.py +++ b/server/mergin/auth/models.py @@ -54,6 +54,8 @@ class User(db.Model): locked_until = db.Column(db.DateTime(), nullable=True) # nonce of the only valid password reset token, cleared on any password change password_reset_nonce = db.Column(db.String(64), nullable=True) + # bumped to invalidate all issued bearer tokens and session cookies + auth_version = db.Column(db.Integer, nullable=False, default=0, server_default="0") receive_notifications = db.Column( db.Boolean, default=True, nullable=False, index=True ) @@ -152,6 +154,10 @@ def rotate_password_reset_nonce(self) -> str: self.password_reset_nonce = secrets.token_urlsafe(32) return self.password_reset_nonce + def revoke_sessions(self) -> None: + """Invalidate all bearer tokens and session cookies issued so far.""" + self.auth_version += 1 + @property def is_authenticated(self): """For Flask-Login""" @@ -168,8 +174,8 @@ def is_anonymous(self): return False def get_id(self): - """For Flask-Login ... must return unicode user ID""" - return str(self.id) + """For Flask-Login, stored in session cookie ... user ID bound to auth version""" + return f"{self.id}:{self.auth_version}" @staticmethod def search(like: str, limit: int = 10, only_active: bool = True) -> List[User]: diff --git a/server/mergin/config.py b/server/mergin/config.py index f2041410..31ffba64 100644 --- a/server/mergin/config.py +++ b/server/mergin/config.py @@ -20,6 +20,10 @@ class Configuration(object): # expiration time in seconds WTF_CSRF_TIME_LIMIT = config("WTF_CSRF_TIME_LIMIT", default=3600 * 24, cast=int) WTF_CSRF_ENABLED = config("WTF_CSRF_ENABLED", default=True, cast=bool) + # how long a web session cookie is accepted, in seconds + PERMANENT_SESSION_LIFETIME = config( + "PERMANENT_SESSION_LIFETIME", default=3600 * 24 * 31, cast=int + ) # Mergin DB related SQLALCHEMY_TRACK_MODIFICATIONS = config( diff --git a/server/mergin/tests/test_auth.py b/server/mergin/tests/test_auth.py index 47cebd6a..69e3d7d4 100644 --- a/server/mergin/tests/test_auth.py +++ b/server/mergin/tests/test_auth.py @@ -455,6 +455,8 @@ def test_bcrypt_lazy_rehash(app): db.session.refresh(user) hash_rounds = int(user.passwd.split("$")[2]) assert hash_rounds == 5 + # rehash is not a password change, existing sessions stay valid + assert user.auth_version == 0 def test_deactivated_user_session_rejected(client): @@ -1564,3 +1566,116 @@ def test_bearer_token_expiration(app): "/v1/user/profile", headers={**json_headers, "Authorization": f"Bearer {token}"} ) assert resp.status_code == 401 + + +def _api_token(client, username, password): + resp = client.post( + "/v1/auth/login", + data=json.dumps({"login": username, "password": password}), + headers=json_headers, + ) + assert resp.status_code == 200 + return resp.json["session"]["token"] + + +def _profile_status(client, token=None): + headers = {**json_headers} + if token: + headers["Authorization"] = f"Bearer {token}" + # fresh app context, so flask-login does not reuse user cached in g by previous request + with client.application.app_context(): + return client.get("/v1/user/profile", headers=headers).status_code + + +def test_password_change_revokes_sessions(app): + """Password change invalidates other sessions and bearer tokens, but not the current session""" + user = add_user("revokeuser", "oldpassword") + current_session = app.test_client() + other_session = app.test_client() + api_client = app.test_client() + login(current_session, user.username, "oldpassword") + login(other_session, user.username, "oldpassword") + token = _api_token(api_client, user.username, "oldpassword") + assert _profile_status(other_session) == 200 + assert _profile_status(api_client, token) == 200 + + resp = current_session.post( + url_for("/.mergin_auth_controller_change_password"), + json={ + "old_password": "oldpassword", + "password": "changed#1", + "confirm": "changed#1", + }, + ) + assert resp.status_code == 200 + assert user.auth_version == 1 + assert _profile_status(current_session) == 200 + assert _profile_status(other_session) == 401 + assert _profile_status(api_client, token) == 401 + + # login with new credentials works + new_token = _api_token(api_client, user.username, "changed#1") + assert _profile_status(api_client, new_token) == 200 + login(other_session, user.username, "changed#1") + assert _profile_status(other_session) == 200 + + +def test_password_change_with_bearer_token(app): + """Password change through bearer token does not create session cookie, caller needs to log in again""" + user = add_user("revokeuser", "oldpassword") + api_client = app.test_client() + token = _api_token(api_client, user.username, "oldpassword") + resp = api_client.post( + url_for("/.mergin_auth_controller_change_password"), + json={ + "old_password": "oldpassword", + "password": "changed#1", + "confirm": "changed#1", + }, + headers={"Authorization": f"Bearer {token}"}, + ) + assert resp.status_code == 200 + assert "Set-Cookie" not in resp.headers + assert _profile_status(api_client, token) == 401 + + +def test_password_reset_revokes_sessions(app, client): + """Password reset invalidates all sessions and bearer tokens""" + user = add_user("revokeuser", "oldpassword") + web_session = app.test_client() + login(web_session, user.username, "oldpassword") + token = _api_token(client, user.username, "oldpassword") + + reset_token = generate_password_reset_token(app, user) + db.session.commit() + assert _confirm_new_password(client, reset_token).status_code == 200 + assert user.auth_version == 1 + assert _profile_status(web_session) == 401 + assert _profile_status(client, token) == 401 + + +def test_legacy_sessions_accepted_until_revoked(app): + """Session cookies and bearer tokens issued before auth version was introduced are valid until password change""" + user = add_user("legacyuser", "password") + web_session = app.test_client() + with web_session.session_transaction() as sess: + sess["_user_id"] = str(user.id) + sess["_fresh"] = True + legacy_token = encode_token( + app.config["SECRET_KEY"], + app.config["SECURITY_BEARER_SALT"], + { + "user_id": user.id, + "username": user.username, + "email": user.email, + "expire": str(datetime.now(timezone.utc) + timedelta(hours=1)), + }, + ) + api_client = app.test_client() + assert _profile_status(web_session) == 200 + assert _profile_status(api_client, legacy_token) == 200 + + user.revoke_sessions() + db.session.commit() + assert _profile_status(web_session) == 401 + assert _profile_status(api_client, legacy_token) == 401 diff --git a/server/migrations/community/d8a2f6c1e5b4_add_user_auth_version.py b/server/migrations/community/d8a2f6c1e5b4_add_user_auth_version.py new file mode 100644 index 00000000..6645f9a9 --- /dev/null +++ b/server/migrations/community/d8a2f6c1e5b4_add_user_auth_version.py @@ -0,0 +1,28 @@ +"""Add auth_version to user table + +Revision ID: d8a2f6c1e5b4 +Revises: c4e7b1d9a2f3 +Create Date: 2026-10-06 00:00:00.000000 + +""" + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = "d8a2f6c1e5b4" +down_revision = "c4e7b1d9a2f3" +branch_labels = None +depends_on = None + + +def upgrade(): + op.add_column( + "user", + sa.Column("auth_version", sa.Integer(), nullable=False, server_default="0"), + ) + + +def downgrade(): + op.drop_column("user", "auth_version") From bfdb839a8bbd94a7db9ff550cb938fca5739735a Mon Sep 17 00:00:00 2001 From: Martin Varga Date: Thu, 8 Oct 2026 16:06:07 +0200 Subject: [PATCH 18/20] Decrease bcrypt rounds in tests to speed up runtime --- server/.test.env | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/.test.env b/server/.test.env index 0ab2ce8a..a7af59fc 100644 --- a/server/.test.env +++ b/server/.test.env @@ -26,4 +26,5 @@ SECURITY_PASSWORD_SALT='password' SECURITY_UNLOCK_SALT='unlock' DIAGNOSTIC_LOGS_DIR=/tmp/diagnostic_logs GEVENT_WORKER=0 -OTEL_ENABLED=0 \ No newline at end of file +OTEL_ENABLED=0 +BCRYPT_LOG_ROUNDS=4 From 1b65ef142f5f09c68b9bb852eab51f1d782e71b4 Mon Sep 17 00:00:00 2001 From: Martin Varga Date: Fri, 9 Oct 2026 10:08:56 +0200 Subject: [PATCH 19/20] Share app and db schema across tests to speed up test suite - create flask app and db tables once per session, each test gets fresh app context and empty tables (clean_db deletes rows and restarts sequences) - use monkeypatch for config changes in tests so they do not leak - fix tests relying on undefined order of db rows Co-Authored-By: Claude Opus 5.5 --- server/mergin/tests/fixtures.py | 44 ++++++++----- server/mergin/tests/test_auth.py | 12 ++-- server/mergin/tests/test_celery.py | 8 +-- server/mergin/tests/test_cli.py | 21 ++++--- server/mergin/tests/test_config.py | 10 +-- server/mergin/tests/test_controller.py | 4 +- server/mergin/tests/test_db_hooks.py | 2 +- server/mergin/tests/test_permissions.py | 8 +-- .../mergin/tests/test_private_project_api.py | 8 +-- .../mergin/tests/test_project_controller.py | 61 +++++++++++-------- server/mergin/tests/test_public_api_v2.py | 31 ++++++---- server/mergin/tests/test_statistics.py | 16 ++--- server/mergin/tests/test_utils.py | 4 +- server/mergin/tests/test_workspace.py | 22 +++---- server/mergin/tests/utils.py | 26 ++++++++ 15 files changed, 170 insertions(+), 107 deletions(-) diff --git a/server/mergin/tests/fixtures.py b/server/mergin/tests/fixtures.py index c1a5ab8f..894c0731 100644 --- a/server/mergin/tests/fixtures.py +++ b/server/mergin/tests/fixtures.py @@ -17,16 +17,23 @@ from ..stats.app import register from ..stats.models import MerginInfo from . import test_project, test_workspace_id, test_project_dir, TMP_DIR -from .utils import login_as_admin, initialize, cleanup, file_info, ListSink +from .utils import ( + login_as_admin, + initialize, + cleanup, + file_info, + ListSink, + clean_db, +) from ..sync.files import files_changes_from_upload thisdir = os.path.dirname(os.path.realpath(__file__)) sys.path.append(os.path.join(thisdir, os.pardir)) -@pytest.fixture(scope="function") -def flask_app(request): - """Flask app with fresh db and initialized empty tables""" +@pytest.fixture(scope="session") +def session_app(): + """Flask app shared by all tests, db tables are created only once""" from ..sync.db_events import remove_events application = create_app( @@ -44,24 +51,33 @@ def flask_app(request): application.config["SERVER_NAME"] = "localhost.localdomain" application.config["SERVER_TYPE"] = "ce" application.config["SERVICE_ID"] = str(uuid.uuid4()) - app_context = application.app_context() - app_context.push() - with app_context: + with application.app_context(): + # start from scratch in case of previous interrupted run + db.drop_all() db.create_all() - def teardown(): - # clean up db + yield application + + with application.app_context(): db.session.remove() db.drop_all() db.engine.dispose() + # detach db hooks + remove_events() - app_context.pop() - # detach db hooks - remove_events() - request.addfinalizer(teardown) - return application +@pytest.fixture(scope="function") +def flask_app(session_app): + """Flask app with empty db tables""" + app_context = session_app.app_context() + app_context.push() + clean_db() + + yield session_app + + db.session.remove() + app_context.pop() @pytest.fixture(scope="function") diff --git a/server/mergin/tests/test_auth.py b/server/mergin/tests/test_auth.py index 69e3d7d4..dfa2a1ab 100644 --- a/server/mergin/tests/test_auth.py +++ b/server/mergin/tests/test_auth.py @@ -435,7 +435,7 @@ def login_attempt(login, password="dummy"): assert mock_hashpw.call_count + mock_checkpw.call_count == 4 -def test_bcrypt_lazy_rehash(app): +def test_bcrypt_lazy_rehash(app, monkeypatch): """Password is transparently rehashed on login when the cost factor changes.""" import bcrypt from ..auth.app import authenticate @@ -448,7 +448,7 @@ def test_bcrypt_lazy_rehash(app): user.passwd = low_rounds_hash db.session.commit() - app.config["BCRYPT_LOG_ROUNDS"] = 5 + monkeypatch.setitem(app.config, "BCRYPT_LOG_ROUNDS", 5) result = authenticate("rehashuser", "rehashpassword") assert result is not None @@ -963,7 +963,7 @@ def test_api_user_profile(client): assert key in resp.json -def test_update_user(client): +def test_update_user(client, monkeypatch): login_as_admin(client) user = User.query.filter_by(username="mergin").first() data = {"active": True, "is_admin": True} @@ -976,7 +976,9 @@ def test_update_user(client): assert user.active assert user.is_admin - client.application.config["ENABLE_SUPERADMIN_ASSIGNMENT"] = False + monkeypatch.setitem( + client.application.config, "ENABLE_SUPERADMIN_ASSIGNMENT", False + ) data = {"active": False, "is_admin": False} resp = client.patch( url_for("/.mergin_auth_controller_update_user", username=user.username), @@ -994,7 +996,7 @@ def test_update_user(client): assert resp.status_code == 200 assert not user.active - client.application.config["ENABLE_SUPERADMIN_ASSIGNMENT"] = True + monkeypatch.setitem(client.application.config, "ENABLE_SUPERADMIN_ASSIGNMENT", True) user.is_admin = False db.session.add(user) db.session.commit() diff --git a/server/mergin/tests/test_celery.py b/server/mergin/tests/test_celery.py index cb814622..1eba5094 100644 --- a/server/mergin/tests/test_celery.py +++ b/server/mergin/tests/test_celery.py @@ -49,7 +49,7 @@ from ..auth.models import User -def test_send_email(app): +def test_send_email(app, monkeypatch): """Test celery is actually sending emails.""" mail = Mail() email_data = { @@ -59,7 +59,7 @@ def test_send_email(app): "sender": "no_reply@cloudmergin.com", } with mail.record_messages() as outbox: - Configuration.MERGIN_TESTING = True + monkeypatch.setattr(Configuration, "MERGIN_TESTING", True) task = send_email_async.s(**email_data).apply() assert len(outbox) == 1 assert task.status == "SUCCESS" @@ -70,13 +70,13 @@ def test_send_email(app): assert "foo@bar.com" in outbox[0].send_to # turn off testing mode - Configuration.MERGIN_TESTING = False + monkeypatch.setattr(Configuration, "MERGIN_TESTING", False) task = send_email_async.s(**email_data).apply() assert len(outbox) == 2 assert task.status == "SUCCESS" assert current_app.config["MAIL_BCC"] in outbox[1].bcc - Configuration.MERGIN_TESTING = True + monkeypatch.setattr(Configuration, "MERGIN_TESTING", True) del email_data["recipients"] task = send_email_async.s(**email_data).apply() assert task.status == "FAILURE" diff --git a/server/mergin/tests/test_cli.py b/server/mergin/tests/test_cli.py index e500177e..d19637f0 100644 --- a/server/mergin/tests/test_cli.py +++ b/server/mergin/tests/test_cli.py @@ -234,6 +234,7 @@ def test_send_statistics( mock_send_statistics, collect_stats, app, + monkeypatch, ): """Test '_send_statistics' helper""" from mergin.commands import _send_statistics @@ -242,7 +243,7 @@ def test_send_statistics( mock_check_celery.return_value = True mock_save_statistics.return_value = None mock_send_statistics.return_value = None - app.config["COLLECT_STATISTICS"] = 1 if collect_stats else 0 + monkeypatch.setitem(app.config, "COLLECT_STATISTICS", 1 if collect_stats else 0) _send_statistics(app) assert mock_save_statistics.call_count == 1 @@ -279,12 +280,15 @@ def test_check_email( output, runner, app, + monkeypatch, ): """Test 'send-check-email' command""" mock_send_email.return_value = None mock_check_celery.return_value = celery_check - app.config["MAIL_SUPPRESS_SEND"] = suppressed - app.config["MAIL_DEFAULT_SENDER"] = "sender@mergin.com" if sender else None + monkeypatch.setitem(app.config, "MAIL_SUPPRESS_SEND", suppressed) + monkeypatch.setitem( + app.config, "MAIL_DEFAULT_SENDER", "sender@mergin.com" if sender else None + ) args = ["server", "send-check-email"] if recipient: @@ -438,19 +442,20 @@ def test_check_server( output, app, runner, + monkeypatch, ): """Test 'check' server command""" - app.config["SERVER_TYPE"] = edition - app.config["MERGIN_BASE_URL"] = base_url - app.config["CONTACT_EMAIL"] = contact_email + monkeypatch.setitem(app.config, "SERVER_TYPE", edition) + monkeypatch.setitem(app.config, "MERGIN_BASE_URL", base_url) + monkeypatch.setitem(app.config, "CONTACT_EMAIL", contact_email) if service_id is None: - app.config["SERVICE_ID"] = "" + monkeypatch.setitem(app.config, "SERVICE_ID", "") MerginInfo.query.delete() db.session.commit() if service_id == "service_id_config": - app.config["SERVICE_ID"] = "service-id-config" + monkeypatch.setitem(app.config, "SERVICE_ID", "service-id-config") if not tables: table_names_mock.return_value = "" diff --git a/server/mergin/tests/test_config.py b/server/mergin/tests/test_config.py index 494bb438..dc9d9d45 100644 --- a/server/mergin/tests/test_config.py +++ b/server/mergin/tests/test_config.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-MerginMaps-Commercial -def test_config(client): +def test_config(client, monkeypatch): """Test response of app public config""" resp = client.get("/config") assert resp.status_code == 200 @@ -28,19 +28,21 @@ def test_config(client): assert resp.status_code == 200 assert resp.json["server_type"] == "ce" - client.application.config["VERSION"] = "2023.1.2" + monkeypatch.setitem(client.application.config, "VERSION", "2023.1.2") resp = client.get("/config") assert resp.json["major"] == 2023 assert resp.json["minor"] == 1 assert resp.json["fix"] == 2 assert resp.json["server_configured"] is False - client.application.config["MERGIN_BASE_URL"] = "http://localhost:5000" + monkeypatch.setitem( + client.application.config, "MERGIN_BASE_URL", "http://localhost:5000" + ) resp = client.get("/config") assert resp.json["server_configured"] is True assert resp.json["user_self_registration"] is False assert resp.json["build_hash"] == "" - client.application.config["BUILD_HASH"] = "abcd1234" + monkeypatch.setitem(client.application.config, "BUILD_HASH", "abcd1234") resp = client.get("/config") assert resp.json["build_hash"] == "abcd1234" diff --git a/server/mergin/tests/test_controller.py b/server/mergin/tests/test_controller.py index dab45afc..2cefa6b4 100644 --- a/server/mergin/tests/test_controller.py +++ b/server/mergin/tests/test_controller.py @@ -10,10 +10,10 @@ from .utils import Response -def test_healthcheck(client): +def test_healthcheck(client, monkeypatch): # anonymous user client.get(url_for("/.mergin_auth_controller_logout")) - client.application.config["WTF_CSRF_ENABLED"] = True + monkeypatch.setitem(client.application.config, "WTF_CSRF_ENABLED", True) maint_file = current_app.config["MAINTENANCE_FILE"] resp = client.post("/alive") assert resp.status_code == 200 diff --git a/server/mergin/tests/test_db_hooks.py b/server/mergin/tests/test_db_hooks.py index 27aadb5b..4d0fd0bb 100644 --- a/server/mergin/tests/test_db_hooks.py +++ b/server/mergin/tests/test_db_hooks.py @@ -127,7 +127,7 @@ def test_remove_project(client, diff_project): .all() ] file_history = FileHistory.query.filter( - FileHistory.version_id.in_(versions_ids) + FileHistory.version_id.in_(versions_ids), FileHistory.location.isnot(None) ).first() file = os.path.join(project_dir, file_history.location) assert file_history and os.path.exists(file) diff --git a/server/mergin/tests/test_permissions.py b/server/mergin/tests/test_permissions.py index 73bf5ab4..0b790978 100644 --- a/server/mergin/tests/test_permissions.py +++ b/server/mergin/tests/test_permissions.py @@ -27,7 +27,7 @@ ) -def test_project_permissions(client): +def test_project_permissions(client, monkeypatch): owner = add_user("owner", "pwd") test_workspace = create_workspace() project = create_project("test_permissions", test_workspace, owner) @@ -72,17 +72,17 @@ def test_project_permissions(client): assert ProjectPermissions.get_user_project_role(project, user) == ProjectRole.EDITOR # adjust global permissions - Configuration.GLOBAL_READ = True + monkeypatch.setattr(Configuration, "GLOBAL_READ", True) assert ProjectPermissions.Read.check(project, user) assert ProjectPermissions.Edit.check(project, user) assert not ProjectPermissions.Upload.check(project, user) assert not ProjectPermissions.Delete.check(project, user) - Configuration.GLOBAL_WRITE = True + monkeypatch.setattr(Configuration, "GLOBAL_WRITE", True) assert ProjectPermissions.Upload.check(project, user) assert ProjectPermissions.Edit.check(project, user) assert not ProjectPermissions.Delete.check(project, user) assert not ProjectPermissions.All.check(project, user) - Configuration.GLOBAL_ADMIN = True + monkeypatch.setattr(Configuration, "GLOBAL_ADMIN", True) assert ProjectPermissions.Delete.check(project, user) assert ProjectPermissions.All.check(project, user) diff --git a/server/mergin/tests/test_private_project_api.py b/server/mergin/tests/test_private_project_api.py index 56838506..53ee1923 100644 --- a/server/mergin/tests/test_private_project_api.py +++ b/server/mergin/tests/test_private_project_api.py @@ -53,7 +53,7 @@ def test_project_unsubscribe(client, diff_project): assert not diff_project.get_role(user.id) -def test_project_access_request(client): +def test_project_access_request(client, monkeypatch): """Test project access CRUD operations""" user = User.query.filter(User.username == "mergin").first() test_workspace = create_workspace() @@ -105,7 +105,7 @@ def test_project_access_request(client): assert access_request2.requested_by == user2.id # user can not list incoming namespace access requests - Configuration.GLOBAL_ADMIN = False + monkeypatch.setattr(Configuration, "GLOBAL_ADMIN", False) assert ( client.get( f"/app/project/access-request/{test_workspace.name}?page=1&per_page=10", @@ -456,7 +456,7 @@ def test_download_project( assert resp.status_code == 200 -def test_prepare_large_project_fail(client, diff_project): +def test_prepare_large_project_fail(client, diff_project, monkeypatch): """Test asking for too large project is refused""" resp = client.post( url_for( @@ -467,7 +467,7 @@ def test_prepare_large_project_fail(client, diff_project): ) assert resp.status_code == 201 # pretend testing project to be too large by lowering limit - client.application.config["MAX_DOWNLOAD_ARCHIVE_SIZE"] = 10 + monkeypatch.setitem(client.application.config, "MAX_DOWNLOAD_ARCHIVE_SIZE", 10) resp = client.post( url_for( "/app.mergin_sync_private_api_controller_prepare_archive", diff --git a/server/mergin/tests/test_project_controller.py b/server/mergin/tests/test_project_controller.py index 61dcc2e8..3669972b 100644 --- a/server/mergin/tests/test_project_controller.py +++ b/server/mergin/tests/test_project_controller.py @@ -169,7 +169,7 @@ def test_file_history(client, diff_project): assert "location" not in history["v7"] -def test_get_paginated_projects(client): +def test_get_paginated_projects(client, monkeypatch): user = User.query.filter_by(username="mergin").first() test_workspace = create_workspace() for i in range(14): @@ -207,11 +207,14 @@ def test_get_paginated_projects(client): resp_data = json.loads(resp.data) assert len(resp_data.get("projects")) == 5 assert "foo13" in resp_data.get("projects")[-1]["name"] - # tests backward compatibility sort + # tests backward compatibility sort, projects within the same namespace are not ordered resp_alt = client.get( "/v1/project/paginated?page=2&per_page=10&order_by=namespace&descending=false" ) - assert resp_alt.json == resp.json + assert resp_alt.json["count"] == resp.json["count"] + assert [p["namespace"] for p in resp_alt.json["projects"]] == [ + p["namespace"] for p in resp.json["projects"] + ] # try with unknown order parameter resp = client.get( @@ -300,9 +303,9 @@ def test_get_paginated_projects(client): db.session.commit() # reset permissions so new user would be only a guest - Configuration.GLOBAL_READ = False - Configuration.GLOBAL_WRITE = False - Configuration.GLOBAL_ADMIN = False + monkeypatch.setattr(Configuration, "GLOBAL_READ", False) + monkeypatch.setattr(Configuration, "GLOBAL_WRITE", False) + monkeypatch.setattr(Configuration, "GLOBAL_ADMIN", False) # add new user and pretend he created one project (total 15+1) user2 = add_user("user2", "ilovemergin") create_project("created", test_workspace, user2) @@ -323,7 +326,7 @@ def test_get_paginated_projects(client): assert resp.json["projects"][0]["name"] == "foo1" # make user reader of all projects - Configuration.GLOBAL_READ = True + monkeypatch.setattr(Configuration, "GLOBAL_READ", True) resp = client.get("/v1/project/paginated?page=1&per_page=10&flag=created") assert resp.json["count"] == 1 resp = client.get("/v1/project/paginated?page=1&per_page=20&flag=shared") @@ -434,8 +437,8 @@ def test_add_project(client, app, data, expected): project = Project.query.filter_by( name=data["name"].strip(), workspace_id=test_workspace_id ).first() - proj_files = project.files - temp_files = template.files + proj_files = sorted(project.files, key=lambda f: f.path) + temp_files = sorted(template.files, key=lambda f: f.path) assert len(proj_files) == len(temp_files) assert not any( x.checksum != y.checksum and x.path != y.path @@ -1099,7 +1102,7 @@ def test_push_project_start(client, data, expected): assert failure.error_type == "push_start" -def test_push_to_new_project(client): +def test_push_to_new_project(client, monkeypatch): # create blank project p = Project.query.filter_by( name=test_project, workspace_id=test_workspace_id @@ -1110,7 +1113,7 @@ def test_push_to_new_project(client): db.session.add(project) db.session.commit() - current_app.config["BLACKLIST"] = ["test4"] + monkeypatch.setitem(current_app.config, "BLACKLIST", ["test4"]) url = "/v1/project/push/{}/{}".format(test_workspace_name, "blank") data = {"version": "v0", "changes": _get_changes(test_project_dir)} resp = client.post( @@ -1149,8 +1152,8 @@ def test_push_to_new_project(client): assert failure.error_details == "First push should be with v0" -def test_push_integrity_error(client, app): - app.config["LOCKFILE_EXPIRATION"] = 5 +def test_push_integrity_error(client, app, monkeypatch): + monkeypatch.setitem(app.config, "LOCKFILE_EXPIRATION", 5) url = "/v1/project/push/{}/{}".format(test_workspace_name, test_project) changes = _get_changes(test_project_dir) changes["added"] = changes["removed"] = [] @@ -1258,13 +1261,13 @@ def test_stale_upload_takeover(client, app): assert failure.error_details == "Push artefact removed by subsequent push" -def test_exceed_data_limit(client): +def test_exceed_data_limit(client, monkeypatch): project = Project.query.filter_by( name=test_project, workspace_id=test_workspace_id ).first() user_disk_space = sum(p.disk_usage for p in project.creator.projects) # set basic storage that it is fully used - Configuration.GLOBAL_STORAGE = user_disk_space + monkeypatch.setattr(Configuration, "GLOBAL_STORAGE", user_disk_space) url = "/v1/project/push/{}/{}".format(test_workspace_name, test_project) changes = _get_changes(test_project_dir) @@ -1298,7 +1301,11 @@ def test_exceed_data_limit(client): assert resp.status_code == 200 # tight limit again - Configuration.GLOBAL_STORAGE = sum(p.disk_usage for p in project.creator.projects) + monkeypatch.setattr( + Configuration, + "GLOBAL_STORAGE", + sum(p.disk_usage for p in project.creator.projects), + ) db.session.commit() changes["removed"] = changes["updated"] = [] @@ -1326,7 +1333,7 @@ def test_exceed_data_limit(client): headers=json_headers, ) # reset - Configuration.GLOBAL_STORAGE = 104857600 + monkeypatch.setattr(Configuration, "GLOBAL_STORAGE", 104857600) assert resp.status_code == 200 @@ -1349,7 +1356,7 @@ def remove_transaction(transaction_id): shutil.rmtree(upload_dir, ignore_errors=True) -def test_chunk_upload(client, app): +def test_chunk_upload(client, app, monkeypatch): changes = _get_changes(test_project_dir) upload, upload_dir = create_transaction("mergin", changes) chunk_id = upload.changes["added"][0]["chunks"][0] @@ -1365,7 +1372,7 @@ def test_chunk_upload(client, app): assert os.path.exists(os.path.join(upload_dir, "chunks", chunk_id)) # tests to send bigger chunk than allowed - app.config["MAX_CHUNK_SIZE"] = 10 * CHUNK_SIZE + monkeypatch.setitem(app.config, "MAX_CHUNK_SIZE", 10 * CHUNK_SIZE) with open(os.path.join(test_project_dir, "test_dir", "test4.txt"), "rb") as file: data = file.read(11 * CHUNK_SIZE) headers = {"Content-Type": "application/octet-stream"} @@ -1883,7 +1890,7 @@ def test_push_force_update_size_limit(client): @pytest.mark.parametrize("data,username,expected", clone_project_data) -def test_clone_project(client, data, username, expected): +def test_clone_project(client, data, username, expected, monkeypatch): # create new version with diff upload, upload_dir = create_transaction( "mergin", _get_changes_with_diff(test_project_dir) @@ -1897,7 +1904,7 @@ def test_clone_project(client, data, username, expected): if username != "mergin": user = add_user(username, "bar") # allow user to write into workspace, e.g. create project - Configuration.GLOBAL_ADMIN = True + monkeypatch.setattr(Configuration, "GLOBAL_ADMIN", True) # switch default user client.get(url_for("/.mergin_auth_controller_logout")) client.post( @@ -1912,7 +1919,7 @@ def test_clone_project(client, data, username, expected): ).first() user_disk_space = sum(p.disk_usage for p in project.creator.projects) # set basic storage that it is fully used - Configuration.GLOBAL_STORAGE = user_disk_space + monkeypatch.setattr(Configuration, "GLOBAL_STORAGE", user_disk_space) resp = client.post(endpoint, data=json.dumps(data), headers=json_headers) assert resp.status_code == expected if expected == 422: @@ -1960,10 +1967,10 @@ def test_clone_project(client, data, username, expected): # cleanup shutil.rmtree(project.storage.project_dir) - Configuration.GLOBAL_STORAGE = 104857600 + monkeypatch.setattr(Configuration, "GLOBAL_STORAGE", 104857600) -def test_optimize_storage(app, client, diff_project): +def test_optimize_storage(app, client, diff_project, monkeypatch): """Test optimize storage for geopackages which could be restored from diffs Scenarios for test projects: v1/base.gpkg create - basefile (no optimize) @@ -2004,7 +2011,7 @@ def test_optimize_storage(app, client, diff_project): assert os.path.exists(optimize_v4) and os.path.exists(optimize_v6) # remove constraint on file age - SyncConfiguration.FILE_EXPIRATION = 0 + monkeypatch.setattr(SyncConfiguration, "FILE_EXPIRATION", 0) optimize_storage(diff_project.id) assert not (os.path.exists(optimize_v4) and os.path.exists(optimize_v6)) # we keep latest file, basefiles must stay (either very first one, or any other with forced update) @@ -2329,7 +2336,7 @@ def test_orphan_project(client): assert not next((p for p in created_projects if p.name == "orphan"), None) -def test_inactive_project(client, diff_project): +def test_inactive_project(client, diff_project, monkeypatch): """Project set for removal is not listed and can not be updated""" user = add_user("tests", "tests") diff_project.set_role(user.id, ProjectRole.OWNER) @@ -2406,7 +2413,7 @@ def test_inactive_project(client, diff_project): assert resp.status_code == 404 # create project with the same name - Configuration.GLOBAL_ADMIN = True + monkeypatch.setattr(Configuration, "GLOBAL_ADMIN", True) data = {"name": diff_project.name} resp = client.post( f"/v1/project/{diff_project.workspace.name}", diff --git a/server/mergin/tests/test_public_api_v2.py b/server/mergin/tests/test_public_api_v2.py index 76fc6c26..66fa6507 100644 --- a/server/mergin/tests/test_public_api_v2.py +++ b/server/mergin/tests/test_public_api_v2.py @@ -145,7 +145,7 @@ def test_rename_project(client): assert response.json["code"] == "InvalidProjectName" -def test_project_members(client): +def test_project_members(client, monkeypatch): """Test CRUD endpoints for direct project members""" project = Project.query.filter_by( workspace_id=test_workspace_id, name=test_project @@ -170,9 +170,9 @@ def test_project_members(client): assert response.json["id"] == user.id assert response.json["project_role"] == role - Configuration.GLOBAL_READ = 0 - Configuration.GLOBAL_WRITE = 0 - Configuration.GLOBAL_ADMIN = 0 + monkeypatch.setattr(Configuration, "GLOBAL_READ", 0) + monkeypatch.setattr(Configuration, "GLOBAL_WRITE", 0) + monkeypatch.setattr(Configuration, "GLOBAL_ADMIN", 0) response = client.get(url) assert len(response.json) == 2 member = next(u for u in response.json if u["id"] == user.id) @@ -192,7 +192,7 @@ def test_project_members(client): assert len(response.json) == 1 # test access only by workspace role - Configuration.GLOBAL_READ = 1 + monkeypatch.setattr(Configuration, "GLOBAL_READ", 1) response = client.get(url) member = next(u for u in response.json if u["id"] == user.id) assert not member["project_role"] @@ -201,7 +201,7 @@ def test_project_members(client): # access provided by workspace role cannot be removed directly response = client.delete(url + f"/{user.id}") assert response.status_code == 404 - Configuration.GLOBAL_READ = 0 + monkeypatch.setattr(Configuration, "GLOBAL_READ", 0) def test_file_diff_download(client, diff_project): @@ -731,9 +731,15 @@ def test_project_version_delta_changes(client, diff_project: Project): delta = diff_project.get_delta_changes(8, latest_version.name + 6) assert len(delta) == 2 # file history in 9.th version is basefile - fh = FileHistory.query.filter_by( - project_version_name=latest_version.name - 1 - ).first() + fh = ( + FileHistory.query.join(ProjectFilePath) + .filter( + ProjectFilePath.project_id == diff_project.id, + ProjectFilePath.path == "test.gpkg", + FileHistory.project_version_name == latest_version.name - 1, + ) + .first() + ) # testing constistency of db entries FileDiff and ProjectVersionDelta test_gpkg_checkpoint = FileDiff.query.filter_by(basefile_id=fh.id, rank=1).first() assert test_gpkg_checkpoint @@ -1187,15 +1193,14 @@ def test_create_version_permanent_error_takes_priority(client): assert project.latest_version == 1 -def test_upload_chunk(client): +def test_upload_chunk(client, monkeypatch): """Test pushing a chunk to a project""" project = Project.query.filter_by( workspace_id=test_workspace_id, name=test_project ).first() url = f"/v2/projects/{project.id}/chunks" - client.application.config["MAX_CHUNK_SIZE"] = ( - 1024 # Set a small max chunk size for testing - ) + # Set a small max chunk size for testing + monkeypatch.setitem(client.application.config, "MAX_CHUNK_SIZE", 1024) max_chunk_size = client.application.config["MAX_CHUNK_SIZE"] response = client.post( diff --git a/server/mergin/tests/test_statistics.py b/server/mergin/tests/test_statistics.py index 189b04b0..f02d664f 100644 --- a/server/mergin/tests/test_statistics.py +++ b/server/mergin/tests/test_statistics.py @@ -18,7 +18,7 @@ from .utils import Response, add_user, create_project, create_workspace -def test_send_statistics(app, caplog): +def test_send_statistics(app, caplog, monkeypatch): """Test job to send usage statistics. Test opt-out, repeated request and 3rd party service errors. """ @@ -28,8 +28,8 @@ def test_send_statistics(app, caplog): with patch("requests.post") as mock: mock.return_value = Response(True, {}) - app.config["COLLECT_STATISTICS"] = False - app.config["CONTACT_EMAIL"] = "test@example.com" + monkeypatch.setitem(app.config, "COLLECT_STATISTICS", False) + monkeypatch.setitem(app.config, "CONTACT_EMAIL", "test@example.com") user = add_user() admin = User.query.filter_by(username="mergin").first() # create new project @@ -42,7 +42,7 @@ def test_send_statistics(app, caplog): assert not info.last_reported # success - app.config["COLLECT_STATISTICS"] = True + monkeypatch.setitem(app.config, "COLLECT_STATISTICS", True) task = send_statistics.s().apply() assert task.status == "SUCCESS" ts = info.last_reported @@ -121,10 +121,10 @@ def test_send_statistics(app, caplog): assert info.last_reported -def test_save_statistics(app, client): +def test_save_statistics(app, client, monkeypatch): """Test save statistics celery job""" info = MerginInfo.query.first() - app.config["CONTACT_EMAIL"] = "test@example.com" + monkeypatch.setitem(app.config, "CONTACT_EMAIL", "test@example.com") assert MerginStatistics.query.count() == 0 save_statistics.s().apply() assert MerginStatistics.query.count() == 1 @@ -134,7 +134,7 @@ def test_save_statistics(app, client): assert stats.data == asdict(stats_json_data) -def test_download_report(app, client): +def test_download_report(app, client, monkeypatch): """Test download report endpoint""" url = "/app/admin/report" resp = client.get(url) @@ -144,7 +144,7 @@ def test_download_report(app, client): resp = client.get(f"{url}?date_from=2021-01-01T00:00:00&date_to=2021-01-01") assert resp.status_code == 400 - app.config["CONTACT_EMAIL"] = "test@example.com" + monkeypatch.setitem(app.config, "CONTACT_EMAIL", "test@example.com") save_statistics.s().apply() resp = client.get( f"{url}?date_from=2021-01-01&date_to={datetime.now(timezone.utc).strftime('%Y-%m-%d')}" diff --git a/server/mergin/tests/test_utils.py b/server/mergin/tests/test_utils.py index 288577b0..7e96cabf 100644 --- a/server/mergin/tests/test_utils.py +++ b/server/mergin/tests/test_utils.py @@ -252,9 +252,9 @@ def test_has_trailing_space(path, path_platform, result): assert has_trailing_space(path) is result -def test_get_x_accell_uri(client): +def test_get_x_accell_uri(client, monkeypatch): """Test get_x_accell_uri""" - client.application.config["LOCAL_PROJECTS"] = "/data/" + monkeypatch.setitem(client.application.config, "LOCAL_PROJECTS", "/data/") # Input URL parts url_parts = ("/data", "archive", "project1", "file.txt") # Expected result diff --git a/server/mergin/tests/test_workspace.py b/server/mergin/tests/test_workspace.py index 1127b414..f1b1df0e 100644 --- a/server/mergin/tests/test_workspace.py +++ b/server/mergin/tests/test_workspace.py @@ -14,7 +14,7 @@ from .utils import add_user, login, create_project -def test_workspace_implementation(client): +def test_workspace_implementation(client, monkeypatch): """Test global implementation of workspace""" handler = GlobalWorkspaceHandler() user = add_user("user", "password") @@ -23,9 +23,9 @@ def test_workspace_implementation(client): ws = handler.get_by_name(Configuration.GLOBAL_WORKSPACE) assert ws.storage == Configuration.GLOBAL_STORAGE assert ws.is_active - Configuration.GLOBAL_READ = False - Configuration.GLOBAL_WRITE = False - Configuration.GLOBAL_ADMIN = False + monkeypatch.setattr(Configuration, "GLOBAL_READ", False) + monkeypatch.setattr(Configuration, "GLOBAL_WRITE", False) + monkeypatch.setattr(Configuration, "GLOBAL_ADMIN", False) assert ws.get_user_role(user) == WorkspaceRole.GUEST assert not ws.user_has_permissions(user, "owner") assert not ws.user_has_permissions(user, "read") @@ -36,13 +36,13 @@ def test_workspace_implementation(client): assert handler.list_active()[0].name == ws.name assert len(handler.list_user_workspaces(user.username)) == 1 assert handler.list_user_workspaces(user.username)[0].name == ws.name - Configuration.GLOBAL_READ = True + monkeypatch.setattr(Configuration, "GLOBAL_READ", True) assert ws.user_has_permissions(user, "read") assert not ws.user_has_permissions(user, "write") # admin is counted as editor assert handler.server_editors_count() == 1 # change global flag to enable user push to any project - Configuration.GLOBAL_WRITE = True + monkeypatch.setattr(Configuration, "GLOBAL_WRITE", True) assert ws.user_has_permissions(user, "write") assert ws.user_has_permissions(user, "read") assert handler.server_editors_count() == 2 @@ -55,7 +55,7 @@ def test_workspace_implementation(client): assert not ws.user_has_permissions(user, "admin") assert not ws.user_has_permissions(user, "owner") - Configuration.GLOBAL_ADMIN = True + monkeypatch.setattr(Configuration, "GLOBAL_ADMIN", True) # create project with dummy file to count for workspace usage project = create_project("test_permissions", ws, user) latest_version = project.get_latest_version() @@ -98,7 +98,7 @@ def test_workspace_implementation(client): assert handler.monthly_contributors_count() == 2 -def test_workspace(client): +def test_workspace(client, monkeypatch): """Test get global workspace""" resp = client.get("/v1/workspaces") assert len(resp.json) == 1 @@ -113,9 +113,9 @@ def test_workspace(client): assert client.get("/v1/workspace/2").status_code == 404 # login as another user - Configuration.GLOBAL_READ = False - Configuration.GLOBAL_WRITE = False - Configuration.GLOBAL_ADMIN = False + monkeypatch.setattr(Configuration, "GLOBAL_READ", False) + monkeypatch.setattr(Configuration, "GLOBAL_WRITE", False) + monkeypatch.setattr(Configuration, "GLOBAL_ADMIN", False) user = add_user("user", "password") login(client, "user", "password") resp = client.get("/v1/workspace/1") diff --git a/server/mergin/tests/utils.py b/server/mergin/tests/utils.py index 52b3e970..0fe172b4 100644 --- a/server/mergin/tests/utils.py +++ b/server/mergin/tests/utils.py @@ -15,6 +15,7 @@ import os from dateutil.tz import tzlocal from pygeodiff import GeoDiff +from sqlalchemy import text from ..auth.models import User from ..sync.utils import generate_location, generate_checksum @@ -33,6 +34,31 @@ CHUNK_SIZE = 1024 +def clean_db() -> None: + """Delete all rows from db tables and restart their sequences, so tests can rely on ids. + Tables are processed in reversed dependency order, so referencing rows are deleted first. + """ + tables = [ + f'"{t.schema or "public"}"."{t.name}"' + for t in reversed(db.metadata.sorted_tables) + ] + # delete is much faster than truncate for tables with only few rows. + db.session.execute(text("; ".join(f"DELETE FROM {t}" for t in tables))) + # restart sequences of serial and identity columns + db.session.execute( + text( + """ + SELECT setval(s.oid, 1, false) + FROM pg_class s + JOIN pg_depend d ON d.objid = s.oid AND d.classid = 'pg_class'::regclass AND d.deptype IN ('a', 'i') + WHERE s.relkind = 'S' AND d.refobjid = ANY(CAST(:tables AS regclass[])) + """ + ), + {"tables": tables}, + ) + db.session.commit() + + def add_user(username="random", password="random", is_admin=False) -> User: """Helper function to create not-privileged user. Associated user workspace is created with db hook. From 677d96066de7e012522a917b99d5da0e8db3f47f Mon Sep 17 00:00:00 2001 From: Martin Varga Date: Fri, 9 Oct 2026 11:07:30 +0200 Subject: [PATCH 20/20] Run tests in parallel with pytest-xdist Each xdist worker uses its own database (created automatically) and temporary directories. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/auto_tests.yml | 2 +- development.md | 4 ++++ server/Pipfile | 1 + server/Pipfile.lock | 25 ++++++++++++++++++---- server/conftest.py | 31 +++++++++++++++++++++++++++ server/mergin/tests/fixtures.py | 36 +++++++++++++++++--------------- server/mergin/tests/utils.py | 16 +++++++++++++- 7 files changed, 92 insertions(+), 23 deletions(-) create mode 100644 server/conftest.py diff --git a/.github/workflows/auto_tests.yml b/.github/workflows/auto_tests.yml index c48a52a4..283549a3 100644 --- a/.github/workflows/auto_tests.yml +++ b/.github/workflows/auto_tests.yml @@ -17,7 +17,7 @@ jobs: matrix: include: - suite: server - pytest_args: "-v --cov=mergin --cov-report=lcov mergin/tests" + pytest_args: "-v -n auto --cov=mergin --cov-report=lcov mergin/tests" - suite: migration pytest_args: "-v mergin/test_migrations" diff --git a/development.md b/development.md index d4a8763c..860905a1 100644 --- a/development.md +++ b/development.md @@ -142,3 +142,7 @@ cd server pipenv install --dev --deploy --verbose pipenv run pytest -v --cov=mergin mergin/tests ``` + +Tests can run in parallel with [pytest-xdist](https://pytest-xdist.readthedocs.io), e.g. `pipenv run pytest -n 4 mergin/tests`. +Each worker uses its own database (`_gw`, created automatically) and its own temporary directory. +To run several test sessions at the same time, give each a different `DB_DATABASE`, e.g. `DB_DATABASE=ce pipenv run pytest -n 4 mergin/tests`. diff --git a/server/Pipfile b/server/Pipfile index 552741d0..f82614c5 100644 --- a/server/Pipfile +++ b/server/Pipfile @@ -51,6 +51,7 @@ pytest-cov = "==5.0.0" pylint = "==3.2.6" responses = "==0.21.0" pytest-dotenv= "==0.5.2" +pytest-xdist = "==3.8.0" # sqlite with loadable extensions for tests, pysqlite3-binary wheels are available only for linux pysqlite3-binary = {version = "==0.5.3", markers = "sys_platform == 'linux'"} pysqlite3 = {version = "==0.6.0", markers = "sys_platform != 'linux'"} diff --git a/server/Pipfile.lock b/server/Pipfile.lock index af4c6204..19429fca 100644 --- a/server/Pipfile.lock +++ b/server/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "250ff3b20424d27421a771e1618f66d389b07456cf88e45274d1f9f148ddc069" + "sha256": "32767bfc360446c9796c8edf84ef1496707ec64089a84a8a66750a08b825dd8f" }, "pipfile-spec": 6, "requires": { @@ -2807,6 +2807,14 @@ ], "version": "==0.4.3" }, + "execnet": { + "hashes": [ + "sha256:63d83bfdd9a23e35b9c6a3261412324f964c2ec8dcd8d3c6916ee9373e0befcd", + "sha256:67fba928dd5a544b783f6056f449e5e3931a5c378b128bc18501f7ea79e296ec" + ], + "markers": "python_version >= '3.8'", + "version": "==2.1.2" + }, "filelock": { "hashes": [ "sha256:a93c4d93269b339a6af4848342c7e940d0f9928ad95eff64764699e5f1bf8a6a", @@ -2833,11 +2841,11 @@ }, "iniconfig": { "hashes": [ - "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", - "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12" + "sha256:67f4b9c50da0dedf52af349e7749a80a9057a5031199791b906c3bb3ae878960", + "sha256:9121e2c1fdb355232495be3194c8dfe87ccc2d5dee45947b78e68f499790d7a7" ], "markers": "python_version >= '3.10'", - "version": "==2.3.0" + "version": "==2.3.1" }, "isort": { "hashes": [ @@ -3006,6 +3014,15 @@ "index": "pypi", "version": "==0.5.2" }, + "pytest-xdist": { + "hashes": [ + "sha256:202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88", + "sha256:7e578125ec9bc6050861aa93f2d59f1d8d085595d6551c2c90b6f4fad8d3a9f1" + ], + "index": "pypi", + "markers": "python_version >= '3.9'", + "version": "==3.8.0" + }, "python-discovery": { "hashes": [ "sha256:cf87d3627dfb4412437fdd5b13eae402607722998d21567993aedbc59b23c15e", diff --git a/server/conftest.py b/server/conftest.py new file mode 100644 index 00000000..0c098615 --- /dev/null +++ b/server/conftest.py @@ -0,0 +1,31 @@ +# Copyright (C) Lutra Consulting Limited +# +# SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-MerginMaps-Commercial + +import os +import tempfile + + +def isolate_xdist_worker(): + """Give each pytest-xdist worker its own database and temporary directories. + + Must run before app configuration is imported as it is read from env variables, + this conftest is loaded right after test env file and before any tests modules. + """ + worker = os.environ.get("PYTEST_XDIST_WORKER") + if not worker: + return + + db_name = f"{os.environ.get('DB_DATABASE', 'postgres')}_{worker}" + os.environ["DB_DATABASE"] = db_name + tmp_dir = tempfile.gettempdir() + worker_tmp_dir = os.path.join(tmp_dir, db_name) + os.makedirs(worker_tmp_dir, exist_ok=True) + for key, value in list(os.environ.items()): + if value == tmp_dir or value.startswith(tmp_dir + os.sep): + os.environ[key] = worker_tmp_dir + value[len(tmp_dir) :] + os.environ["TMPDIR"] = worker_tmp_dir + tempfile.tempdir = None + + +isolate_xdist_worker() diff --git a/server/mergin/tests/fixtures.py b/server/mergin/tests/fixtures.py index 894c0731..3987d4c5 100644 --- a/server/mergin/tests/fixtures.py +++ b/server/mergin/tests/fixtures.py @@ -4,6 +4,7 @@ import os import shutil +import tempfile import sys import uuid from shutil import copy, move @@ -24,6 +25,7 @@ file_info, ListSink, clean_db, + create_db, ) from ..sync.files import files_changes_from_upload @@ -53,6 +55,7 @@ def session_app(): application.config["SERVICE_ID"] = str(uuid.uuid4()) with application.app_context(): + create_db() # start from scratch in case of previous interrupted run db.drop_all() db.create_all() @@ -143,41 +146,40 @@ def diff_project(app): """ from .test_project_controller import create_diff_meta - test_gpkg_file = os.path.join(test_project_dir, "test.gpkg") + # work on a copy of testing project files, the source dir is shared by all tests (and xdist workers) + project_dir = tempfile.mkdtemp(dir=TMP_DIR) + shutil.copytree(test_project_dir, project_dir, dirs_exist_ok=True) + test_gpkg_file = os.path.join(project_dir, "test.gpkg") try: geodiff = GeoDiff() project = Project.query.filter_by( name=test_project, workspace_id=test_workspace_id ).first() - update_meta = file_info(test_project_dir, "base.gpkg") - diff_meta_A = create_diff_meta( - "base.gpkg", "inserted_1_A.gpkg", test_project_dir - ) + update_meta = file_info(project_dir, "base.gpkg") + diff_meta_A = create_diff_meta("base.gpkg", "inserted_1_A.gpkg", project_dir) diff_meta_mod = create_diff_meta( - "base.gpkg", "modified_1_geom.gpkg", test_project_dir + "base.gpkg", "modified_1_geom.gpkg", project_dir ) patch = os.path.join(TMP_DIR, "patch") - basefile = os.path.join(test_project_dir, "base.gpkg") + basefile = os.path.join(project_dir, "base.gpkg") copy(basefile, patch) copy(basefile, test_gpkg_file) geodiff.apply_changeset( patch, os.path.join(TMP_DIR, diff_meta_mod["diff"]["path"]) ) - diff_meta_B = create_diff_meta( - "base.gpkg", "inserted_1_B.gpkg", test_project_dir - ) + diff_meta_B = create_diff_meta("base.gpkg", "inserted_1_B.gpkg", project_dir) changes = [ { "added": [], - "removed": [file_info(test_project_dir, "base.gpkg")], + "removed": [file_info(project_dir, "base.gpkg")], "updated": [], }, { - "added": [file_info(test_project_dir, "base.gpkg")], + "added": [file_info(project_dir, "base.gpkg")], "removed": [], "updated": [], }, @@ -198,8 +200,8 @@ def diff_project(app): }, # file renamed, by removing old and upload new - break of history { - "added": [file_info(test_project_dir, "test.gpkg")], - "removed": [file_info(test_project_dir, "base.gpkg")], + "added": [file_info(project_dir, "test.gpkg")], + "removed": [file_info(project_dir, "base.gpkg")], "updated": [], }, {"added": [], "removed": [], "updated": []}, @@ -212,7 +214,7 @@ def diff_project(app): project.storage.project_dir, ver, file_meta["path"] ) os.makedirs(os.path.dirname(new_file), exist_ok=True) - copy(os.path.join(test_project_dir, file_meta["path"]), new_file) + copy(os.path.join(project_dir, file_meta["path"]), new_file) elif change["updated"]: file_meta = change["updated"][0] f_updated = next( @@ -236,7 +238,7 @@ def diff_project(app): ), ) else: - copy(os.path.join(test_project_dir, f_updated.path), patchedfile) + copy(os.path.join(project_dir, f_updated.path), patchedfile) else: # no files uploaded, hence no action needed pass @@ -264,7 +266,7 @@ def diff_project(app): db.session.add(project) db.session.commit() finally: - os.remove(test_gpkg_file) + shutil.rmtree(project_dir) return project diff --git a/server/mergin/tests/utils.py b/server/mergin/tests/utils.py index 0fe172b4..8341fbc9 100644 --- a/server/mergin/tests/utils.py +++ b/server/mergin/tests/utils.py @@ -15,7 +15,7 @@ import os from dateutil.tz import tzlocal from pygeodiff import GeoDiff -from sqlalchemy import text +from sqlalchemy import create_engine, text from ..auth.models import User from ..sync.utils import generate_location, generate_checksum @@ -34,6 +34,20 @@ CHUNK_SIZE = 1024 +def create_db() -> None: + """Create database for tests if it does not exist yet, e.g. a separate one for each xdist worker""" + url = db.engine.url + engine = create_engine(url.set(database="postgres"), isolation_level="AUTOCOMMIT") + with engine.connect() as conn: + exists = conn.execute( + text("SELECT 1 FROM pg_database WHERE datname = :name"), + {"name": url.database}, + ).scalar() + if not exists: + conn.execute(text(f'CREATE DATABASE "{url.database}"')) + engine.dispose() + + def clean_db() -> None: """Delete all rows from db tables and restart their sequences, so tests can rely on ids. Tables are processed in reversed dependency order, so referencing rows are deleted first.