From 249754b088cd16ab6ebcefbf23d410b8c6a4748e Mon Sep 17 00:00:00 2001 From: komal <2022.komal.sabale@ves.ac.in> Date: Fri, 19 Sep 2025 09:41:13 +0530 Subject: [PATCH 1/2] authentication added --- frontend/.env | 1 + frontend/package-lock.json | 194 ++++++++++++++++++++++++++++++++++--- frontend/package.json | 1 + frontend/src/App.js | 60 ++++++++++-- frontend/src/index.js | 29 ++++-- 5 files changed, 254 insertions(+), 31 deletions(-) create mode 100644 frontend/.env diff --git a/frontend/.env b/frontend/.env new file mode 100644 index 0000000..7fdaa4d --- /dev/null +++ b/frontend/.env @@ -0,0 +1 @@ +REACT_APP_CLERK_PUBLISHABLE_KEY=pk_test_aG9seS1idWctNDkuY2xlcmsuYWNjb3VudHMuZGV2JA diff --git a/frontend/package-lock.json b/frontend/package-lock.json index e8a23c7..382f3a0 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -8,6 +8,7 @@ "name": "frontend", "version": "0.1.0", "dependencies": { + "@clerk/clerk-react": "^5.47.0", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", @@ -1868,6 +1869,66 @@ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==" }, + "node_modules/@clerk/clerk-react": { + "version": "5.47.0", + "resolved": "https://registry.npmjs.org/@clerk/clerk-react/-/clerk-react-5.47.0.tgz", + "integrity": "sha512-of2Y6dg36eL7TwAP4DbGOMWW6DJpJSIuCn6g1jJqJkh4NGljHC7vz3H18OERRM5UQXmBG3twjC8CNAQxQrquRA==", + "license": "MIT", + "dependencies": { + "@clerk/shared": "^3.25.0", + "@clerk/types": "^4.86.0", + "tslib": "2.8.1" + }, + "engines": { + "node": ">=18.17.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0 || ^19.0.0-0", + "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-0" + } + }, + "node_modules/@clerk/shared": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@clerk/shared/-/shared-3.25.0.tgz", + "integrity": "sha512-2Vb6NQqBA+1g7kfGct/OlSFmzU54/s4BQp3qeHwDqW1FgaU4MuXbqfBClI6AatxOC8Ux8W16Rvf705ViwFSxlw==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@clerk/types": "^4.86.0", + "dequal": "2.0.3", + "glob-to-regexp": "0.4.1", + "js-cookie": "3.0.5", + "std-env": "^3.9.0", + "swr": "2.3.4" + }, + "engines": { + "node": ">=18.17.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0 || ^19.0.0-0", + "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/@clerk/types": { + "version": "4.86.0", + "resolved": "https://registry.npmjs.org/@clerk/types/-/types-4.86.0.tgz", + "integrity": "sha512-YFaOYIAZWbpXehAmtgUB0YNf1v5b/hlwePvdqxlD5vdwrNsap28RpupWZat0hp1+PTtb9uAwSa5AFCOxkYLUJQ==", + "license": "MIT", + "dependencies": { + "csstype": "3.1.3" + }, + "engines": { + "node": ">=18.17.0" + } + }, "node_modules/@csstools/normalize.css": { "version": "12.0.0", "resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-12.0.0.tgz", @@ -6459,9 +6520,10 @@ "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==" }, "node_modules/csstype": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", - "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==" + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT" }, "node_modules/damerau-levenshtein": { "version": "1.0.8", @@ -6575,6 +6637,15 @@ "node": ">= 0.8" } }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/destroy": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", @@ -11415,6 +11486,15 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/js-cookie": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", + "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, "node_modules/js-sdsl": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", @@ -15251,6 +15331,12 @@ "node": ">= 0.8" } }, + "node_modules/std-env": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.9.0.tgz", + "integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==", + "license": "MIT" + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -15600,6 +15686,19 @@ "boolbase": "~1.0.0" } }, + "node_modules/swr": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/swr/-/swr-2.3.4.tgz", + "integrity": "sha512-bYd2lrhc+VarcpkgWclcUi92wYCpOgMws9Sd1hG1ntAu0NEy+14CbotuFjshBU2kt9rYj9TSmDcybpxpeTU1fg==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.3", + "use-sync-external-store": "^1.4.0" + }, + "peerDependencies": { + "react": "^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", @@ -15892,9 +15991,10 @@ } }, "node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" }, "node_modules/tsutils": { "version": "3.21.0", @@ -16124,6 +16224,15 @@ } } }, + "node_modules/use-sync-external-store": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz", + "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -18350,6 +18459,37 @@ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==" }, + "@clerk/clerk-react": { + "version": "5.47.0", + "resolved": "https://registry.npmjs.org/@clerk/clerk-react/-/clerk-react-5.47.0.tgz", + "integrity": "sha512-of2Y6dg36eL7TwAP4DbGOMWW6DJpJSIuCn6g1jJqJkh4NGljHC7vz3H18OERRM5UQXmBG3twjC8CNAQxQrquRA==", + "requires": { + "@clerk/shared": "^3.25.0", + "@clerk/types": "^4.86.0", + "tslib": "2.8.1" + } + }, + "@clerk/shared": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@clerk/shared/-/shared-3.25.0.tgz", + "integrity": "sha512-2Vb6NQqBA+1g7kfGct/OlSFmzU54/s4BQp3qeHwDqW1FgaU4MuXbqfBClI6AatxOC8Ux8W16Rvf705ViwFSxlw==", + "requires": { + "@clerk/types": "^4.86.0", + "dequal": "2.0.3", + "glob-to-regexp": "0.4.1", + "js-cookie": "3.0.5", + "std-env": "^3.9.0", + "swr": "2.3.4" + } + }, + "@clerk/types": { + "version": "4.86.0", + "resolved": "https://registry.npmjs.org/@clerk/types/-/types-4.86.0.tgz", + "integrity": "sha512-YFaOYIAZWbpXehAmtgUB0YNf1v5b/hlwePvdqxlD5vdwrNsap28RpupWZat0hp1+PTtb9uAwSa5AFCOxkYLUJQ==", + "requires": { + "csstype": "3.1.3" + } + }, "@csstools/normalize.css": { "version": "12.0.0", "resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-12.0.0.tgz", @@ -21672,9 +21812,9 @@ } }, "csstype": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", - "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==" + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, "damerau-levenshtein": { "version": "1.0.8", @@ -21756,6 +21896,11 @@ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" }, + "dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==" + }, "destroy": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", @@ -25257,6 +25402,11 @@ } } }, + "js-cookie": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", + "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==" + }, "js-sdsl": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", @@ -27879,6 +28029,11 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" }, + "std-env": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.9.0.tgz", + "integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==" + }, "string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -28139,6 +28294,15 @@ } } }, + "swr": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/swr/-/swr-2.3.4.tgz", + "integrity": "sha512-bYd2lrhc+VarcpkgWclcUi92wYCpOgMws9Sd1hG1ntAu0NEy+14CbotuFjshBU2kt9rYj9TSmDcybpxpeTU1fg==", + "requires": { + "dequal": "^2.0.3", + "use-sync-external-store": "^1.4.0" + } + }, "symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", @@ -28353,9 +28517,9 @@ } }, "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "tsutils": { "version": "3.21.0", @@ -28508,6 +28672,12 @@ "integrity": "sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==", "requires": {} }, + "use-sync-external-store": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz", + "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==", + "requires": {} + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", diff --git a/frontend/package.json b/frontend/package.json index dd6e6da..99a0dc0 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -3,6 +3,7 @@ "version": "0.1.0", "private": true, "dependencies": { + "@clerk/clerk-react": "^5.47.0", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", diff --git a/frontend/src/App.js b/frontend/src/App.js index 4f2ede4..dad4b29 100644 --- a/frontend/src/App.js +++ b/frontend/src/App.js @@ -1,20 +1,62 @@ import "./App.css"; -import {Hero, About, Repositories, Form, Layout} from './pages' -import { Route, RouterProvider, createBrowserRouter, createRoutesFromElements } from 'react-router-dom' +import { Hero, About, Repositories, Form, Layout } from "./pages"; +import { + Route, + RouterProvider, + createBrowserRouter, + createRoutesFromElements, +} from "react-router-dom"; +import { SignedIn, SignedOut, SignIn, UserButton } from "@clerk/clerk-react"; + +function ProtectedRoute({ children }) { + return ( + <> + +
+ {/* Profile + Sign out */} +
+ {children} +
+ + + {/* Show sign in if not authenticated */} + + + ); +} const router = createBrowserRouter( createRoutesFromElements( - }> - } /> - } /> - } /> - } /> + }> + {/* Public Routes */} + } /> + } /> + + {/* Protected Routes */} + + + + } + /> + +
+ + } + /> ) -) +); function App() { - return + return ; } export default App; diff --git a/frontend/src/index.js b/frontend/src/index.js index d563c0f..941cfcd 100644 --- a/frontend/src/index.js +++ b/frontend/src/index.js @@ -1,17 +1,26 @@ -import React from 'react'; -import ReactDOM from 'react-dom/client'; -import './index.css'; -import App from './App'; -import reportWebVitals from './reportWebVitals'; +import React from "react"; +import ReactDOM from "react-dom/client"; +import "./index.css"; +import App from "./App"; +import reportWebVitals from "./reportWebVitals"; +import { ClerkProvider } from "@clerk/clerk-react"; -const root = ReactDOM.createRoot(document.getElementById('root')); +// Read Clerk publishable key directly from .env +const clerkPubKey = process.env.REACT_APP_CLERK_PUBLISHABLE_KEY; + +if (!clerkPubKey) { + throw new Error( + "Missing Clerk Publishable Key! Please set REACT_APP_CLERK_PUBLISHABLE_KEY in your .env file." + ); +} + +const root = ReactDOM.createRoot(document.getElementById("root")); root.render( - + + + ); -// If you want to start measuring performance in your app, pass a function -// to log results (for example: reportWebVitals(console.log)) -// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals reportWebVitals(); From 0dc16d6a8cf1c30be2305ad8bd03c7baa44d237a Mon Sep 17 00:00:00 2001 From: komal <2022.komal.sabale@ves.ac.in> Date: Fri, 10 Oct 2025 00:01:25 +0530 Subject: [PATCH 2/2] Added backend API for homepage (fetch + filter GFI by tech stack) --- backend/__pycache__/app.cpython-312.pyc | Bin 0 -> 2422 bytes backend/app.py | 66 + backend/package-lock.json | 13 + backend/package.json | 12 + backend/requirements.txt | Bin 0 -> 536 bytes .../blinker-1.9.0.dist-info/INSTALLER | 1 + .../blinker-1.9.0.dist-info/LICENSE.txt | 20 + .../blinker-1.9.0.dist-info/METADATA | 60 + .../blinker-1.9.0.dist-info/RECORD | 12 + .../blinker-1.9.0.dist-info/WHEEL | 4 + .../Lib/site-packages/blinker/__init__.py | 17 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 510 bytes .../__pycache__/_utilities.cpython-312.pyc | Bin 0 -> 2737 bytes .../blinker/__pycache__/base.cpython-312.pyc | Bin 0 -> 21980 bytes .../Lib/site-packages/blinker/_utilities.py | 64 + .../venv/Lib/site-packages/blinker/base.py | 512 + .../venv/Lib/site-packages/blinker/py.typed | 0 .../certifi-2025.10.5.dist-info/INSTALLER | 1 + .../certifi-2025.10.5.dist-info/METADATA | 78 + .../certifi-2025.10.5.dist-info/RECORD | 14 + .../certifi-2025.10.5.dist-info/WHEEL | 5 + .../licenses/LICENSE | 20 + .../certifi-2025.10.5.dist-info/top_level.txt | 1 + .../Lib/site-packages/certifi/__init__.py | 4 + .../Lib/site-packages/certifi/__main__.py | 12 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 325 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 0 -> 640 bytes .../certifi/__pycache__/core.cpython-312.pyc | Bin 0 -> 2072 bytes .../venv/Lib/site-packages/certifi/cacert.pem | 4800 +++++++++ .../venv/Lib/site-packages/certifi/core.py | 83 + .../venv/Lib/site-packages/certifi/py.typed | 0 .../INSTALLER | 1 + .../METADATA | 750 ++ .../charset_normalizer-3.4.3.dist-info/RECORD | 35 + .../charset_normalizer-3.4.3.dist-info/WHEEL | 5 + .../entry_points.txt | 2 + .../licenses/LICENSE | 21 + .../top_level.txt | 1 + .../charset_normalizer/__init__.py | 48 + .../charset_normalizer/__main__.py | 6 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1791 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 0 -> 366 bytes .../__pycache__/api.cpython-312.pyc | Bin 0 -> 18174 bytes .../__pycache__/cd.cpython-312.pyc | Bin 0 -> 13253 bytes .../__pycache__/constant.cpython-312.pyc | Bin 0 -> 40821 bytes .../__pycache__/legacy.cpython-312.pyc | Bin 0 -> 3021 bytes .../__pycache__/md.cpython-312.pyc | Bin 0 -> 24347 bytes .../__pycache__/models.cpython-312.pyc | Bin 0 -> 17134 bytes .../__pycache__/utils.cpython-312.pyc | Bin 0 -> 13721 bytes .../__pycache__/version.cpython-312.pyc | Bin 0 -> 393 bytes .../site-packages/charset_normalizer/api.py | 669 ++ .../site-packages/charset_normalizer/cd.py | 395 + .../charset_normalizer/cli/__init__.py | 8 + .../charset_normalizer/cli/__main__.py | 381 + .../cli/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 354 bytes .../cli/__pycache__/__main__.cpython-312.pyc | Bin 0 -> 14404 bytes .../charset_normalizer/constant.py | 2015 ++++ .../charset_normalizer/legacy.py | 80 + .../charset_normalizer/md.cp312-win_amd64.pyd | Bin 0 -> 10752 bytes .../site-packages/charset_normalizer/md.py | 635 ++ .../md__mypyc.cp312-win_amd64.pyd | Bin 0 -> 128512 bytes .../charset_normalizer/models.py | 360 + .../site-packages/charset_normalizer/py.typed | 0 .../site-packages/charset_normalizer/utils.py | 414 + .../charset_normalizer/version.py | 8 + .../click-8.3.0.dist-info/INSTALLER | 1 + .../click-8.3.0.dist-info/METADATA | 84 + .../click-8.3.0.dist-info/RECORD | 40 + .../site-packages/click-8.3.0.dist-info/WHEEL | 4 + .../licenses/LICENSE.txt | 28 + .../venv/Lib/site-packages/click/__init__.py | 123 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 4082 bytes .../click/__pycache__/_compat.cpython-312.pyc | Bin 0 -> 24201 bytes .../__pycache__/_termui_impl.cpython-312.pyc | Bin 0 -> 31565 bytes .../__pycache__/_textwrap.cpython-312.pyc | Bin 0 -> 2430 bytes .../click/__pycache__/_utils.cpython-312.pyc | Bin 0 -> 1210 bytes .../__pycache__/_winconsole.cpython-312.pyc | Bin 0 -> 11775 bytes .../click/__pycache__/core.cpython-312.pyc | Bin 0 -> 133173 bytes .../__pycache__/decorators.cpython-312.pyc | Bin 0 -> 22147 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 14787 bytes .../__pycache__/formatting.cpython-312.pyc | Bin 0 -> 13608 bytes .../click/__pycache__/globals.cpython-312.pyc | Bin 0 -> 2975 bytes .../click/__pycache__/parser.cpython-312.pyc | Bin 0 -> 20434 bytes .../shell_completion.cpython-312.pyc | Bin 0 -> 23309 bytes .../click/__pycache__/termui.cpython-312.pyc | Bin 0 -> 34534 bytes .../click/__pycache__/testing.cpython-312.pyc | Bin 0 -> 27404 bytes .../click/__pycache__/types.cpython-312.pyc | Bin 0 -> 50074 bytes .../click/__pycache__/utils.cpython-312.pyc | Bin 0 -> 24879 bytes .../venv/Lib/site-packages/click/_compat.py | 622 ++ .../Lib/site-packages/click/_termui_impl.py | 847 ++ .../venv/Lib/site-packages/click/_textwrap.py | 51 + .../venv/Lib/site-packages/click/_utils.py | 36 + .../Lib/site-packages/click/_winconsole.py | 296 + backend/venv/Lib/site-packages/click/core.py | 3347 +++++++ .../Lib/site-packages/click/decorators.py | 551 ++ .../Lib/site-packages/click/exceptions.py | 308 + .../Lib/site-packages/click/formatting.py | 301 + .../venv/Lib/site-packages/click/globals.py | 67 + .../venv/Lib/site-packages/click/parser.py | 532 + backend/venv/Lib/site-packages/click/py.typed | 0 .../site-packages/click/shell_completion.py | 667 ++ .../venv/Lib/site-packages/click/termui.py | 877 ++ .../venv/Lib/site-packages/click/testing.py | 577 ++ backend/venv/Lib/site-packages/click/types.py | 1209 +++ backend/venv/Lib/site-packages/click/utils.py | 627 ++ .../colorama-0.4.6.dist-info/INSTALLER | 1 + .../colorama-0.4.6.dist-info/METADATA | 441 + .../colorama-0.4.6.dist-info/RECORD | 31 + .../colorama-0.4.6.dist-info/WHEEL | 5 + .../licenses/LICENSE.txt | 27 + .../Lib/site-packages/colorama/__init__.py | 7 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 499 bytes .../colorama/__pycache__/ansi.cpython-312.pyc | Bin 0 -> 3952 bytes .../__pycache__/ansitowin32.cpython-312.pyc | Bin 0 -> 16419 bytes .../__pycache__/initialise.cpython-312.pyc | Bin 0 -> 3557 bytes .../__pycache__/win32.cpython-312.pyc | Bin 0 -> 8142 bytes .../__pycache__/winterm.cpython-312.pyc | Bin 0 -> 9095 bytes .../venv/Lib/site-packages/colorama/ansi.py | 102 + .../Lib/site-packages/colorama/ansitowin32.py | 277 + .../Lib/site-packages/colorama/initialise.py | 121 + .../site-packages/colorama/tests/__init__.py | 1 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 205 bytes .../__pycache__/ansi_test.cpython-312.pyc | Bin 0 -> 5474 bytes .../ansitowin32_test.cpython-312.pyc | Bin 0 -> 18013 bytes .../initialise_test.cpython-312.pyc | Bin 0 -> 11661 bytes .../__pycache__/isatty_test.cpython-312.pyc | Bin 0 -> 4788 bytes .../tests/__pycache__/utils.cpython-312.pyc | Bin 0 -> 2477 bytes .../__pycache__/winterm_test.cpython-312.pyc | Bin 0 -> 6619 bytes .../site-packages/colorama/tests/ansi_test.py | 76 + .../colorama/tests/ansitowin32_test.py | 294 + .../colorama/tests/initialise_test.py | 189 + .../colorama/tests/isatty_test.py | 57 + .../Lib/site-packages/colorama/tests/utils.py | 49 + .../colorama/tests/winterm_test.py | 131 + .../venv/Lib/site-packages/colorama/win32.py | 180 + .../Lib/site-packages/colorama/winterm.py | 195 + .../venv/Lib/site-packages/dotenv/__init__.py | 49 + .../venv/Lib/site-packages/dotenv/__main__.py | 6 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1706 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 0 -> 370 bytes .../dotenv/__pycache__/cli.cpython-312.pyc | Bin 0 -> 10075 bytes .../__pycache__/ipython.cpython-312.pyc | Bin 0 -> 1979 bytes .../dotenv/__pycache__/main.cpython-312.pyc | Bin 0 -> 16913 bytes .../dotenv/__pycache__/parser.cpython-312.pyc | Bin 0 -> 10012 bytes .../__pycache__/variables.cpython-312.pyc | Bin 0 -> 5038 bytes .../__pycache__/version.cpython-312.pyc | Bin 0 -> 222 bytes backend/venv/Lib/site-packages/dotenv/cli.py | 205 + .../venv/Lib/site-packages/dotenv/ipython.py | 39 + backend/venv/Lib/site-packages/dotenv/main.py | 400 + .../venv/Lib/site-packages/dotenv/parser.py | 175 + .../venv/Lib/site-packages/dotenv/py.typed | 1 + .../Lib/site-packages/dotenv/variables.py | 86 + .../venv/Lib/site-packages/dotenv/version.py | 1 + .../flask-3.1.2.dist-info/INSTALLER | 1 + .../flask-3.1.2.dist-info/METADATA | 91 + .../flask-3.1.2.dist-info/RECORD | 58 + .../flask-3.1.2.dist-info/REQUESTED | 0 .../site-packages/flask-3.1.2.dist-info/WHEEL | 4 + .../flask-3.1.2.dist-info/entry_points.txt | 3 + .../licenses/LICENSE.txt | 28 + .../venv/Lib/site-packages/flask/__init__.py | 61 + .../venv/Lib/site-packages/flask/__main__.py | 3 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 2542 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 0 -> 250 bytes .../flask/__pycache__/app.cpython-312.pyc | Bin 0 -> 62427 bytes .../__pycache__/blueprints.cpython-312.pyc | Bin 0 -> 5009 bytes .../flask/__pycache__/cli.cpython-312.pyc | Bin 0 -> 43529 bytes .../flask/__pycache__/config.cpython-312.pyc | Bin 0 -> 16218 bytes .../flask/__pycache__/ctx.cpython-312.pyc | Bin 0 -> 19836 bytes .../__pycache__/debughelpers.cpython-312.pyc | Bin 0 -> 9141 bytes .../flask/__pycache__/globals.cpython-312.pyc | Bin 0 -> 1874 bytes .../flask/__pycache__/helpers.cpython-312.pyc | Bin 0 -> 25552 bytes .../flask/__pycache__/logging.cpython-312.pyc | Bin 0 -> 3279 bytes .../__pycache__/sessions.cpython-312.pyc | Bin 0 -> 17191 bytes .../flask/__pycache__/signals.cpython-312.pyc | Bin 0 -> 1231 bytes .../__pycache__/templating.cpython-312.pyc | Bin 0 -> 9915 bytes .../flask/__pycache__/testing.cpython-312.pyc | Bin 0 -> 13590 bytes .../flask/__pycache__/typing.cpython-312.pyc | Bin 0 -> 4139 bytes .../flask/__pycache__/views.cpython-312.pyc | Bin 0 -> 7015 bytes .../__pycache__/wrappers.cpython-312.pyc | Bin 0 -> 10062 bytes backend/venv/Lib/site-packages/flask/app.py | 1536 +++ .../Lib/site-packages/flask/blueprints.py | 128 + backend/venv/Lib/site-packages/flask/cli.py | 1135 +++ .../venv/Lib/site-packages/flask/config.py | 367 + backend/venv/Lib/site-packages/flask/ctx.py | 449 + .../Lib/site-packages/flask/debughelpers.py | 178 + .../venv/Lib/site-packages/flask/globals.py | 51 + .../venv/Lib/site-packages/flask/helpers.py | 641 ++ .../Lib/site-packages/flask/json/__init__.py | 170 + .../json/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 6702 bytes .../json/__pycache__/provider.cpython-312.pyc | Bin 0 -> 9269 bytes .../json/__pycache__/tag.cpython-312.pyc | Bin 0 -> 13964 bytes .../Lib/site-packages/flask/json/provider.py | 215 + .../venv/Lib/site-packages/flask/json/tag.py | 327 + .../venv/Lib/site-packages/flask/logging.py | 79 + backend/venv/Lib/site-packages/flask/py.typed | 0 .../Lib/site-packages/flask/sansio/README.md | 6 + .../sansio/__pycache__/app.cpython-312.pyc | Bin 0 -> 33695 bytes .../__pycache__/blueprints.cpython-312.pyc | Bin 0 -> 31193 bytes .../__pycache__/scaffold.cpython-312.pyc | Bin 0 -> 30233 bytes .../Lib/site-packages/flask/sansio/app.py | 964 ++ .../site-packages/flask/sansio/blueprints.py | 632 ++ .../site-packages/flask/sansio/scaffold.py | 792 ++ .../venv/Lib/site-packages/flask/sessions.py | 399 + .../venv/Lib/site-packages/flask/signals.py | 17 + .../Lib/site-packages/flask/templating.py | 219 + .../venv/Lib/site-packages/flask/testing.py | 298 + .../venv/Lib/site-packages/flask/typing.py | 93 + backend/venv/Lib/site-packages/flask/views.py | 191 + .../venv/Lib/site-packages/flask/wrappers.py | 257 + .../flask_cors-6.0.1.dist-info/INSTALLER | 1 + .../flask_cors-6.0.1.dist-info/METADATA | 143 + .../flask_cors-6.0.1.dist-info/RECORD | 16 + .../flask_cors-6.0.1.dist-info/REQUESTED | 0 .../flask_cors-6.0.1.dist-info/WHEEL | 5 + .../flask_cors-6.0.1.dist-info/top_level.txt | 1 + .../Lib/site-packages/flask_cors/__init__.py | 17 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 773 bytes .../__pycache__/core.cpython-312.pyc | Bin 0 -> 15845 bytes .../__pycache__/decorator.cpython-312.pyc | Bin 0 -> 5075 bytes .../__pycache__/extension.cpython-312.pyc | Bin 0 -> 8933 bytes .../__pycache__/version.cpython-312.pyc | Bin 0 -> 226 bytes .../venv/Lib/site-packages/flask_cors/core.py | 399 + .../Lib/site-packages/flask_cors/decorator.py | 129 + .../Lib/site-packages/flask_cors/extension.py | 206 + .../Lib/site-packages/flask_cors/version.py | 1 + .../idna-3.10.dist-info/INSTALLER | 1 + .../idna-3.10.dist-info/LICENSE.md | 31 + .../idna-3.10.dist-info/METADATA | 250 + .../site-packages/idna-3.10.dist-info/RECORD | 22 + .../site-packages/idna-3.10.dist-info/WHEEL | 4 + .../venv/Lib/site-packages/idna/__init__.py | 45 + .../idna/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 893 bytes .../idna/__pycache__/codec.cpython-312.pyc | Bin 0 -> 4983 bytes .../idna/__pycache__/compat.cpython-312.pyc | Bin 0 -> 897 bytes .../idna/__pycache__/core.cpython-312.pyc | Bin 0 -> 16128 bytes .../idna/__pycache__/idnadata.cpython-312.pyc | Bin 0 -> 99483 bytes .../__pycache__/intranges.cpython-312.pyc | Bin 0 -> 2640 bytes .../__pycache__/package_data.cpython-312.pyc | Bin 0 -> 224 bytes .../__pycache__/uts46data.cpython-312.pyc | Bin 0 -> 158853 bytes backend/venv/Lib/site-packages/idna/codec.py | 122 + backend/venv/Lib/site-packages/idna/compat.py | 15 + backend/venv/Lib/site-packages/idna/core.py | 437 + .../venv/Lib/site-packages/idna/idnadata.py | 4243 ++++++++ .../venv/Lib/site-packages/idna/intranges.py | 57 + .../Lib/site-packages/idna/package_data.py | 1 + backend/venv/Lib/site-packages/idna/py.typed | 0 .../venv/Lib/site-packages/idna/uts46data.py | 8681 +++++++++++++++++ .../itsdangerous-2.2.0.dist-info/INSTALLER | 1 + .../itsdangerous-2.2.0.dist-info/LICENSE.txt | 28 + .../itsdangerous-2.2.0.dist-info/METADATA | 60 + .../itsdangerous-2.2.0.dist-info/RECORD | 22 + .../itsdangerous-2.2.0.dist-info/WHEEL | 4 + .../site-packages/itsdangerous/__init__.py | 38 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1641 bytes .../__pycache__/_json.cpython-312.pyc | Bin 0 -> 1195 bytes .../__pycache__/encoding.cpython-312.pyc | Bin 0 -> 2695 bytes .../__pycache__/exc.cpython-312.pyc | Bin 0 -> 3955 bytes .../__pycache__/serializer.cpython-312.pyc | Bin 0 -> 15423 bytes .../__pycache__/signer.cpython-312.pyc | Bin 0 -> 11300 bytes .../__pycache__/timed.cpython-312.pyc | Bin 0 -> 8744 bytes .../__pycache__/url_safe.cpython-312.pyc | Bin 0 -> 3545 bytes .../Lib/site-packages/itsdangerous/_json.py | 18 + .../site-packages/itsdangerous/encoding.py | 54 + .../Lib/site-packages/itsdangerous/exc.py | 106 + .../Lib/site-packages/itsdangerous/py.typed | 0 .../site-packages/itsdangerous/serializer.py | 406 + .../Lib/site-packages/itsdangerous/signer.py | 266 + .../Lib/site-packages/itsdangerous/timed.py | 228 + .../site-packages/itsdangerous/url_safe.py | 83 + .../jinja2-3.1.6.dist-info/INSTALLER | 1 + .../jinja2-3.1.6.dist-info/METADATA | 84 + .../jinja2-3.1.6.dist-info/RECORD | 57 + .../jinja2-3.1.6.dist-info/WHEEL | 4 + .../jinja2-3.1.6.dist-info/entry_points.txt | 3 + .../licenses/LICENSE.txt | 28 + .../venv/Lib/site-packages/jinja2/__init__.py | 38 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1666 bytes .../__pycache__/_identifier.cpython-312.pyc | Bin 0 -> 2147 bytes .../__pycache__/async_utils.cpython-312.pyc | Bin 0 -> 4987 bytes .../__pycache__/bccache.cpython-312.pyc | Bin 0 -> 19338 bytes .../__pycache__/compiler.cpython-312.pyc | Bin 0 -> 103905 bytes .../__pycache__/constants.cpython-312.pyc | Bin 0 -> 1569 bytes .../jinja2/__pycache__/debug.cpython-312.pyc | Bin 0 -> 6579 bytes .../__pycache__/defaults.cpython-312.pyc | Bin 0 -> 1619 bytes .../__pycache__/environment.cpython-312.pyc | Bin 0 -> 76648 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 7728 bytes .../jinja2/__pycache__/ext.cpython-312.pyc | Bin 0 -> 41890 bytes .../__pycache__/filters.cpython-312.pyc | Bin 0 -> 72282 bytes .../__pycache__/idtracking.cpython-312.pyc | Bin 0 -> 19133 bytes .../jinja2/__pycache__/lexer.cpython-312.pyc | Bin 0 -> 32078 bytes .../__pycache__/loaders.cpython-312.pyc | Bin 0 -> 32288 bytes .../jinja2/__pycache__/meta.cpython-312.pyc | Bin 0 -> 5483 bytes .../__pycache__/nativetypes.cpython-312.pyc | Bin 0 -> 7032 bytes .../jinja2/__pycache__/nodes.cpython-312.pyc | Bin 0 -> 58232 bytes .../__pycache__/optimizer.cpython-312.pyc | Bin 0 -> 2702 bytes .../jinja2/__pycache__/parser.cpython-312.pyc | Bin 0 -> 61193 bytes .../__pycache__/runtime.cpython-312.pyc | Bin 0 -> 48897 bytes .../__pycache__/sandbox.cpython-312.pyc | Bin 0 -> 18110 bytes .../jinja2/__pycache__/tests.cpython-312.pyc | Bin 0 -> 9063 bytes .../jinja2/__pycache__/utils.cpython-312.pyc | Bin 0 -> 34811 bytes .../__pycache__/visitor.cpython-312.pyc | Bin 0 -> 5366 bytes .../Lib/site-packages/jinja2/_identifier.py | 6 + .../Lib/site-packages/jinja2/async_utils.py | 99 + .../venv/Lib/site-packages/jinja2/bccache.py | 408 + .../venv/Lib/site-packages/jinja2/compiler.py | 1998 ++++ .../Lib/site-packages/jinja2/constants.py | 20 + .../venv/Lib/site-packages/jinja2/debug.py | 191 + .../venv/Lib/site-packages/jinja2/defaults.py | 48 + .../Lib/site-packages/jinja2/environment.py | 1672 ++++ .../Lib/site-packages/jinja2/exceptions.py | 166 + backend/venv/Lib/site-packages/jinja2/ext.py | 870 ++ .../venv/Lib/site-packages/jinja2/filters.py | 1873 ++++ .../Lib/site-packages/jinja2/idtracking.py | 318 + .../venv/Lib/site-packages/jinja2/lexer.py | 868 ++ .../venv/Lib/site-packages/jinja2/loaders.py | 693 ++ backend/venv/Lib/site-packages/jinja2/meta.py | 112 + .../Lib/site-packages/jinja2/nativetypes.py | 130 + .../venv/Lib/site-packages/jinja2/nodes.py | 1206 +++ .../Lib/site-packages/jinja2/optimizer.py | 48 + .../venv/Lib/site-packages/jinja2/parser.py | 1049 ++ .../venv/Lib/site-packages/jinja2/py.typed | 0 .../venv/Lib/site-packages/jinja2/runtime.py | 1062 ++ .../venv/Lib/site-packages/jinja2/sandbox.py | 436 + .../venv/Lib/site-packages/jinja2/tests.py | 256 + .../venv/Lib/site-packages/jinja2/utils.py | 766 ++ .../venv/Lib/site-packages/jinja2/visitor.py | 92 + .../markupsafe-3.0.3.dist-info/INSTALLER | 1 + .../markupsafe-3.0.3.dist-info/METADATA | 74 + .../markupsafe-3.0.3.dist-info/RECORD | 14 + .../markupsafe-3.0.3.dist-info/WHEEL | 5 + .../licenses/LICENSE.txt | 28 + .../markupsafe-3.0.3.dist-info/top_level.txt | 1 + .../Lib/site-packages/markupsafe/__init__.py | 396 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 21001 bytes .../__pycache__/_native.cpython-312.pyc | Bin 0 -> 628 bytes .../Lib/site-packages/markupsafe/_native.py | 8 + .../Lib/site-packages/markupsafe/_speedups.c | 200 + .../markupsafe/_speedups.cp312-win_amd64.pyd | Bin 0 -> 13312 bytes .../site-packages/markupsafe/_speedups.pyi | 1 + .../Lib/site-packages/markupsafe/py.typed | 0 .../pip-24.2.dist-info/AUTHORS.txt | 796 ++ .../pip-24.2.dist-info/INSTALLER | 1 + .../pip-24.2.dist-info/LICENSE.txt | 20 + .../site-packages/pip-24.2.dist-info/METADATA | 89 + .../site-packages/pip-24.2.dist-info/RECORD | 853 ++ .../pip-24.2.dist-info/REQUESTED | 0 .../site-packages/pip-24.2.dist-info/WHEEL | 5 + .../pip-24.2.dist-info/entry_points.txt | 3 + .../pip-24.2.dist-info/top_level.txt | 1 + .../venv/Lib/site-packages/pip/__init__.py | 13 + .../venv/Lib/site-packages/pip/__main__.py | 24 + .../Lib/site-packages/pip/__pip-runner__.py | 50 + .../pip/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 703 bytes .../pip/__pycache__/__main__.cpython-312.pyc | Bin 0 -> 859 bytes .../__pip-runner__.cpython-312.pyc | Bin 0 -> 2223 bytes .../site-packages/pip/_internal/__init__.py | 18 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 805 bytes .../__pycache__/build_env.cpython-312.pyc | Bin 0 -> 14490 bytes .../__pycache__/cache.cpython-312.pyc | Bin 0 -> 12685 bytes .../__pycache__/configuration.cpython-312.pyc | Bin 0 -> 17650 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 35569 bytes .../__pycache__/main.cpython-312.pyc | Bin 0 -> 688 bytes .../__pycache__/pyproject.cpython-312.pyc | Bin 0 -> 5136 bytes .../self_outdated_check.cpython-312.pyc | Bin 0 -> 10226 bytes .../__pycache__/wheel_builder.cpython-312.pyc | Bin 0 -> 13633 bytes .../site-packages/pip/_internal/build_env.py | 315 + .../Lib/site-packages/pip/_internal/cache.py | 290 + .../pip/_internal/cli/__init__.py | 4 + .../cli/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 296 bytes .../autocompletion.cpython-312.pyc | Bin 0 -> 8624 bytes .../__pycache__/base_command.cpython-312.pyc | Bin 0 -> 10212 bytes .../__pycache__/cmdoptions.cpython-312.pyc | Bin 0 -> 30413 bytes .../command_context.cpython-312.pyc | Bin 0 -> 1792 bytes .../__pycache__/index_command.cpython-312.pyc | Bin 0 -> 7142 bytes .../cli/__pycache__/main.cpython-312.pyc | Bin 0 -> 2318 bytes .../__pycache__/main_parser.cpython-312.pyc | Bin 0 -> 4924 bytes .../cli/__pycache__/parser.cpython-312.pyc | Bin 0 -> 15031 bytes .../__pycache__/progress_bars.cpython-312.pyc | Bin 0 -> 3852 bytes .../__pycache__/req_command.cpython-312.pyc | Bin 0 -> 12259 bytes .../cli/__pycache__/spinners.cpython-312.pyc | Bin 0 -> 7851 bytes .../__pycache__/status_codes.cpython-312.pyc | Bin 0 -> 393 bytes .../pip/_internal/cli/autocompletion.py | 176 + .../pip/_internal/cli/base_command.py | 231 + .../pip/_internal/cli/cmdoptions.py | 1075 ++ .../pip/_internal/cli/command_context.py | 27 + .../pip/_internal/cli/index_command.py | 170 + .../site-packages/pip/_internal/cli/main.py | 80 + .../pip/_internal/cli/main_parser.py | 134 + .../site-packages/pip/_internal/cli/parser.py | 294 + .../pip/_internal/cli/progress_bars.py | 94 + .../pip/_internal/cli/req_command.py | 329 + .../pip/_internal/cli/spinners.py | 159 + .../pip/_internal/cli/status_codes.py | 6 + .../pip/_internal/commands/__init__.py | 132 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 4020 bytes .../__pycache__/cache.cpython-312.pyc | Bin 0 -> 9719 bytes .../__pycache__/check.cpython-312.pyc | Bin 0 -> 2610 bytes .../__pycache__/completion.cpython-312.pyc | Bin 0 -> 5211 bytes .../__pycache__/configuration.cpython-312.pyc | Bin 0 -> 13181 bytes .../__pycache__/debug.cpython-312.pyc | Bin 0 -> 10086 bytes .../__pycache__/download.cpython-312.pyc | Bin 0 -> 7521 bytes .../__pycache__/freeze.cpython-312.pyc | Bin 0 -> 4403 bytes .../commands/__pycache__/hash.cpython-312.pyc | Bin 0 -> 2986 bytes .../commands/__pycache__/help.cpython-312.pyc | Bin 0 -> 1691 bytes .../__pycache__/index.cpython-312.pyc | Bin 0 -> 6689 bytes .../__pycache__/inspect.cpython-312.pyc | Bin 0 -> 3998 bytes .../__pycache__/install.cpython-312.pyc | Bin 0 -> 29132 bytes .../commands/__pycache__/list.cpython-312.pyc | Bin 0 -> 15775 bytes .../__pycache__/search.cpython-312.pyc | Bin 0 -> 7536 bytes .../commands/__pycache__/show.cpython-312.pyc | Bin 0 -> 10495 bytes .../__pycache__/uninstall.cpython-312.pyc | Bin 0 -> 4727 bytes .../__pycache__/wheel.cpython-312.pyc | Bin 0 -> 8883 bytes .../pip/_internal/commands/cache.py | 225 + .../pip/_internal/commands/check.py | 67 + .../pip/_internal/commands/completion.py | 130 + .../pip/_internal/commands/configuration.py | 280 + .../pip/_internal/commands/debug.py | 201 + .../pip/_internal/commands/download.py | 146 + .../pip/_internal/commands/freeze.py | 109 + .../pip/_internal/commands/hash.py | 59 + .../pip/_internal/commands/help.py | 41 + .../pip/_internal/commands/index.py | 139 + .../pip/_internal/commands/inspect.py | 92 + .../pip/_internal/commands/install.py | 783 ++ .../pip/_internal/commands/list.py | 375 + .../pip/_internal/commands/search.py | 172 + .../pip/_internal/commands/show.py | 217 + .../pip/_internal/commands/uninstall.py | 114 + .../pip/_internal/commands/wheel.py | 182 + .../pip/_internal/configuration.py | 383 + .../pip/_internal/distributions/__init__.py | 21 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 959 bytes .../__pycache__/base.cpython-312.pyc | Bin 0 -> 2911 bytes .../__pycache__/installed.cpython-312.pyc | Bin 0 -> 1718 bytes .../__pycache__/sdist.cpython-312.pyc | Bin 0 -> 8445 bytes .../__pycache__/wheel.cpython-312.pyc | Bin 0 -> 2299 bytes .../pip/_internal/distributions/base.py | 53 + .../pip/_internal/distributions/installed.py | 29 + .../pip/_internal/distributions/sdist.py | 158 + .../pip/_internal/distributions/wheel.py | 42 + .../site-packages/pip/_internal/exceptions.py | 777 ++ .../pip/_internal/index/__init__.py | 2 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 250 bytes .../__pycache__/collector.cpython-312.pyc | Bin 0 -> 21635 bytes .../package_finder.cpython-312.pyc | Bin 0 -> 40666 bytes .../index/__pycache__/sources.cpython-312.pyc | Bin 0 -> 12606 bytes .../pip/_internal/index/collector.py | 494 + .../pip/_internal/index/package_finder.py | 1020 ++ .../pip/_internal/index/sources.py | 285 + .../pip/_internal/locations/__init__.py | 456 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 16458 bytes .../__pycache__/_distutils.cpython-312.pyc | Bin 0 -> 6870 bytes .../__pycache__/_sysconfig.cpython-312.pyc | Bin 0 -> 8046 bytes .../__pycache__/base.cpython-312.pyc | Bin 0 -> 3799 bytes .../pip/_internal/locations/_distutils.py | 172 + .../pip/_internal/locations/_sysconfig.py | 214 + .../pip/_internal/locations/base.py | 81 + .../Lib/site-packages/pip/_internal/main.py | 12 + .../pip/_internal/metadata/__init__.py | 128 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 5887 bytes .../__pycache__/_json.cpython-312.pyc | Bin 0 -> 2944 bytes .../metadata/__pycache__/base.cpython-312.pyc | Bin 0 -> 35216 bytes .../__pycache__/pkg_resources.cpython-312.pyc | Bin 0 -> 16102 bytes .../pip/_internal/metadata/_json.py | 84 + .../pip/_internal/metadata/base.py | 688 ++ .../_internal/metadata/importlib/__init__.py | 6 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 376 bytes .../__pycache__/_compat.cpython-312.pyc | Bin 0 -> 4509 bytes .../__pycache__/_dists.cpython-312.pyc | Bin 0 -> 12583 bytes .../__pycache__/_envs.cpython-312.pyc | Bin 0 -> 11097 bytes .../_internal/metadata/importlib/_compat.py | 85 + .../_internal/metadata/importlib/_dists.py | 221 + .../pip/_internal/metadata/importlib/_envs.py | 189 + .../pip/_internal/metadata/pkg_resources.py | 301 + .../pip/_internal/models/__init__.py | 2 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 284 bytes .../__pycache__/candidate.cpython-312.pyc | Bin 0 -> 1622 bytes .../__pycache__/direct_url.cpython-312.pyc | Bin 0 -> 10862 bytes .../format_control.cpython-312.pyc | Bin 0 -> 4241 bytes .../models/__pycache__/index.cpython-312.pyc | Bin 0 -> 1712 bytes .../installation_report.cpython-312.pyc | Bin 0 -> 2295 bytes .../models/__pycache__/link.cpython-312.pyc | Bin 0 -> 26635 bytes .../models/__pycache__/scheme.cpython-312.pyc | Bin 0 -> 1041 bytes .../__pycache__/search_scope.cpython-312.pyc | Bin 0 -> 5005 bytes .../selection_prefs.cpython-312.pyc | Bin 0 -> 1869 bytes .../__pycache__/target_python.cpython-312.pyc | Bin 0 -> 4971 bytes .../models/__pycache__/wheel.cpython-312.pyc | Bin 0 -> 5778 bytes .../pip/_internal/models/candidate.py | 25 + .../pip/_internal/models/direct_url.py | 224 + .../pip/_internal/models/format_control.py | 78 + .../pip/_internal/models/index.py | 28 + .../_internal/models/installation_report.py | 56 + .../pip/_internal/models/link.py | 590 ++ .../pip/_internal/models/scheme.py | 25 + .../pip/_internal/models/search_scope.py | 127 + .../pip/_internal/models/selection_prefs.py | 53 + .../pip/_internal/models/target_python.py | 121 + .../pip/_internal/models/wheel.py | 93 + .../pip/_internal/network/__init__.py | 2 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 272 bytes .../network/__pycache__/auth.cpython-312.pyc | Bin 0 -> 22117 bytes .../network/__pycache__/cache.cpython-312.pyc | Bin 0 -> 6469 bytes .../__pycache__/download.cpython-312.pyc | Bin 0 -> 8497 bytes .../__pycache__/lazy_wheel.cpython-312.pyc | Bin 0 -> 11625 bytes .../__pycache__/session.cpython-312.pyc | Bin 0 -> 18892 bytes .../network/__pycache__/utils.cpython-312.pyc | Bin 0 -> 2273 bytes .../__pycache__/xmlrpc.cpython-312.pyc | Bin 0 -> 2967 bytes .../pip/_internal/network/auth.py | 566 ++ .../pip/_internal/network/cache.py | 106 + .../pip/_internal/network/download.py | 187 + .../pip/_internal/network/lazy_wheel.py | 210 + .../pip/_internal/network/session.py | 522 + .../pip/_internal/network/utils.py | 98 + .../pip/_internal/network/xmlrpc.py | 62 + .../pip/_internal/operations/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 215 bytes .../__pycache__/check.cpython-312.pyc | Bin 0 -> 7122 bytes .../__pycache__/freeze.cpython-312.pyc | Bin 0 -> 10146 bytes .../__pycache__/prepare.cpython-312.pyc | Bin 0 -> 25790 bytes .../_internal/operations/build/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 221 bytes .../__pycache__/build_tracker.cpython-312.pyc | Bin 0 -> 7685 bytes .../__pycache__/metadata.cpython-312.pyc | Bin 0 -> 1875 bytes .../metadata_editable.cpython-312.pyc | Bin 0 -> 1909 bytes .../metadata_legacy.cpython-312.pyc | Bin 0 -> 3029 bytes .../build/__pycache__/wheel.cpython-312.pyc | Bin 0 -> 1695 bytes .../wheel_editable.cpython-312.pyc | Bin 0 -> 2034 bytes .../__pycache__/wheel_legacy.cpython-312.pyc | Bin 0 -> 3864 bytes .../operations/build/build_tracker.py | 138 + .../_internal/operations/build/metadata.py | 39 + .../operations/build/metadata_editable.py | 41 + .../operations/build/metadata_legacy.py | 74 + .../pip/_internal/operations/build/wheel.py | 37 + .../operations/build/wheel_editable.py | 46 + .../operations/build/wheel_legacy.py | 102 + .../pip/_internal/operations/check.py | 181 + .../pip/_internal/operations/freeze.py | 258 + .../_internal/operations/install/__init__.py | 2 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 284 bytes .../editable_legacy.cpython-312.pyc | Bin 0 -> 1816 bytes .../install/__pycache__/wheel.cpython-312.pyc | Bin 0 -> 34121 bytes .../operations/install/editable_legacy.py | 47 + .../pip/_internal/operations/install/wheel.py | 741 ++ .../pip/_internal/operations/prepare.py | 732 ++ .../site-packages/pip/_internal/pyproject.py | 185 + .../pip/_internal/req/__init__.py | 90 + .../req/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 3463 bytes .../__pycache__/constructors.cpython-312.pyc | Bin 0 -> 21236 bytes .../req/__pycache__/req_file.cpython-312.pyc | Bin 0 -> 21450 bytes .../__pycache__/req_install.cpython-312.pyc | Bin 0 -> 38493 bytes .../req/__pycache__/req_set.cpython-312.pyc | Bin 0 -> 5501 bytes .../__pycache__/req_uninstall.cpython-312.pyc | Bin 0 -> 32112 bytes .../pip/_internal/req/constructors.py | 560 ++ .../pip/_internal/req/req_file.py | 551 ++ .../pip/_internal/req/req_install.py | 934 ++ .../pip/_internal/req/req_set.py | 82 + .../pip/_internal/req/req_uninstall.py | 633 ++ .../pip/_internal/resolution/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 215 bytes .../__pycache__/base.cpython-312.pyc | Bin 0 -> 1203 bytes .../pip/_internal/resolution/base.py | 20 + .../_internal/resolution/legacy/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 222 bytes .../__pycache__/resolver.cpython-312.pyc | Bin 0 -> 22597 bytes .../_internal/resolution/legacy/resolver.py | 597 ++ .../resolution/resolvelib/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 226 bytes .../__pycache__/base.cpython-312.pyc | Bin 0 -> 8167 bytes .../__pycache__/candidates.cpython-312.pyc | Bin 0 -> 29190 bytes .../__pycache__/factory.cpython-312.pyc | Bin 0 -> 32304 bytes .../found_candidates.cpython-312.pyc | Bin 0 -> 6811 bytes .../__pycache__/provider.cpython-312.pyc | Bin 0 -> 10541 bytes .../__pycache__/reporter.cpython-312.pyc | Bin 0 -> 5058 bytes .../__pycache__/requirements.cpython-312.pyc | Bin 0 -> 15374 bytes .../__pycache__/resolver.cpython-312.pyc | Bin 0 -> 12332 bytes .../_internal/resolution/resolvelib/base.py | 139 + .../resolution/resolvelib/candidates.py | 569 ++ .../resolution/resolvelib/factory.py | 817 ++ .../resolution/resolvelib/found_candidates.py | 174 + .../resolution/resolvelib/provider.py | 258 + .../resolution/resolvelib/reporter.py | 81 + .../resolution/resolvelib/requirements.py | 245 + .../resolution/resolvelib/resolver.py | 317 + .../pip/_internal/self_outdated_check.py | 244 + .../pip/_internal/utils/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 210 bytes .../__pycache__/_jaraco_text.cpython-312.pyc | Bin 0 -> 4545 bytes .../utils/__pycache__/_log.cpython-312.pyc | Bin 0 -> 1881 bytes .../utils/__pycache__/appdirs.cpython-312.pyc | Bin 0 -> 2425 bytes .../utils/__pycache__/compat.cpython-312.pyc | Bin 0 -> 2922 bytes .../compatibility_tags.cpython-312.pyc | Bin 0 -> 5578 bytes .../__pycache__/datetime.cpython-312.pyc | Bin 0 -> 699 bytes .../__pycache__/deprecation.cpython-312.pyc | Bin 0 -> 4206 bytes .../direct_url_helpers.cpython-312.pyc | Bin 0 -> 3551 bytes .../__pycache__/egg_link.cpython-312.pyc | Bin 0 -> 3221 bytes .../__pycache__/encoding.cpython-312.pyc | Bin 0 -> 2163 bytes .../__pycache__/entrypoints.cpython-312.pyc | Bin 0 -> 4008 bytes .../__pycache__/filesystem.cpython-312.pyc | Bin 0 -> 7344 bytes .../__pycache__/filetypes.cpython-312.pyc | Bin 0 -> 1179 bytes .../utils/__pycache__/glibc.cpython-312.pyc | Bin 0 -> 2434 bytes .../utils/__pycache__/hashes.cpython-312.pyc | Bin 0 -> 7618 bytes .../utils/__pycache__/logging.cpython-312.pyc | Bin 0 -> 13573 bytes .../utils/__pycache__/misc.cpython-312.pyc | Bin 0 -> 33566 bytes .../__pycache__/packaging.cpython-312.pyc | Bin 0 -> 2598 bytes .../utils/__pycache__/retry.cpython-312.pyc | Bin 0 -> 2123 bytes .../setuptools_build.cpython-312.pyc | Bin 0 -> 4565 bytes .../__pycache__/subprocess.cpython-312.pyc | Bin 0 -> 8654 bytes .../__pycache__/temp_dir.cpython-312.pyc | Bin 0 -> 12039 bytes .../__pycache__/unpacking.cpython-312.pyc | Bin 0 -> 13513 bytes .../utils/__pycache__/urls.cpython-312.pyc | Bin 0 -> 2092 bytes .../__pycache__/virtualenv.cpython-312.pyc | Bin 0 -> 4481 bytes .../utils/__pycache__/wheel.cpython-312.pyc | Bin 0 -> 5918 bytes .../pip/_internal/utils/_jaraco_text.py | 109 + .../site-packages/pip/_internal/utils/_log.py | 38 + .../pip/_internal/utils/appdirs.py | 52 + .../pip/_internal/utils/compat.py | 79 + .../pip/_internal/utils/compatibility_tags.py | 165 + .../pip/_internal/utils/datetime.py | 11 + .../pip/_internal/utils/deprecation.py | 124 + .../pip/_internal/utils/direct_url_helpers.py | 87 + .../pip/_internal/utils/egg_link.py | 80 + .../pip/_internal/utils/encoding.py | 36 + .../pip/_internal/utils/entrypoints.py | 84 + .../pip/_internal/utils/filesystem.py | 149 + .../pip/_internal/utils/filetypes.py | 27 + .../pip/_internal/utils/glibc.py | 101 + .../pip/_internal/utils/hashes.py | 147 + .../pip/_internal/utils/logging.py | 347 + .../site-packages/pip/_internal/utils/misc.py | 777 ++ .../pip/_internal/utils/packaging.py | 57 + .../pip/_internal/utils/retry.py | 42 + .../pip/_internal/utils/setuptools_build.py | 146 + .../pip/_internal/utils/subprocess.py | 245 + .../pip/_internal/utils/temp_dir.py | 296 + .../pip/_internal/utils/unpacking.py | 337 + .../site-packages/pip/_internal/utils/urls.py | 55 + .../pip/_internal/utils/virtualenv.py | 104 + .../pip/_internal/utils/wheel.py | 134 + .../pip/_internal/vcs/__init__.py | 15 + .../vcs/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 549 bytes .../vcs/__pycache__/bazaar.cpython-312.pyc | Bin 0 -> 5070 bytes .../vcs/__pycache__/git.cpython-312.pyc | Bin 0 -> 19035 bytes .../vcs/__pycache__/mercurial.cpython-312.pyc | Bin 0 -> 7623 bytes .../__pycache__/subversion.cpython-312.pyc | Bin 0 -> 12542 bytes .../versioncontrol.cpython-312.pyc | Bin 0 -> 29015 bytes .../site-packages/pip/_internal/vcs/bazaar.py | 112 + .../site-packages/pip/_internal/vcs/git.py | 527 + .../pip/_internal/vcs/mercurial.py | 163 + .../pip/_internal/vcs/subversion.py | 324 + .../pip/_internal/vcs/versioncontrol.py | 688 ++ .../pip/_internal/wheel_builder.py | 354 + .../Lib/site-packages/pip/_vendor/__init__.py | 116 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 4568 bytes .../typing_extensions.cpython-312.pyc | Bin 0 -> 139470 bytes .../pip/_vendor/cachecontrol/__init__.py | 28 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 921 bytes .../__pycache__/_cmd.cpython-312.pyc | Bin 0 -> 2665 bytes .../__pycache__/adapter.cpython-312.pyc | Bin 0 -> 6483 bytes .../__pycache__/cache.cpython-312.pyc | Bin 0 -> 3806 bytes .../__pycache__/controller.cpython-312.pyc | Bin 0 -> 16243 bytes .../__pycache__/filewrapper.cpython-312.pyc | Bin 0 -> 4366 bytes .../__pycache__/heuristics.cpython-312.pyc | Bin 0 -> 6713 bytes .../__pycache__/serialize.cpython-312.pyc | Bin 0 -> 5280 bytes .../__pycache__/wrapper.cpython-312.pyc | Bin 0 -> 1693 bytes .../pip/_vendor/cachecontrol/_cmd.py | 70 + .../pip/_vendor/cachecontrol/adapter.py | 161 + .../pip/_vendor/cachecontrol/cache.py | 74 + .../_vendor/cachecontrol/caches/__init__.py | 8 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 454 bytes .../__pycache__/file_cache.cpython-312.pyc | Bin 0 -> 7782 bytes .../__pycache__/redis_cache.cpython-312.pyc | Bin 0 -> 2752 bytes .../_vendor/cachecontrol/caches/file_cache.py | 182 + .../cachecontrol/caches/redis_cache.py | 48 + .../pip/_vendor/cachecontrol/controller.py | 499 + .../pip/_vendor/cachecontrol/filewrapper.py | 119 + .../pip/_vendor/cachecontrol/heuristics.py | 154 + .../pip/_vendor/cachecontrol/py.typed | 0 .../pip/_vendor/cachecontrol/serialize.py | 146 + .../pip/_vendor/cachecontrol/wrapper.py | 43 + .../pip/_vendor/certifi/__init__.py | 4 + .../pip/_vendor/certifi/__main__.py | 12 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 337 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 0 -> 664 bytes .../certifi/__pycache__/core.cpython-312.pyc | Bin 0 -> 3230 bytes .../pip/_vendor/certifi/cacert.pem | 4798 +++++++++ .../site-packages/pip/_vendor/certifi/core.py | 114 + .../pip/_vendor/certifi/py.typed | 0 .../pip/_vendor/distlib/__init__.py | 33 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1288 bytes .../__pycache__/compat.cpython-312.pyc | Bin 0 -> 45550 bytes .../__pycache__/database.cpython-312.pyc | Bin 0 -> 65700 bytes .../distlib/__pycache__/index.cpython-312.pyc | Bin 0 -> 24335 bytes .../__pycache__/locators.cpython-312.pyc | Bin 0 -> 59949 bytes .../__pycache__/manifest.cpython-312.pyc | Bin 0 -> 15095 bytes .../__pycache__/markers.cpython-312.pyc | Bin 0 -> 7697 bytes .../__pycache__/metadata.cpython-312.pyc | Bin 0 -> 41685 bytes .../__pycache__/resources.cpython-312.pyc | Bin 0 -> 17331 bytes .../__pycache__/scripts.cpython-312.pyc | Bin 0 -> 19788 bytes .../distlib/__pycache__/util.cpython-312.pyc | Bin 0 -> 88036 bytes .../__pycache__/version.cpython-312.pyc | Bin 0 -> 30364 bytes .../distlib/__pycache__/wheel.cpython-312.pyc | Bin 0 -> 51467 bytes .../pip/_vendor/distlib/compat.py | 1138 +++ .../pip/_vendor/distlib/database.py | 1359 +++ .../pip/_vendor/distlib/index.py | 508 + .../pip/_vendor/distlib/locators.py | 1303 +++ .../pip/_vendor/distlib/manifest.py | 384 + .../pip/_vendor/distlib/markers.py | 167 + .../pip/_vendor/distlib/metadata.py | 1068 ++ .../pip/_vendor/distlib/resources.py | 358 + .../pip/_vendor/distlib/scripts.py | 466 + .../site-packages/pip/_vendor/distlib/t32.exe | Bin 0 -> 97792 bytes .../pip/_vendor/distlib/t64-arm.exe | Bin 0 -> 182784 bytes .../site-packages/pip/_vendor/distlib/t64.exe | Bin 0 -> 108032 bytes .../site-packages/pip/_vendor/distlib/util.py | 2025 ++++ .../pip/_vendor/distlib/version.py | 751 ++ .../site-packages/pip/_vendor/distlib/w32.exe | Bin 0 -> 91648 bytes .../pip/_vendor/distlib/w64-arm.exe | Bin 0 -> 168448 bytes .../site-packages/pip/_vendor/distlib/w64.exe | Bin 0 -> 101888 bytes .../pip/_vendor/distlib/wheel.py | 1099 +++ .../pip/_vendor/distro/__init__.py | 54 + .../pip/_vendor/distro/__main__.py | 4 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 979 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 0 -> 311 bytes .../distro/__pycache__/distro.cpython-312.pyc | Bin 0 -> 53811 bytes .../pip/_vendor/distro/distro.py | 1403 +++ .../site-packages/pip/_vendor/distro/py.typed | 0 .../pip/_vendor/idna/__init__.py | 44 + .../idna/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 900 bytes .../idna/__pycache__/codec.cpython-312.pyc | Bin 0 -> 4995 bytes .../idna/__pycache__/compat.cpython-312.pyc | Bin 0 -> 906 bytes .../idna/__pycache__/core.cpython-312.pyc | Bin 0 -> 15810 bytes .../idna/__pycache__/idnadata.cpython-312.pyc | Bin 0 -> 99495 bytes .../__pycache__/intranges.cpython-312.pyc | Bin 0 -> 2652 bytes .../__pycache__/package_data.cpython-312.pyc | Bin 0 -> 235 bytes .../__pycache__/uts46data.cpython-312.pyc | Bin 0 -> 158867 bytes .../site-packages/pip/_vendor/idna/codec.py | 118 + .../site-packages/pip/_vendor/idna/compat.py | 13 + .../site-packages/pip/_vendor/idna/core.py | 395 + .../pip/_vendor/idna/idnadata.py | 4245 ++++++++ .../pip/_vendor/idna/intranges.py | 54 + .../pip/_vendor/idna/package_data.py | 2 + .../site-packages/pip/_vendor/idna/py.typed | 0 .../pip/_vendor/idna/uts46data.py | 8598 ++++++++++++++++ .../pip/_vendor/msgpack/__init__.py | 55 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1760 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 2044 bytes .../msgpack/__pycache__/ext.cpython-312.pyc | Bin 0 -> 8189 bytes .../__pycache__/fallback.cpython-312.pyc | Bin 0 -> 42062 bytes .../pip/_vendor/msgpack/exceptions.py | 48 + .../site-packages/pip/_vendor/msgpack/ext.py | 168 + .../pip/_vendor/msgpack/fallback.py | 951 ++ .../pip/_vendor/packaging/__init__.py | 15 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 577 bytes .../__pycache__/_elffile.cpython-312.pyc | Bin 0 -> 4986 bytes .../__pycache__/_manylinux.cpython-312.pyc | Bin 0 -> 9704 bytes .../__pycache__/_musllinux.cpython-312.pyc | Bin 0 -> 4573 bytes .../__pycache__/_parser.cpython-312.pyc | Bin 0 -> 14004 bytes .../__pycache__/_structures.cpython-312.pyc | Bin 0 -> 3260 bytes .../__pycache__/_tokenizer.cpython-312.pyc | Bin 0 -> 7934 bytes .../__pycache__/markers.cpython-312.pyc | Bin 0 -> 11030 bytes .../__pycache__/metadata.cpython-312.pyc | Bin 0 -> 24972 bytes .../__pycache__/requirements.cpython-312.pyc | Bin 0 -> 4429 bytes .../__pycache__/specifiers.cpython-312.pyc | Bin 0 -> 38758 bytes .../__pycache__/tags.cpython-312.pyc | Bin 0 -> 21363 bytes .../__pycache__/utils.cpython-312.pyc | Bin 0 -> 7360 bytes .../__pycache__/version.cpython-312.pyc | Bin 0 -> 19526 bytes .../pip/_vendor/packaging/_elffile.py | 110 + .../pip/_vendor/packaging/_manylinux.py | 262 + .../pip/_vendor/packaging/_musllinux.py | 85 + .../pip/_vendor/packaging/_parser.py | 354 + .../pip/_vendor/packaging/_structures.py | 61 + .../pip/_vendor/packaging/_tokenizer.py | 194 + .../pip/_vendor/packaging/markers.py | 325 + .../pip/_vendor/packaging/metadata.py | 804 ++ .../pip/_vendor/packaging/py.typed | 0 .../pip/_vendor/packaging/requirements.py | 91 + .../pip/_vendor/packaging/specifiers.py | 1009 ++ .../pip/_vendor/packaging/tags.py | 568 ++ .../pip/_vendor/packaging/utils.py | 174 + .../pip/_vendor/packaging/version.py | 563 ++ .../pip/_vendor/pkg_resources/__init__.py | 3676 +++++++ .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 161280 bytes .../pip/_vendor/platformdirs/__init__.py | 627 ++ .../pip/_vendor/platformdirs/__main__.py | 55 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 19848 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 0 -> 1967 bytes .../__pycache__/android.cpython-312.pyc | Bin 0 -> 10716 bytes .../__pycache__/api.cpython-312.pyc | Bin 0 -> 12930 bytes .../__pycache__/macos.cpython-312.pyc | Bin 0 -> 8026 bytes .../__pycache__/unix.cpython-312.pyc | Bin 0 -> 15056 bytes .../__pycache__/version.cpython-312.pyc | Bin 0 -> 616 bytes .../__pycache__/windows.cpython-312.pyc | Bin 0 -> 13693 bytes .../pip/_vendor/platformdirs/android.py | 249 + .../pip/_vendor/platformdirs/api.py | 292 + .../pip/_vendor/platformdirs/macos.py | 130 + .../pip/_vendor/platformdirs/py.typed | 0 .../pip/_vendor/platformdirs/unix.py | 275 + .../pip/_vendor/platformdirs/version.py | 16 + .../pip/_vendor/platformdirs/windows.py | 272 + .../pip/_vendor/pygments/__init__.py | 82 + .../pip/_vendor/pygments/__main__.py | 17 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 3508 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 0 -> 754 bytes .../__pycache__/cmdline.cpython-312.pyc | Bin 0 -> 26604 bytes .../__pycache__/console.cpython-312.pyc | Bin 0 -> 2648 bytes .../__pycache__/filter.cpython-312.pyc | Bin 0 -> 3241 bytes .../__pycache__/formatter.cpython-312.pyc | Bin 0 -> 4740 bytes .../__pycache__/lexer.cpython-312.pyc | Bin 0 -> 38381 bytes .../__pycache__/modeline.cpython-312.pyc | Bin 0 -> 1579 bytes .../__pycache__/plugin.cpython-312.pyc | Bin 0 -> 2628 bytes .../__pycache__/regexopt.cpython-312.pyc | Bin 0 -> 4097 bytes .../__pycache__/scanner.cpython-312.pyc | Bin 0 -> 4776 bytes .../__pycache__/sphinxext.cpython-312.pyc | Bin 0 -> 12118 bytes .../__pycache__/style.cpython-312.pyc | Bin 0 -> 6713 bytes .../__pycache__/token.cpython-312.pyc | Bin 0 -> 8209 bytes .../__pycache__/unistring.cpython-312.pyc | Bin 0 -> 32992 bytes .../pygments/__pycache__/util.cpython-312.pyc | Bin 0 -> 14089 bytes .../pip/_vendor/pygments/cmdline.py | 668 ++ .../pip/_vendor/pygments/console.py | 70 + .../pip/_vendor/pygments/filter.py | 70 + .../pip/_vendor/pygments/filters/__init__.py | 940 ++ .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 37931 bytes .../pip/_vendor/pygments/formatter.py | 129 + .../_vendor/pygments/formatters/__init__.py | 157 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 6922 bytes .../__pycache__/_mapping.cpython-312.pyc | Bin 0 -> 4235 bytes .../__pycache__/bbcode.cpython-312.pyc | Bin 0 -> 4242 bytes .../__pycache__/groff.cpython-312.pyc | Bin 0 -> 7313 bytes .../__pycache__/html.cpython-312.pyc | Bin 0 -> 41046 bytes .../__pycache__/img.cpython-312.pyc | Bin 0 -> 28568 bytes .../__pycache__/irc.cpython-312.pyc | Bin 0 -> 6075 bytes .../__pycache__/latex.cpython-312.pyc | Bin 0 -> 20145 bytes .../__pycache__/other.cpython-312.pyc | Bin 0 -> 6897 bytes .../__pycache__/pangomarkup.cpython-312.pyc | Bin 0 -> 2978 bytes .../__pycache__/rtf.cpython-312.pyc | Bin 0 -> 13793 bytes .../__pycache__/svg.cpython-312.pyc | Bin 0 -> 9159 bytes .../__pycache__/terminal.cpython-312.pyc | Bin 0 -> 5839 bytes .../__pycache__/terminal256.cpython-312.pyc | Bin 0 -> 15138 bytes .../_vendor/pygments/formatters/_mapping.py | 23 + .../pip/_vendor/pygments/formatters/bbcode.py | 108 + .../pip/_vendor/pygments/formatters/groff.py | 170 + .../pip/_vendor/pygments/formatters/html.py | 987 ++ .../pip/_vendor/pygments/formatters/img.py | 685 ++ .../pip/_vendor/pygments/formatters/irc.py | 154 + .../pip/_vendor/pygments/formatters/latex.py | 518 + .../pip/_vendor/pygments/formatters/other.py | 160 + .../pygments/formatters/pangomarkup.py | 83 + .../pip/_vendor/pygments/formatters/rtf.py | 349 + .../pip/_vendor/pygments/formatters/svg.py | 185 + .../_vendor/pygments/formatters/terminal.py | 127 + .../pygments/formatters/terminal256.py | 338 + .../pip/_vendor/pygments/lexer.py | 963 ++ .../pip/_vendor/pygments/lexers/__init__.py | 362 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 14641 bytes .../__pycache__/_mapping.cpython-312.pyc | Bin 0 -> 68283 bytes .../lexers/__pycache__/python.cpython-312.pyc | Bin 0 -> 42987 bytes .../pip/_vendor/pygments/lexers/_mapping.py | 589 ++ .../pip/_vendor/pygments/lexers/python.py | 1198 +++ .../pip/_vendor/pygments/modeline.py | 43 + .../pip/_vendor/pygments/plugin.py | 72 + .../pip/_vendor/pygments/regexopt.py | 91 + .../pip/_vendor/pygments/scanner.py | 104 + .../pip/_vendor/pygments/sphinxext.py | 247 + .../pip/_vendor/pygments/style.py | 203 + .../pip/_vendor/pygments/styles/__init__.py | 61 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 2684 bytes .../__pycache__/_mapping.cpython-312.pyc | Bin 0 -> 3668 bytes .../pip/_vendor/pygments/styles/_mapping.py | 54 + .../pip/_vendor/pygments/token.py | 214 + .../pip/_vendor/pygments/unistring.py | 153 + .../pip/_vendor/pygments/util.py | 324 + .../pip/_vendor/pyproject_hooks/__init__.py | 23 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 633 bytes .../__pycache__/_compat.cpython-312.pyc | Bin 0 -> 394 bytes .../__pycache__/_impl.cpython-312.pyc | Bin 0 -> 14713 bytes .../pip/_vendor/pyproject_hooks/_compat.py | 8 + .../pip/_vendor/pyproject_hooks/_impl.py | 330 + .../pyproject_hooks/_in_process/__init__.py | 18 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1100 bytes .../__pycache__/_in_process.cpython-312.pyc | Bin 0 -> 14373 bytes .../_in_process/_in_process.py | 353 + .../pip/_vendor/requests/__init__.py | 179 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 5273 bytes .../__pycache__/__version__.cpython-312.pyc | Bin 0 -> 604 bytes .../_internal_utils.cpython-312.pyc | Bin 0 -> 2044 bytes .../__pycache__/adapters.cpython-312.pyc | Bin 0 -> 28451 bytes .../requests/__pycache__/api.cpython-312.pyc | Bin 0 -> 7211 bytes .../requests/__pycache__/auth.cpython-312.pyc | Bin 0 -> 13941 bytes .../__pycache__/certs.cpython-312.pyc | Bin 0 -> 942 bytes .../__pycache__/compat.cpython-312.pyc | Bin 0 -> 1697 bytes .../__pycache__/cookies.cpython-312.pyc | Bin 0 -> 25218 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 7618 bytes .../requests/__pycache__/help.cpython-312.pyc | Bin 0 -> 4248 bytes .../__pycache__/hooks.cpython-312.pyc | Bin 0 -> 1071 bytes .../__pycache__/models.cpython-312.pyc | Bin 0 -> 35448 bytes .../__pycache__/packages.cpython-312.pyc | Bin 0 -> 1286 bytes .../__pycache__/sessions.cpython-312.pyc | Bin 0 -> 27866 bytes .../__pycache__/status_codes.cpython-312.pyc | Bin 0 -> 6043 bytes .../__pycache__/structures.cpython-312.pyc | Bin 0 -> 5643 bytes .../__pycache__/utils.cpython-312.pyc | Bin 0 -> 36386 bytes .../pip/_vendor/requests/__version__.py | 14 + .../pip/_vendor/requests/_internal_utils.py | 50 + .../pip/_vendor/requests/adapters.py | 719 ++ .../site-packages/pip/_vendor/requests/api.py | 157 + .../pip/_vendor/requests/auth.py | 314 + .../pip/_vendor/requests/certs.py | 24 + .../pip/_vendor/requests/compat.py | 78 + .../pip/_vendor/requests/cookies.py | 561 ++ .../pip/_vendor/requests/exceptions.py | 151 + .../pip/_vendor/requests/help.py | 127 + .../pip/_vendor/requests/hooks.py | 33 + .../pip/_vendor/requests/models.py | 1037 ++ .../pip/_vendor/requests/packages.py | 25 + .../pip/_vendor/requests/sessions.py | 831 ++ .../pip/_vendor/requests/status_codes.py | 128 + .../pip/_vendor/requests/structures.py | 99 + .../pip/_vendor/requests/utils.py | 1096 +++ .../pip/_vendor/resolvelib/__init__.py | 26 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 654 bytes .../__pycache__/providers.cpython-312.pyc | Bin 0 -> 6871 bytes .../__pycache__/reporters.cpython-312.pyc | Bin 0 -> 2674 bytes .../__pycache__/resolvers.cpython-312.pyc | Bin 0 -> 25900 bytes .../__pycache__/structs.cpython-312.pyc | Bin 0 -> 10520 bytes .../pip/_vendor/resolvelib/compat/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 220 bytes .../collections_abc.cpython-312.pyc | Bin 0 -> 440 bytes .../resolvelib/compat/collections_abc.py | 6 + .../pip/_vendor/resolvelib/providers.py | 133 + .../pip/_vendor/resolvelib/py.typed | 0 .../pip/_vendor/resolvelib/reporters.py | 43 + .../pip/_vendor/resolvelib/resolvers.py | 547 ++ .../pip/_vendor/resolvelib/structs.py | 170 + .../pip/_vendor/rich/__init__.py | 177 + .../pip/_vendor/rich/__main__.py | 273 + .../rich/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 7035 bytes .../rich/__pycache__/__main__.cpython-312.pyc | Bin 0 -> 10312 bytes .../__pycache__/_cell_widths.cpython-312.pyc | Bin 0 -> 7892 bytes .../__pycache__/_emoji_codes.cpython-312.pyc | Bin 0 -> 205996 bytes .../_emoji_replace.cpython-312.pyc | Bin 0 -> 1749 bytes .../_export_format.cpython-312.pyc | Bin 0 -> 2369 bytes .../__pycache__/_extension.cpython-312.pyc | Bin 0 -> 557 bytes .../rich/__pycache__/_fileno.cpython-312.pyc | Bin 0 -> 875 bytes .../rich/__pycache__/_inspect.cpython-312.pyc | Bin 0 -> 12093 bytes .../__pycache__/_log_render.cpython-312.pyc | Bin 0 -> 4167 bytes .../rich/__pycache__/_loop.cpython-312.pyc | Bin 0 -> 1890 bytes .../__pycache__/_null_file.cpython-312.pyc | Bin 0 -> 3640 bytes .../__pycache__/_palettes.cpython-312.pyc | Bin 0 -> 5180 bytes .../rich/__pycache__/_pick.cpython-312.pyc | Bin 0 -> 741 bytes .../rich/__pycache__/_ratio.cpython-312.pyc | Bin 0 -> 6590 bytes .../__pycache__/_spinners.cpython-312.pyc | Bin 0 -> 13199 bytes .../rich/__pycache__/_stack.cpython-312.pyc | Bin 0 -> 985 bytes .../rich/__pycache__/_timer.cpython-312.pyc | Bin 0 -> 885 bytes .../_win32_console.cpython-312.pyc | Bin 0 -> 28996 bytes .../rich/__pycache__/_windows.cpython-312.pyc | Bin 0 -> 2510 bytes .../_windows_renderer.cpython-312.pyc | Bin 0 -> 3583 bytes .../rich/__pycache__/_wrap.cpython-312.pyc | Bin 0 -> 3346 bytes .../rich/__pycache__/abc.cpython-312.pyc | Bin 0 -> 1628 bytes .../rich/__pycache__/align.cpython-312.pyc | Bin 0 -> 12307 bytes .../rich/__pycache__/ansi.cpython-312.pyc | Bin 0 -> 9086 bytes .../rich/__pycache__/bar.cpython-312.pyc | Bin 0 -> 4292 bytes .../rich/__pycache__/box.cpython-312.pyc | Bin 0 -> 11858 bytes .../rich/__pycache__/cells.cpython-312.pyc | Bin 0 -> 5830 bytes .../rich/__pycache__/color.cpython-312.pyc | Bin 0 -> 26589 bytes .../__pycache__/color_triplet.cpython-312.pyc | Bin 0 -> 1721 bytes .../rich/__pycache__/columns.cpython-312.pyc | Bin 0 -> 8604 bytes .../rich/__pycache__/console.cpython-312.pyc | Bin 0 -> 113456 bytes .../__pycache__/constrain.cpython-312.pyc | Bin 0 -> 2278 bytes .../__pycache__/containers.cpython-312.pyc | Bin 0 -> 9230 bytes .../rich/__pycache__/control.cpython-312.pyc | Bin 0 -> 10961 bytes .../default_styles.cpython-312.pyc | Bin 0 -> 10386 bytes .../rich/__pycache__/diagnose.cpython-312.pyc | Bin 0 -> 1508 bytes .../rich/__pycache__/emoji.cpython-312.pyc | Bin 0 -> 4232 bytes .../rich/__pycache__/errors.cpython-312.pyc | Bin 0 -> 1865 bytes .../__pycache__/file_proxy.cpython-312.pyc | Bin 0 -> 3591 bytes .../rich/__pycache__/filesize.cpython-312.pyc | Bin 0 -> 3092 bytes .../__pycache__/highlighter.cpython-312.pyc | Bin 0 -> 9907 bytes .../rich/__pycache__/json.cpython-312.pyc | Bin 0 -> 6055 bytes .../rich/__pycache__/jupyter.cpython-312.pyc | Bin 0 -> 5228 bytes .../rich/__pycache__/layout.cpython-312.pyc | Bin 0 -> 20178 bytes .../rich/__pycache__/live.cpython-312.pyc | Bin 0 -> 19029 bytes .../__pycache__/live_render.cpython-312.pyc | Bin 0 -> 4909 bytes .../rich/__pycache__/logging.cpython-312.pyc | Bin 0 -> 13574 bytes .../rich/__pycache__/markup.cpython-312.pyc | Bin 0 -> 9587 bytes .../rich/__pycache__/measure.cpython-312.pyc | Bin 0 -> 6398 bytes .../rich/__pycache__/padding.cpython-312.pyc | Bin 0 -> 7144 bytes .../rich/__pycache__/pager.cpython-312.pyc | Bin 0 -> 1831 bytes .../rich/__pycache__/palette.cpython-312.pyc | Bin 0 -> 5317 bytes .../rich/__pycache__/panel.cpython-312.pyc | Bin 0 -> 12203 bytes .../rich/__pycache__/pretty.cpython-312.pyc | Bin 0 -> 40167 bytes .../rich/__pycache__/progress.cpython-312.pyc | Bin 0 -> 74955 bytes .../__pycache__/progress_bar.cpython-312.pyc | Bin 0 -> 10397 bytes .../rich/__pycache__/prompt.cpython-312.pyc | Bin 0 -> 14807 bytes .../rich/__pycache__/protocol.cpython-312.pyc | Bin 0 -> 1812 bytes .../rich/__pycache__/region.cpython-312.pyc | Bin 0 -> 587 bytes .../rich/__pycache__/repr.cpython-312.pyc | Bin 0 -> 6633 bytes .../rich/__pycache__/rule.cpython-312.pyc | Bin 0 -> 6588 bytes .../rich/__pycache__/scope.cpython-312.pyc | Bin 0 -> 3845 bytes .../rich/__pycache__/screen.cpython-312.pyc | Bin 0 -> 2499 bytes .../rich/__pycache__/segment.cpython-312.pyc | Bin 0 -> 28135 bytes .../rich/__pycache__/spinner.cpython-312.pyc | Bin 0 -> 6084 bytes .../rich/__pycache__/status.cpython-312.pyc | Bin 0 -> 6081 bytes .../rich/__pycache__/style.cpython-312.pyc | Bin 0 -> 33520 bytes .../rich/__pycache__/styled.cpython-312.pyc | Bin 0 -> 2159 bytes .../rich/__pycache__/syntax.cpython-312.pyc | Bin 0 -> 39968 bytes .../rich/__pycache__/table.cpython-312.pyc | Bin 0 -> 43559 bytes .../terminal_theme.cpython-312.pyc | Bin 0 -> 3368 bytes .../rich/__pycache__/text.cpython-312.pyc | Bin 0 -> 60869 bytes .../rich/__pycache__/theme.cpython-312.pyc | Bin 0 -> 6355 bytes .../rich/__pycache__/themes.cpython-312.pyc | Bin 0 -> 334 bytes .../__pycache__/traceback.cpython-312.pyc | Bin 0 -> 31531 bytes .../rich/__pycache__/tree.cpython-312.pyc | Bin 0 -> 11456 bytes .../pip/_vendor/rich/_cell_widths.py | 454 + .../pip/_vendor/rich/_emoji_codes.py | 3610 +++++++ .../pip/_vendor/rich/_emoji_replace.py | 32 + .../pip/_vendor/rich/_export_format.py | 76 + .../pip/_vendor/rich/_extension.py | 10 + .../site-packages/pip/_vendor/rich/_fileno.py | 24 + .../pip/_vendor/rich/_inspect.py | 270 + .../pip/_vendor/rich/_log_render.py | 94 + .../site-packages/pip/_vendor/rich/_loop.py | 43 + .../pip/_vendor/rich/_null_file.py | 69 + .../pip/_vendor/rich/_palettes.py | 309 + .../site-packages/pip/_vendor/rich/_pick.py | 17 + .../site-packages/pip/_vendor/rich/_ratio.py | 159 + .../pip/_vendor/rich/_spinners.py | 482 + .../site-packages/pip/_vendor/rich/_stack.py | 16 + .../site-packages/pip/_vendor/rich/_timer.py | 19 + .../pip/_vendor/rich/_win32_console.py | 662 ++ .../pip/_vendor/rich/_windows.py | 71 + .../pip/_vendor/rich/_windows_renderer.py | 56 + .../site-packages/pip/_vendor/rich/_wrap.py | 93 + .../Lib/site-packages/pip/_vendor/rich/abc.py | 33 + .../site-packages/pip/_vendor/rich/align.py | 311 + .../site-packages/pip/_vendor/rich/ansi.py | 240 + .../Lib/site-packages/pip/_vendor/rich/bar.py | 93 + .../Lib/site-packages/pip/_vendor/rich/box.py | 480 + .../site-packages/pip/_vendor/rich/cells.py | 167 + .../site-packages/pip/_vendor/rich/color.py | 621 ++ .../pip/_vendor/rich/color_triplet.py | 38 + .../site-packages/pip/_vendor/rich/columns.py | 187 + .../site-packages/pip/_vendor/rich/console.py | 2633 +++++ .../pip/_vendor/rich/constrain.py | 37 + .../pip/_vendor/rich/containers.py | 167 + .../site-packages/pip/_vendor/rich/control.py | 225 + .../pip/_vendor/rich/default_styles.py | 190 + .../pip/_vendor/rich/diagnose.py | 37 + .../site-packages/pip/_vendor/rich/emoji.py | 96 + .../site-packages/pip/_vendor/rich/errors.py | 34 + .../pip/_vendor/rich/file_proxy.py | 57 + .../pip/_vendor/rich/filesize.py | 89 + .../pip/_vendor/rich/highlighter.py | 232 + .../site-packages/pip/_vendor/rich/json.py | 139 + .../site-packages/pip/_vendor/rich/jupyter.py | 101 + .../site-packages/pip/_vendor/rich/layout.py | 442 + .../site-packages/pip/_vendor/rich/live.py | 375 + .../pip/_vendor/rich/live_render.py | 112 + .../site-packages/pip/_vendor/rich/logging.py | 289 + .../site-packages/pip/_vendor/rich/markup.py | 251 + .../site-packages/pip/_vendor/rich/measure.py | 151 + .../site-packages/pip/_vendor/rich/padding.py | 141 + .../site-packages/pip/_vendor/rich/pager.py | 34 + .../site-packages/pip/_vendor/rich/palette.py | 100 + .../site-packages/pip/_vendor/rich/panel.py | 312 + .../site-packages/pip/_vendor/rich/pretty.py | 995 ++ .../pip/_vendor/rich/progress.py | 1699 ++++ .../pip/_vendor/rich/progress_bar.py | 223 + .../site-packages/pip/_vendor/rich/prompt.py | 375 + .../pip/_vendor/rich/protocol.py | 42 + .../site-packages/pip/_vendor/rich/py.typed | 0 .../site-packages/pip/_vendor/rich/region.py | 10 + .../site-packages/pip/_vendor/rich/repr.py | 149 + .../site-packages/pip/_vendor/rich/rule.py | 130 + .../site-packages/pip/_vendor/rich/scope.py | 86 + .../site-packages/pip/_vendor/rich/screen.py | 54 + .../site-packages/pip/_vendor/rich/segment.py | 738 ++ .../site-packages/pip/_vendor/rich/spinner.py | 137 + .../site-packages/pip/_vendor/rich/status.py | 131 + .../site-packages/pip/_vendor/rich/style.py | 796 ++ .../site-packages/pip/_vendor/rich/styled.py | 42 + .../site-packages/pip/_vendor/rich/syntax.py | 958 ++ .../site-packages/pip/_vendor/rich/table.py | 1000 ++ .../pip/_vendor/rich/terminal_theme.py | 153 + .../site-packages/pip/_vendor/rich/text.py | 1357 +++ .../site-packages/pip/_vendor/rich/theme.py | 115 + .../site-packages/pip/_vendor/rich/themes.py | 5 + .../pip/_vendor/rich/traceback.py | 753 ++ .../site-packages/pip/_vendor/rich/tree.py | 249 + .../pip/_vendor/tomli/__init__.py | 11 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 404 bytes .../tomli/__pycache__/_parser.cpython-312.pyc | Bin 0 -> 26919 bytes .../tomli/__pycache__/_re.cpython-312.pyc | Bin 0 -> 3928 bytes .../tomli/__pycache__/_types.cpython-312.pyc | Bin 0 -> 386 bytes .../pip/_vendor/tomli/_parser.py | 691 ++ .../site-packages/pip/_vendor/tomli/_re.py | 107 + .../site-packages/pip/_vendor/tomli/_types.py | 10 + .../site-packages/pip/_vendor/tomli/py.typed | 1 + .../pip/_vendor/truststore/__init__.py | 13 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 638 bytes .../__pycache__/_api.cpython-312.pyc | Bin 0 -> 16560 bytes .../__pycache__/_macos.cpython-312.pyc | Bin 0 -> 16592 bytes .../__pycache__/_openssl.cpython-312.pyc | Bin 0 -> 2225 bytes .../_ssl_constants.cpython-312.pyc | Bin 0 -> 1119 bytes .../__pycache__/_windows.cpython-312.pyc | Bin 0 -> 15760 bytes .../pip/_vendor/truststore/_api.py | 313 + .../pip/_vendor/truststore/_macos.py | 499 + .../pip/_vendor/truststore/_openssl.py | 66 + .../pip/_vendor/truststore/_ssl_constants.py | 31 + .../pip/_vendor/truststore/_windows.py | 564 ++ .../pip/_vendor/truststore/py.typed | 0 .../pip/_vendor/typing_extensions.py | 3641 +++++++ .../pip/_vendor/urllib3/__init__.py | 102 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 3425 bytes .../__pycache__/_collections.cpython-312.pyc | Bin 0 -> 16384 bytes .../__pycache__/_version.cpython-312.pyc | Bin 0 -> 238 bytes .../__pycache__/connection.cpython-312.pyc | Bin 0 -> 20423 bytes .../connectionpool.cpython-312.pyc | Bin 0 -> 36457 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 13513 bytes .../__pycache__/fields.cpython-312.pyc | Bin 0 -> 10422 bytes .../__pycache__/filepost.cpython-312.pyc | Bin 0 -> 4032 bytes .../__pycache__/poolmanager.cpython-312.pyc | Bin 0 -> 20449 bytes .../__pycache__/request.cpython-312.pyc | Bin 0 -> 7314 bytes .../__pycache__/response.cpython-312.pyc | Bin 0 -> 33963 bytes .../pip/_vendor/urllib3/_collections.py | 355 + .../pip/_vendor/urllib3/_version.py | 2 + .../pip/_vendor/urllib3/connection.py | 572 ++ .../pip/_vendor/urllib3/connectionpool.py | 1137 +++ .../pip/_vendor/urllib3/contrib/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 218 bytes .../_appengine_environ.cpython-312.pyc | Bin 0 -> 1868 bytes .../__pycache__/appengine.cpython-312.pyc | Bin 0 -> 11584 bytes .../__pycache__/ntlmpool.cpython-312.pyc | Bin 0 -> 5734 bytes .../__pycache__/pyopenssl.cpython-312.pyc | Bin 0 -> 24468 bytes .../securetransport.cpython-312.pyc | Bin 0 -> 35521 bytes .../contrib/__pycache__/socks.cpython-312.pyc | Bin 0 -> 7531 bytes .../urllib3/contrib/_appengine_environ.py | 36 + .../contrib/_securetransport/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 235 bytes .../__pycache__/bindings.cpython-312.pyc | Bin 0 -> 17447 bytes .../__pycache__/low_level.cpython-312.pyc | Bin 0 -> 14783 bytes .../contrib/_securetransport/bindings.py | 519 + .../contrib/_securetransport/low_level.py | 397 + .../pip/_vendor/urllib3/contrib/appengine.py | 314 + .../pip/_vendor/urllib3/contrib/ntlmpool.py | 130 + .../pip/_vendor/urllib3/contrib/pyopenssl.py | 518 + .../urllib3/contrib/securetransport.py | 920 ++ .../pip/_vendor/urllib3/contrib/socks.py | 216 + .../pip/_vendor/urllib3/exceptions.py | 323 + .../pip/_vendor/urllib3/fields.py | 274 + .../pip/_vendor/urllib3/filepost.py | 98 + .../pip/_vendor/urllib3/packages/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 219 bytes .../packages/__pycache__/six.cpython-312.pyc | Bin 0 -> 41275 bytes .../urllib3/packages/backports/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 229 bytes .../__pycache__/makefile.cpython-312.pyc | Bin 0 -> 1845 bytes .../weakref_finalize.cpython-312.pyc | Bin 0 -> 7356 bytes .../urllib3/packages/backports/makefile.py | 51 + .../packages/backports/weakref_finalize.py | 155 + .../pip/_vendor/urllib3/packages/six.py | 1076 ++ .../pip/_vendor/urllib3/poolmanager.py | 540 + .../pip/_vendor/urllib3/request.py | 191 + .../pip/_vendor/urllib3/response.py | 879 ++ .../pip/_vendor/urllib3/util/__init__.py | 49 + .../util/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1166 bytes .../__pycache__/connection.cpython-312.pyc | Bin 0 -> 4767 bytes .../util/__pycache__/proxy.cpython-312.pyc | Bin 0 -> 1572 bytes .../util/__pycache__/queue.cpython-312.pyc | Bin 0 -> 1372 bytes .../util/__pycache__/request.cpython-312.pyc | Bin 0 -> 4203 bytes .../util/__pycache__/response.cpython-312.pyc | Bin 0 -> 3012 bytes .../util/__pycache__/retry.cpython-312.pyc | Bin 0 -> 21721 bytes .../util/__pycache__/ssl_.cpython-312.pyc | Bin 0 -> 15104 bytes .../ssl_match_hostname.cpython-312.pyc | Bin 0 -> 5071 bytes .../__pycache__/ssltransport.cpython-312.pyc | Bin 0 -> 10773 bytes .../util/__pycache__/timeout.cpython-312.pyc | Bin 0 -> 11159 bytes .../util/__pycache__/url.cpython-312.pyc | Bin 0 -> 15805 bytes .../util/__pycache__/wait.cpython-312.pyc | Bin 0 -> 4423 bytes .../pip/_vendor/urllib3/util/connection.py | 149 + .../pip/_vendor/urllib3/util/proxy.py | 57 + .../pip/_vendor/urllib3/util/queue.py | 22 + .../pip/_vendor/urllib3/util/request.py | 137 + .../pip/_vendor/urllib3/util/response.py | 107 + .../pip/_vendor/urllib3/util/retry.py | 620 ++ .../pip/_vendor/urllib3/util/ssl_.py | 495 + .../urllib3/util/ssl_match_hostname.py | 159 + .../pip/_vendor/urllib3/util/ssltransport.py | 221 + .../pip/_vendor/urllib3/util/timeout.py | 271 + .../pip/_vendor/urllib3/util/url.py | 435 + .../pip/_vendor/urllib3/util/wait.py | 152 + .../Lib/site-packages/pip/_vendor/vendor.txt | 18 + backend/venv/Lib/site-packages/pip/py.typed | 4 + .../python_dotenv-1.1.1.dist-info/INSTALLER | 1 + .../python_dotenv-1.1.1.dist-info/METADATA | 733 ++ .../python_dotenv-1.1.1.dist-info/RECORD | 26 + .../python_dotenv-1.1.1.dist-info/REQUESTED | 0 .../python_dotenv-1.1.1.dist-info/WHEEL | 5 + .../entry_points.txt | 2 + .../licenses/LICENSE | 27 + .../top_level.txt | 1 + .../requests-2.32.5.dist-info/INSTALLER | 1 + .../requests-2.32.5.dist-info/METADATA | 133 + .../requests-2.32.5.dist-info/RECORD | 43 + .../requests-2.32.5.dist-info/REQUESTED | 0 .../requests-2.32.5.dist-info/WHEEL | 5 + .../licenses/LICENSE | 175 + .../requests-2.32.5.dist-info/top_level.txt | 1 + .../Lib/site-packages/requests/__init__.py | 184 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 5428 bytes .../__pycache__/__version__.cpython-312.pyc | Bin 0 -> 592 bytes .../_internal_utils.cpython-312.pyc | Bin 0 -> 2032 bytes .../__pycache__/adapters.cpython-312.pyc | Bin 0 -> 27813 bytes .../requests/__pycache__/api.cpython-312.pyc | Bin 0 -> 7199 bytes .../requests/__pycache__/auth.cpython-312.pyc | Bin 0 -> 13929 bytes .../__pycache__/certs.cpython-312.pyc | Bin 0 -> 674 bytes .../__pycache__/compat.cpython-312.pyc | Bin 0 -> 2383 bytes .../__pycache__/cookies.cpython-312.pyc | Bin 0 -> 25206 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 7593 bytes .../requests/__pycache__/help.cpython-312.pyc | Bin 0 -> 4335 bytes .../__pycache__/hooks.cpython-312.pyc | Bin 0 -> 1059 bytes .../__pycache__/models.cpython-312.pyc | Bin 0 -> 35459 bytes .../__pycache__/packages.cpython-312.pyc | Bin 0 -> 1126 bytes .../__pycache__/sessions.cpython-312.pyc | Bin 0 -> 27862 bytes .../__pycache__/status_codes.cpython-312.pyc | Bin 0 -> 6031 bytes .../__pycache__/structures.cpython-312.pyc | Bin 0 -> 5631 bytes .../__pycache__/utils.cpython-312.pyc | Bin 0 -> 36110 bytes .../Lib/site-packages/requests/__version__.py | 14 + .../site-packages/requests/_internal_utils.py | 50 + .../Lib/site-packages/requests/adapters.py | 696 ++ .../venv/Lib/site-packages/requests/api.py | 157 + .../venv/Lib/site-packages/requests/auth.py | 314 + .../venv/Lib/site-packages/requests/certs.py | 17 + .../venv/Lib/site-packages/requests/compat.py | 106 + .../Lib/site-packages/requests/cookies.py | 561 ++ .../Lib/site-packages/requests/exceptions.py | 151 + .../venv/Lib/site-packages/requests/help.py | 134 + .../venv/Lib/site-packages/requests/hooks.py | 33 + .../venv/Lib/site-packages/requests/models.py | 1039 ++ .../Lib/site-packages/requests/packages.py | 23 + .../Lib/site-packages/requests/sessions.py | 831 ++ .../site-packages/requests/status_codes.py | 128 + .../Lib/site-packages/requests/structures.py | 99 + .../venv/Lib/site-packages/requests/utils.py | 1086 +++ .../urllib3-2.5.0.dist-info/INSTALLER | 1 + .../urllib3-2.5.0.dist-info/METADATA | 154 + .../urllib3-2.5.0.dist-info/RECORD | 79 + .../urllib3-2.5.0.dist-info/WHEEL | 4 + .../licenses/LICENSE.txt | 21 + .../Lib/site-packages/urllib3/__init__.py | 211 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 7323 bytes .../_base_connection.cpython-312.pyc | Bin 0 -> 6873 bytes .../__pycache__/_collections.cpython-312.pyc | Bin 0 -> 22474 bytes .../_request_methods.cpython-312.pyc | Bin 0 -> 10615 bytes .../__pycache__/_version.cpython-312.pyc | Bin 0 -> 659 bytes .../__pycache__/connection.cpython-312.pyc | Bin 0 -> 38407 bytes .../connectionpool.cpython-312.pyc | Bin 0 -> 39743 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 16624 bytes .../__pycache__/fields.cpython-312.pyc | Bin 0 -> 12017 bytes .../__pycache__/filepost.cpython-312.pyc | Bin 0 -> 3492 bytes .../__pycache__/poolmanager.cpython-312.pyc | Bin 0 -> 24373 bytes .../__pycache__/response.cpython-312.pyc | Bin 0 -> 52709 bytes .../site-packages/urllib3/_base_connection.py | 165 + .../Lib/site-packages/urllib3/_collections.py | 479 + .../site-packages/urllib3/_request_methods.py | 278 + .../Lib/site-packages/urllib3/_version.py | 21 + .../Lib/site-packages/urllib3/connection.py | 1093 +++ .../site-packages/urllib3/connectionpool.py | 1178 +++ .../site-packages/urllib3/contrib/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 206 bytes .../__pycache__/pyopenssl.cpython-312.pyc | Bin 0 -> 28230 bytes .../contrib/__pycache__/socks.cpython-312.pyc | Bin 0 -> 8184 bytes .../urllib3/contrib/emscripten/__init__.py | 16 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 914 bytes .../__pycache__/connection.cpython-312.pyc | Bin 0 -> 10250 bytes .../__pycache__/fetch.cpython-312.pyc | Bin 0 -> 28646 bytes .../__pycache__/request.cpython-312.pyc | Bin 0 -> 1434 bytes .../__pycache__/response.cpython-312.pyc | Bin 0 -> 12222 bytes .../urllib3/contrib/emscripten/connection.py | 255 + .../emscripten/emscripten_fetch_worker.js | 110 + .../urllib3/contrib/emscripten/fetch.py | 728 ++ .../urllib3/contrib/emscripten/request.py | 22 + .../urllib3/contrib/emscripten/response.py | 277 + .../urllib3/contrib/pyopenssl.py | 564 ++ .../site-packages/urllib3/contrib/socks.py | 228 + .../Lib/site-packages/urllib3/exceptions.py | 335 + .../venv/Lib/site-packages/urllib3/fields.py | 341 + .../Lib/site-packages/urllib3/filepost.py | 89 + .../site-packages/urllib3/http2/__init__.py | 53 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1759 bytes .../__pycache__/connection.cpython-312.pyc | Bin 0 -> 16980 bytes .../http2/__pycache__/probe.cpython-312.pyc | Bin 0 -> 3670 bytes .../site-packages/urllib3/http2/connection.py | 356 + .../Lib/site-packages/urllib3/http2/probe.py | 87 + .../Lib/site-packages/urllib3/poolmanager.py | 653 ++ .../venv/Lib/site-packages/urllib3/py.typed | 2 + .../Lib/site-packages/urllib3/response.py | 1307 +++ .../site-packages/urllib3/util/__init__.py | 42 + .../util/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1019 bytes .../__pycache__/connection.cpython-312.pyc | Bin 0 -> 4700 bytes .../util/__pycache__/proxy.cpython-312.pyc | Bin 0 -> 1231 bytes .../util/__pycache__/request.cpython-312.pyc | Bin 0 -> 8331 bytes .../util/__pycache__/response.cpython-312.pyc | Bin 0 -> 2890 bytes .../util/__pycache__/retry.cpython-312.pyc | Bin 0 -> 20305 bytes .../util/__pycache__/ssl_.cpython-312.pyc | Bin 0 -> 17169 bytes .../ssl_match_hostname.cpython-312.pyc | Bin 0 -> 5551 bytes .../__pycache__/ssltransport.cpython-312.pyc | Bin 0 -> 13319 bytes .../util/__pycache__/timeout.cpython-312.pyc | Bin 0 -> 11703 bytes .../util/__pycache__/url.cpython-312.pyc | Bin 0 -> 16234 bytes .../util/__pycache__/util.cpython-312.pyc | Bin 0 -> 2008 bytes .../util/__pycache__/wait.cpython-312.pyc | Bin 0 -> 3454 bytes .../site-packages/urllib3/util/connection.py | 137 + .../Lib/site-packages/urllib3/util/proxy.py | 43 + .../Lib/site-packages/urllib3/util/request.py | 266 + .../site-packages/urllib3/util/response.py | 101 + .../Lib/site-packages/urllib3/util/retry.py | 533 + .../Lib/site-packages/urllib3/util/ssl_.py | 524 + .../urllib3/util/ssl_match_hostname.py | 159 + .../urllib3/util/ssltransport.py | 271 + .../Lib/site-packages/urllib3/util/timeout.py | 275 + .../Lib/site-packages/urllib3/util/url.py | 469 + .../Lib/site-packages/urllib3/util/util.py | 42 + .../Lib/site-packages/urllib3/util/wait.py | 124 + .../werkzeug-3.1.3.dist-info/INSTALLER | 1 + .../werkzeug-3.1.3.dist-info/LICENSE.txt | 28 + .../werkzeug-3.1.3.dist-info/METADATA | 99 + .../werkzeug-3.1.3.dist-info/RECORD | 116 + .../werkzeug-3.1.3.dist-info/WHEEL | 4 + .../Lib/site-packages/werkzeug/__init__.py | 4 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 353 bytes .../__pycache__/_internal.cpython-312.pyc | Bin 0 -> 9776 bytes .../__pycache__/_reloader.cpython-312.pyc | Bin 0 -> 20566 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 33337 bytes .../__pycache__/formparser.cpython-312.pyc | Bin 0 -> 17034 bytes .../werkzeug/__pycache__/http.cpython-312.pyc | Bin 0 -> 50225 bytes .../__pycache__/local.cpython-312.pyc | Bin 0 -> 28477 bytes .../__pycache__/security.cpython-312.pyc | Bin 0 -> 7144 bytes .../__pycache__/serving.cpython-312.pyc | Bin 0 -> 46102 bytes .../werkzeug/__pycache__/test.cpython-312.pyc | Bin 0 -> 59825 bytes .../__pycache__/testapp.cpython-312.pyc | Bin 0 -> 8876 bytes .../werkzeug/__pycache__/urls.cpython-312.pyc | Bin 0 -> 8277 bytes .../__pycache__/user_agent.cpython-312.pyc | Bin 0 -> 2166 bytes .../__pycache__/utils.cpython-312.pyc | Bin 0 -> 28145 bytes .../werkzeug/__pycache__/wsgi.cpython-312.pyc | Bin 0 -> 25222 bytes .../Lib/site-packages/werkzeug/_internal.py | 211 + .../Lib/site-packages/werkzeug/_reloader.py | 471 + .../werkzeug/datastructures/__init__.py | 64 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 2430 bytes .../__pycache__/accept.cpython-312.pyc | Bin 0 -> 15930 bytes .../__pycache__/auth.cpython-312.pyc | Bin 0 -> 14463 bytes .../__pycache__/cache_control.cpython-312.pyc | Bin 0 -> 12236 bytes .../__pycache__/csp.cpython-312.pyc | Bin 0 -> 6199 bytes .../__pycache__/etag.cpython-312.pyc | Bin 0 -> 5423 bytes .../__pycache__/file_storage.cpython-312.pyc | Bin 0 -> 8837 bytes .../__pycache__/headers.cpython-312.pyc | Bin 0 -> 30470 bytes .../__pycache__/mixins.cpython-312.pyc | Bin 0 -> 16413 bytes .../__pycache__/range.cpython-312.pyc | Bin 0 -> 10056 bytes .../__pycache__/structures.cpython-312.pyc | Bin 0 -> 58951 bytes .../werkzeug/datastructures/accept.py | 350 + .../werkzeug/datastructures/auth.py | 317 + .../werkzeug/datastructures/cache_control.py | 273 + .../werkzeug/datastructures/csp.py | 100 + .../werkzeug/datastructures/etag.py | 106 + .../werkzeug/datastructures/file_storage.py | 209 + .../werkzeug/datastructures/headers.py | 662 ++ .../werkzeug/datastructures/mixins.py | 317 + .../werkzeug/datastructures/range.py | 214 + .../werkzeug/datastructures/structures.py | 1239 +++ .../site-packages/werkzeug/debug/__init__.py | 565 ++ .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 23420 bytes .../debug/__pycache__/console.cpython-312.pyc | Bin 0 -> 11645 bytes .../debug/__pycache__/repr.cpython-312.pyc | Bin 0 -> 13787 bytes .../debug/__pycache__/tbtools.cpython-312.pyc | Bin 0 -> 16988 bytes .../site-packages/werkzeug/debug/console.py | 219 + .../Lib/site-packages/werkzeug/debug/repr.py | 282 + .../werkzeug/debug/shared/ICON_LICENSE.md | 6 + .../werkzeug/debug/shared/console.png | Bin 0 -> 507 bytes .../werkzeug/debug/shared/debugger.js | 344 + .../werkzeug/debug/shared/less.png | Bin 0 -> 191 bytes .../werkzeug/debug/shared/more.png | Bin 0 -> 200 bytes .../werkzeug/debug/shared/style.css | 150 + .../site-packages/werkzeug/debug/tbtools.py | 450 + .../Lib/site-packages/werkzeug/exceptions.py | 894 ++ .../Lib/site-packages/werkzeug/formparser.py | 430 + .../venv/Lib/site-packages/werkzeug/http.py | 1405 +++ .../venv/Lib/site-packages/werkzeug/local.py | 653 ++ .../werkzeug/middleware/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 210 bytes .../__pycache__/dispatcher.cpython-312.pyc | Bin 0 -> 3328 bytes .../__pycache__/http_proxy.cpython-312.pyc | Bin 0 -> 9424 bytes .../__pycache__/lint.cpython-312.pyc | Bin 0 -> 17770 bytes .../__pycache__/profiler.cpython-312.pyc | Bin 0 -> 7214 bytes .../__pycache__/proxy_fix.cpython-312.pyc | Bin 0 -> 7211 bytes .../__pycache__/shared_data.cpython-312.pyc | Bin 0 -> 12746 bytes .../werkzeug/middleware/dispatcher.py | 81 + .../werkzeug/middleware/http_proxy.py | 236 + .../site-packages/werkzeug/middleware/lint.py | 439 + .../werkzeug/middleware/profiler.py | 155 + .../werkzeug/middleware/proxy_fix.py | 183 + .../werkzeug/middleware/shared_data.py | 283 + .../venv/Lib/site-packages/werkzeug/py.typed | 0 .../werkzeug/routing/__init__.py | 134 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 4683 bytes .../__pycache__/converters.cpython-312.pyc | Bin 0 -> 10930 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 0 -> 7926 bytes .../routing/__pycache__/map.cpython-312.pyc | Bin 0 -> 39811 bytes .../__pycache__/matcher.cpython-312.pyc | Bin 0 -> 8249 bytes .../routing/__pycache__/rules.cpython-312.pyc | Bin 0 -> 39095 bytes .../werkzeug/routing/converters.py | 261 + .../werkzeug/routing/exceptions.py | 152 + .../Lib/site-packages/werkzeug/routing/map.py | 951 ++ .../site-packages/werkzeug/routing/matcher.py | 202 + .../site-packages/werkzeug/routing/rules.py | 928 ++ .../site-packages/werkzeug/sansio/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 206 bytes .../sansio/__pycache__/http.cpython-312.pyc | Bin 0 -> 5652 bytes .../__pycache__/multipart.cpython-312.pyc | Bin 0 -> 14055 bytes .../__pycache__/request.cpython-312.pyc | Bin 0 -> 21899 bytes .../__pycache__/response.cpython-312.pyc | Bin 0 -> 31743 bytes .../sansio/__pycache__/utils.cpython-312.pyc | Bin 0 -> 6191 bytes .../Lib/site-packages/werkzeug/sansio/http.py | 170 + .../werkzeug/sansio/multipart.py | 323 + .../site-packages/werkzeug/sansio/request.py | 534 + .../site-packages/werkzeug/sansio/response.py | 763 ++ .../site-packages/werkzeug/sansio/utils.py | 167 + .../Lib/site-packages/werkzeug/security.py | 166 + .../Lib/site-packages/werkzeug/serving.py | 1125 +++ .../venv/Lib/site-packages/werkzeug/test.py | 1464 +++ .../Lib/site-packages/werkzeug/testapp.py | 194 + .../venv/Lib/site-packages/werkzeug/urls.py | 203 + .../Lib/site-packages/werkzeug/user_agent.py | 47 + .../venv/Lib/site-packages/werkzeug/utils.py | 691 ++ .../werkzeug/wrappers/__init__.py | 3 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 330 bytes .../__pycache__/request.cpython-312.pyc | Bin 0 -> 26139 bytes .../__pycache__/response.cpython-312.pyc | Bin 0 -> 34571 bytes .../werkzeug/wrappers/request.py | 650 ++ .../werkzeug/wrappers/response.py | 831 ++ .../venv/Lib/site-packages/werkzeug/wsgi.py | 595 ++ backend/venv/Scripts/Activate.ps1 | 502 + backend/venv/Scripts/activate | 70 + backend/venv/Scripts/activate.bat | 34 + backend/venv/Scripts/deactivate.bat | 22 + backend/venv/Scripts/dotenv.exe | Bin 0 -> 108432 bytes backend/venv/Scripts/flask.exe | Bin 0 -> 108428 bytes backend/venv/Scripts/normalizer.exe | Bin 0 -> 108453 bytes backend/venv/Scripts/pip.exe | Bin 0 -> 108441 bytes backend/venv/Scripts/pip3.12.exe | Bin 0 -> 108441 bytes backend/venv/Scripts/pip3.exe | Bin 0 -> 108441 bytes backend/venv/Scripts/python.exe | Bin 0 -> 270104 bytes backend/venv/Scripts/pythonw.exe | Bin 0 -> 258840 bytes backend/venv/pyvenv.cfg | 5 + frontend/src/pages/Hero.css | 102 +- frontend/src/pages/Hero.js | 50 +- frontend/src/pages/Repositories.css | 89 +- frontend/src/pages/Repositories.js | 123 +- 1454 files changed, 246368 insertions(+), 40 deletions(-) create mode 100644 backend/__pycache__/app.cpython-312.pyc create mode 100644 backend/app.py create mode 100644 backend/package-lock.json create mode 100644 backend/package.json create mode 100644 backend/requirements.txt create mode 100644 backend/venv/Lib/site-packages/blinker-1.9.0.dist-info/INSTALLER create mode 100644 backend/venv/Lib/site-packages/blinker-1.9.0.dist-info/LICENSE.txt create mode 100644 backend/venv/Lib/site-packages/blinker-1.9.0.dist-info/METADATA create mode 100644 backend/venv/Lib/site-packages/blinker-1.9.0.dist-info/RECORD create mode 100644 backend/venv/Lib/site-packages/blinker-1.9.0.dist-info/WHEEL create mode 100644 backend/venv/Lib/site-packages/blinker/__init__.py create mode 100644 backend/venv/Lib/site-packages/blinker/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/blinker/__pycache__/_utilities.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/blinker/__pycache__/base.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/blinker/_utilities.py create mode 100644 backend/venv/Lib/site-packages/blinker/base.py create mode 100644 backend/venv/Lib/site-packages/blinker/py.typed create mode 100644 backend/venv/Lib/site-packages/certifi-2025.10.5.dist-info/INSTALLER create mode 100644 backend/venv/Lib/site-packages/certifi-2025.10.5.dist-info/METADATA create mode 100644 backend/venv/Lib/site-packages/certifi-2025.10.5.dist-info/RECORD create mode 100644 backend/venv/Lib/site-packages/certifi-2025.10.5.dist-info/WHEEL create mode 100644 backend/venv/Lib/site-packages/certifi-2025.10.5.dist-info/licenses/LICENSE create mode 100644 backend/venv/Lib/site-packages/certifi-2025.10.5.dist-info/top_level.txt create mode 100644 backend/venv/Lib/site-packages/certifi/__init__.py create mode 100644 backend/venv/Lib/site-packages/certifi/__main__.py create mode 100644 backend/venv/Lib/site-packages/certifi/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/certifi/__pycache__/__main__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/certifi/__pycache__/core.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/certifi/cacert.pem create mode 100644 backend/venv/Lib/site-packages/certifi/core.py create mode 100644 backend/venv/Lib/site-packages/certifi/py.typed create mode 100644 backend/venv/Lib/site-packages/charset_normalizer-3.4.3.dist-info/INSTALLER create mode 100644 backend/venv/Lib/site-packages/charset_normalizer-3.4.3.dist-info/METADATA create mode 100644 backend/venv/Lib/site-packages/charset_normalizer-3.4.3.dist-info/RECORD create mode 100644 backend/venv/Lib/site-packages/charset_normalizer-3.4.3.dist-info/WHEEL create mode 100644 backend/venv/Lib/site-packages/charset_normalizer-3.4.3.dist-info/entry_points.txt create mode 100644 backend/venv/Lib/site-packages/charset_normalizer-3.4.3.dist-info/licenses/LICENSE create mode 100644 backend/venv/Lib/site-packages/charset_normalizer-3.4.3.dist-info/top_level.txt create mode 100644 backend/venv/Lib/site-packages/charset_normalizer/__init__.py create mode 100644 backend/venv/Lib/site-packages/charset_normalizer/__main__.py create mode 100644 backend/venv/Lib/site-packages/charset_normalizer/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/charset_normalizer/__pycache__/__main__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/charset_normalizer/__pycache__/api.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/charset_normalizer/__pycache__/cd.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/charset_normalizer/__pycache__/constant.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/charset_normalizer/__pycache__/legacy.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/charset_normalizer/__pycache__/md.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/charset_normalizer/__pycache__/models.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/charset_normalizer/__pycache__/utils.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/charset_normalizer/__pycache__/version.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/charset_normalizer/api.py create mode 100644 backend/venv/Lib/site-packages/charset_normalizer/cd.py create mode 100644 backend/venv/Lib/site-packages/charset_normalizer/cli/__init__.py create mode 100644 backend/venv/Lib/site-packages/charset_normalizer/cli/__main__.py create mode 100644 backend/venv/Lib/site-packages/charset_normalizer/cli/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/charset_normalizer/cli/__pycache__/__main__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/charset_normalizer/constant.py create mode 100644 backend/venv/Lib/site-packages/charset_normalizer/legacy.py create mode 100644 backend/venv/Lib/site-packages/charset_normalizer/md.cp312-win_amd64.pyd create mode 100644 backend/venv/Lib/site-packages/charset_normalizer/md.py create mode 100644 backend/venv/Lib/site-packages/charset_normalizer/md__mypyc.cp312-win_amd64.pyd create mode 100644 backend/venv/Lib/site-packages/charset_normalizer/models.py create mode 100644 backend/venv/Lib/site-packages/charset_normalizer/py.typed create mode 100644 backend/venv/Lib/site-packages/charset_normalizer/utils.py create mode 100644 backend/venv/Lib/site-packages/charset_normalizer/version.py create mode 100644 backend/venv/Lib/site-packages/click-8.3.0.dist-info/INSTALLER create mode 100644 backend/venv/Lib/site-packages/click-8.3.0.dist-info/METADATA create mode 100644 backend/venv/Lib/site-packages/click-8.3.0.dist-info/RECORD create mode 100644 backend/venv/Lib/site-packages/click-8.3.0.dist-info/WHEEL create mode 100644 backend/venv/Lib/site-packages/click-8.3.0.dist-info/licenses/LICENSE.txt create mode 100644 backend/venv/Lib/site-packages/click/__init__.py create mode 100644 backend/venv/Lib/site-packages/click/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/click/__pycache__/_compat.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/click/__pycache__/_termui_impl.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/click/__pycache__/_textwrap.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/click/__pycache__/_utils.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/click/__pycache__/_winconsole.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/click/__pycache__/core.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/click/__pycache__/decorators.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/click/__pycache__/exceptions.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/click/__pycache__/formatting.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/click/__pycache__/globals.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/click/__pycache__/parser.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/click/__pycache__/shell_completion.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/click/__pycache__/termui.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/click/__pycache__/testing.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/click/__pycache__/types.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/click/__pycache__/utils.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/click/_compat.py create mode 100644 backend/venv/Lib/site-packages/click/_termui_impl.py create mode 100644 backend/venv/Lib/site-packages/click/_textwrap.py create mode 100644 backend/venv/Lib/site-packages/click/_utils.py create mode 100644 backend/venv/Lib/site-packages/click/_winconsole.py create mode 100644 backend/venv/Lib/site-packages/click/core.py create mode 100644 backend/venv/Lib/site-packages/click/decorators.py create mode 100644 backend/venv/Lib/site-packages/click/exceptions.py create mode 100644 backend/venv/Lib/site-packages/click/formatting.py create mode 100644 backend/venv/Lib/site-packages/click/globals.py create mode 100644 backend/venv/Lib/site-packages/click/parser.py create mode 100644 backend/venv/Lib/site-packages/click/py.typed create mode 100644 backend/venv/Lib/site-packages/click/shell_completion.py create mode 100644 backend/venv/Lib/site-packages/click/termui.py create mode 100644 backend/venv/Lib/site-packages/click/testing.py create mode 100644 backend/venv/Lib/site-packages/click/types.py create mode 100644 backend/venv/Lib/site-packages/click/utils.py create mode 100644 backend/venv/Lib/site-packages/colorama-0.4.6.dist-info/INSTALLER create mode 100644 backend/venv/Lib/site-packages/colorama-0.4.6.dist-info/METADATA create mode 100644 backend/venv/Lib/site-packages/colorama-0.4.6.dist-info/RECORD create mode 100644 backend/venv/Lib/site-packages/colorama-0.4.6.dist-info/WHEEL create mode 100644 backend/venv/Lib/site-packages/colorama-0.4.6.dist-info/licenses/LICENSE.txt create mode 100644 backend/venv/Lib/site-packages/colorama/__init__.py create mode 100644 backend/venv/Lib/site-packages/colorama/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/colorama/__pycache__/ansi.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/colorama/__pycache__/ansitowin32.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/colorama/__pycache__/initialise.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/colorama/__pycache__/win32.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/colorama/__pycache__/winterm.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/colorama/ansi.py create mode 100644 backend/venv/Lib/site-packages/colorama/ansitowin32.py create mode 100644 backend/venv/Lib/site-packages/colorama/initialise.py create mode 100644 backend/venv/Lib/site-packages/colorama/tests/__init__.py create mode 100644 backend/venv/Lib/site-packages/colorama/tests/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/colorama/tests/__pycache__/ansi_test.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/colorama/tests/__pycache__/ansitowin32_test.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/colorama/tests/__pycache__/initialise_test.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/colorama/tests/__pycache__/isatty_test.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/colorama/tests/__pycache__/utils.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/colorama/tests/__pycache__/winterm_test.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/colorama/tests/ansi_test.py create mode 100644 backend/venv/Lib/site-packages/colorama/tests/ansitowin32_test.py create mode 100644 backend/venv/Lib/site-packages/colorama/tests/initialise_test.py create mode 100644 backend/venv/Lib/site-packages/colorama/tests/isatty_test.py create mode 100644 backend/venv/Lib/site-packages/colorama/tests/utils.py create mode 100644 backend/venv/Lib/site-packages/colorama/tests/winterm_test.py create mode 100644 backend/venv/Lib/site-packages/colorama/win32.py create mode 100644 backend/venv/Lib/site-packages/colorama/winterm.py create mode 100644 backend/venv/Lib/site-packages/dotenv/__init__.py create mode 100644 backend/venv/Lib/site-packages/dotenv/__main__.py create mode 100644 backend/venv/Lib/site-packages/dotenv/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/dotenv/__pycache__/__main__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/dotenv/__pycache__/cli.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/dotenv/__pycache__/ipython.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/dotenv/__pycache__/main.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/dotenv/__pycache__/parser.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/dotenv/__pycache__/variables.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/dotenv/__pycache__/version.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/dotenv/cli.py create mode 100644 backend/venv/Lib/site-packages/dotenv/ipython.py create mode 100644 backend/venv/Lib/site-packages/dotenv/main.py create mode 100644 backend/venv/Lib/site-packages/dotenv/parser.py create mode 100644 backend/venv/Lib/site-packages/dotenv/py.typed create mode 100644 backend/venv/Lib/site-packages/dotenv/variables.py create mode 100644 backend/venv/Lib/site-packages/dotenv/version.py create mode 100644 backend/venv/Lib/site-packages/flask-3.1.2.dist-info/INSTALLER create mode 100644 backend/venv/Lib/site-packages/flask-3.1.2.dist-info/METADATA create mode 100644 backend/venv/Lib/site-packages/flask-3.1.2.dist-info/RECORD create mode 100644 backend/venv/Lib/site-packages/flask-3.1.2.dist-info/REQUESTED create mode 100644 backend/venv/Lib/site-packages/flask-3.1.2.dist-info/WHEEL create mode 100644 backend/venv/Lib/site-packages/flask-3.1.2.dist-info/entry_points.txt create mode 100644 backend/venv/Lib/site-packages/flask-3.1.2.dist-info/licenses/LICENSE.txt create mode 100644 backend/venv/Lib/site-packages/flask/__init__.py create mode 100644 backend/venv/Lib/site-packages/flask/__main__.py create mode 100644 backend/venv/Lib/site-packages/flask/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/flask/__pycache__/__main__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/flask/__pycache__/app.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/flask/__pycache__/blueprints.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/flask/__pycache__/cli.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/flask/__pycache__/config.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/flask/__pycache__/ctx.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/flask/__pycache__/debughelpers.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/flask/__pycache__/globals.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/flask/__pycache__/helpers.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/flask/__pycache__/logging.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/flask/__pycache__/sessions.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/flask/__pycache__/signals.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/flask/__pycache__/templating.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/flask/__pycache__/testing.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/flask/__pycache__/typing.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/flask/__pycache__/views.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/flask/__pycache__/wrappers.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/flask/app.py create mode 100644 backend/venv/Lib/site-packages/flask/blueprints.py create mode 100644 backend/venv/Lib/site-packages/flask/cli.py create mode 100644 backend/venv/Lib/site-packages/flask/config.py create mode 100644 backend/venv/Lib/site-packages/flask/ctx.py create mode 100644 backend/venv/Lib/site-packages/flask/debughelpers.py create mode 100644 backend/venv/Lib/site-packages/flask/globals.py create mode 100644 backend/venv/Lib/site-packages/flask/helpers.py create mode 100644 backend/venv/Lib/site-packages/flask/json/__init__.py create mode 100644 backend/venv/Lib/site-packages/flask/json/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/flask/json/__pycache__/provider.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/flask/json/__pycache__/tag.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/flask/json/provider.py create mode 100644 backend/venv/Lib/site-packages/flask/json/tag.py create mode 100644 backend/venv/Lib/site-packages/flask/logging.py create mode 100644 backend/venv/Lib/site-packages/flask/py.typed create mode 100644 backend/venv/Lib/site-packages/flask/sansio/README.md create mode 100644 backend/venv/Lib/site-packages/flask/sansio/__pycache__/app.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/flask/sansio/__pycache__/blueprints.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/flask/sansio/__pycache__/scaffold.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/flask/sansio/app.py create mode 100644 backend/venv/Lib/site-packages/flask/sansio/blueprints.py create mode 100644 backend/venv/Lib/site-packages/flask/sansio/scaffold.py create mode 100644 backend/venv/Lib/site-packages/flask/sessions.py create mode 100644 backend/venv/Lib/site-packages/flask/signals.py create mode 100644 backend/venv/Lib/site-packages/flask/templating.py create mode 100644 backend/venv/Lib/site-packages/flask/testing.py create mode 100644 backend/venv/Lib/site-packages/flask/typing.py create mode 100644 backend/venv/Lib/site-packages/flask/views.py create mode 100644 backend/venv/Lib/site-packages/flask/wrappers.py create mode 100644 backend/venv/Lib/site-packages/flask_cors-6.0.1.dist-info/INSTALLER create mode 100644 backend/venv/Lib/site-packages/flask_cors-6.0.1.dist-info/METADATA create mode 100644 backend/venv/Lib/site-packages/flask_cors-6.0.1.dist-info/RECORD create mode 100644 backend/venv/Lib/site-packages/flask_cors-6.0.1.dist-info/REQUESTED create mode 100644 backend/venv/Lib/site-packages/flask_cors-6.0.1.dist-info/WHEEL create mode 100644 backend/venv/Lib/site-packages/flask_cors-6.0.1.dist-info/top_level.txt create mode 100644 backend/venv/Lib/site-packages/flask_cors/__init__.py create mode 100644 backend/venv/Lib/site-packages/flask_cors/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/flask_cors/__pycache__/core.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/flask_cors/__pycache__/decorator.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/flask_cors/__pycache__/extension.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/flask_cors/__pycache__/version.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/flask_cors/core.py create mode 100644 backend/venv/Lib/site-packages/flask_cors/decorator.py create mode 100644 backend/venv/Lib/site-packages/flask_cors/extension.py create mode 100644 backend/venv/Lib/site-packages/flask_cors/version.py create mode 100644 backend/venv/Lib/site-packages/idna-3.10.dist-info/INSTALLER create mode 100644 backend/venv/Lib/site-packages/idna-3.10.dist-info/LICENSE.md create mode 100644 backend/venv/Lib/site-packages/idna-3.10.dist-info/METADATA create mode 100644 backend/venv/Lib/site-packages/idna-3.10.dist-info/RECORD create mode 100644 backend/venv/Lib/site-packages/idna-3.10.dist-info/WHEEL create mode 100644 backend/venv/Lib/site-packages/idna/__init__.py create mode 100644 backend/venv/Lib/site-packages/idna/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/idna/__pycache__/codec.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/idna/__pycache__/compat.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/idna/__pycache__/core.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/idna/__pycache__/idnadata.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/idna/__pycache__/intranges.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/idna/__pycache__/package_data.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/idna/__pycache__/uts46data.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/idna/codec.py create mode 100644 backend/venv/Lib/site-packages/idna/compat.py create mode 100644 backend/venv/Lib/site-packages/idna/core.py create mode 100644 backend/venv/Lib/site-packages/idna/idnadata.py create mode 100644 backend/venv/Lib/site-packages/idna/intranges.py create mode 100644 backend/venv/Lib/site-packages/idna/package_data.py create mode 100644 backend/venv/Lib/site-packages/idna/py.typed create mode 100644 backend/venv/Lib/site-packages/idna/uts46data.py create mode 100644 backend/venv/Lib/site-packages/itsdangerous-2.2.0.dist-info/INSTALLER create mode 100644 backend/venv/Lib/site-packages/itsdangerous-2.2.0.dist-info/LICENSE.txt create mode 100644 backend/venv/Lib/site-packages/itsdangerous-2.2.0.dist-info/METADATA create mode 100644 backend/venv/Lib/site-packages/itsdangerous-2.2.0.dist-info/RECORD create mode 100644 backend/venv/Lib/site-packages/itsdangerous-2.2.0.dist-info/WHEEL create mode 100644 backend/venv/Lib/site-packages/itsdangerous/__init__.py create mode 100644 backend/venv/Lib/site-packages/itsdangerous/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/itsdangerous/__pycache__/_json.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/itsdangerous/__pycache__/encoding.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/itsdangerous/__pycache__/exc.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/itsdangerous/__pycache__/serializer.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/itsdangerous/__pycache__/signer.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/itsdangerous/__pycache__/timed.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/itsdangerous/__pycache__/url_safe.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/itsdangerous/_json.py create mode 100644 backend/venv/Lib/site-packages/itsdangerous/encoding.py create mode 100644 backend/venv/Lib/site-packages/itsdangerous/exc.py create mode 100644 backend/venv/Lib/site-packages/itsdangerous/py.typed create mode 100644 backend/venv/Lib/site-packages/itsdangerous/serializer.py create mode 100644 backend/venv/Lib/site-packages/itsdangerous/signer.py create mode 100644 backend/venv/Lib/site-packages/itsdangerous/timed.py create mode 100644 backend/venv/Lib/site-packages/itsdangerous/url_safe.py create mode 100644 backend/venv/Lib/site-packages/jinja2-3.1.6.dist-info/INSTALLER create mode 100644 backend/venv/Lib/site-packages/jinja2-3.1.6.dist-info/METADATA create mode 100644 backend/venv/Lib/site-packages/jinja2-3.1.6.dist-info/RECORD create mode 100644 backend/venv/Lib/site-packages/jinja2-3.1.6.dist-info/WHEEL create mode 100644 backend/venv/Lib/site-packages/jinja2-3.1.6.dist-info/entry_points.txt create mode 100644 backend/venv/Lib/site-packages/jinja2-3.1.6.dist-info/licenses/LICENSE.txt create mode 100644 backend/venv/Lib/site-packages/jinja2/__init__.py create mode 100644 backend/venv/Lib/site-packages/jinja2/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/jinja2/__pycache__/_identifier.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/jinja2/__pycache__/async_utils.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/jinja2/__pycache__/bccache.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/jinja2/__pycache__/compiler.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/jinja2/__pycache__/constants.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/jinja2/__pycache__/debug.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/jinja2/__pycache__/defaults.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/jinja2/__pycache__/environment.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/jinja2/__pycache__/exceptions.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/jinja2/__pycache__/ext.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/jinja2/__pycache__/filters.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/jinja2/__pycache__/idtracking.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/jinja2/__pycache__/lexer.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/jinja2/__pycache__/loaders.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/jinja2/__pycache__/meta.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/jinja2/__pycache__/nativetypes.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/jinja2/__pycache__/nodes.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/jinja2/__pycache__/optimizer.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/jinja2/__pycache__/parser.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/jinja2/__pycache__/runtime.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/jinja2/__pycache__/sandbox.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/jinja2/__pycache__/tests.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/jinja2/__pycache__/utils.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/jinja2/__pycache__/visitor.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/jinja2/_identifier.py create mode 100644 backend/venv/Lib/site-packages/jinja2/async_utils.py create mode 100644 backend/venv/Lib/site-packages/jinja2/bccache.py create mode 100644 backend/venv/Lib/site-packages/jinja2/compiler.py create mode 100644 backend/venv/Lib/site-packages/jinja2/constants.py create mode 100644 backend/venv/Lib/site-packages/jinja2/debug.py create mode 100644 backend/venv/Lib/site-packages/jinja2/defaults.py create mode 100644 backend/venv/Lib/site-packages/jinja2/environment.py create mode 100644 backend/venv/Lib/site-packages/jinja2/exceptions.py create mode 100644 backend/venv/Lib/site-packages/jinja2/ext.py create mode 100644 backend/venv/Lib/site-packages/jinja2/filters.py create mode 100644 backend/venv/Lib/site-packages/jinja2/idtracking.py create mode 100644 backend/venv/Lib/site-packages/jinja2/lexer.py create mode 100644 backend/venv/Lib/site-packages/jinja2/loaders.py create mode 100644 backend/venv/Lib/site-packages/jinja2/meta.py create mode 100644 backend/venv/Lib/site-packages/jinja2/nativetypes.py create mode 100644 backend/venv/Lib/site-packages/jinja2/nodes.py create mode 100644 backend/venv/Lib/site-packages/jinja2/optimizer.py create mode 100644 backend/venv/Lib/site-packages/jinja2/parser.py create mode 100644 backend/venv/Lib/site-packages/jinja2/py.typed create mode 100644 backend/venv/Lib/site-packages/jinja2/runtime.py create mode 100644 backend/venv/Lib/site-packages/jinja2/sandbox.py create mode 100644 backend/venv/Lib/site-packages/jinja2/tests.py create mode 100644 backend/venv/Lib/site-packages/jinja2/utils.py create mode 100644 backend/venv/Lib/site-packages/jinja2/visitor.py create mode 100644 backend/venv/Lib/site-packages/markupsafe-3.0.3.dist-info/INSTALLER create mode 100644 backend/venv/Lib/site-packages/markupsafe-3.0.3.dist-info/METADATA create mode 100644 backend/venv/Lib/site-packages/markupsafe-3.0.3.dist-info/RECORD create mode 100644 backend/venv/Lib/site-packages/markupsafe-3.0.3.dist-info/WHEEL create mode 100644 backend/venv/Lib/site-packages/markupsafe-3.0.3.dist-info/licenses/LICENSE.txt create mode 100644 backend/venv/Lib/site-packages/markupsafe-3.0.3.dist-info/top_level.txt create mode 100644 backend/venv/Lib/site-packages/markupsafe/__init__.py create mode 100644 backend/venv/Lib/site-packages/markupsafe/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/markupsafe/__pycache__/_native.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/markupsafe/_native.py create mode 100644 backend/venv/Lib/site-packages/markupsafe/_speedups.c create mode 100644 backend/venv/Lib/site-packages/markupsafe/_speedups.cp312-win_amd64.pyd create mode 100644 backend/venv/Lib/site-packages/markupsafe/_speedups.pyi create mode 100644 backend/venv/Lib/site-packages/markupsafe/py.typed create mode 100644 backend/venv/Lib/site-packages/pip-24.2.dist-info/AUTHORS.txt create mode 100644 backend/venv/Lib/site-packages/pip-24.2.dist-info/INSTALLER create mode 100644 backend/venv/Lib/site-packages/pip-24.2.dist-info/LICENSE.txt create mode 100644 backend/venv/Lib/site-packages/pip-24.2.dist-info/METADATA create mode 100644 backend/venv/Lib/site-packages/pip-24.2.dist-info/RECORD create mode 100644 backend/venv/Lib/site-packages/pip-24.2.dist-info/REQUESTED create mode 100644 backend/venv/Lib/site-packages/pip-24.2.dist-info/WHEEL create mode 100644 backend/venv/Lib/site-packages/pip-24.2.dist-info/entry_points.txt create mode 100644 backend/venv/Lib/site-packages/pip-24.2.dist-info/top_level.txt create mode 100644 backend/venv/Lib/site-packages/pip/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/__main__.py create mode 100644 backend/venv/Lib/site-packages/pip/__pip-runner__.py create mode 100644 backend/venv/Lib/site-packages/pip/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/__pycache__/__main__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/__pycache__/__pip-runner__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/__pycache__/build_env.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/__pycache__/cache.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/__pycache__/configuration.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/__pycache__/exceptions.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/__pycache__/main.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/__pycache__/pyproject.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/__pycache__/self_outdated_check.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/__pycache__/wheel_builder.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/build_env.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/cache.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/cli/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/cli/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/cli/__pycache__/autocompletion.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/cli/__pycache__/base_command.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/cli/__pycache__/cmdoptions.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/cli/__pycache__/command_context.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/cli/__pycache__/index_command.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/cli/__pycache__/main.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/cli/__pycache__/main_parser.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/cli/__pycache__/parser.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/cli/__pycache__/progress_bars.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/cli/__pycache__/req_command.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/cli/__pycache__/spinners.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/cli/__pycache__/status_codes.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/cli/autocompletion.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/cli/base_command.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/cli/cmdoptions.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/cli/command_context.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/cli/index_command.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/cli/main.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/cli/main_parser.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/cli/parser.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/cli/progress_bars.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/cli/req_command.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/cli/spinners.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/cli/status_codes.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/commands/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/commands/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/commands/__pycache__/cache.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/commands/__pycache__/check.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/commands/__pycache__/completion.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/commands/__pycache__/configuration.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/commands/__pycache__/debug.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/commands/__pycache__/download.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/commands/__pycache__/freeze.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/commands/__pycache__/hash.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/commands/__pycache__/help.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/commands/__pycache__/index.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/commands/__pycache__/inspect.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/commands/__pycache__/install.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/commands/__pycache__/list.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/commands/__pycache__/search.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/commands/__pycache__/show.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/commands/__pycache__/uninstall.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/commands/__pycache__/wheel.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/commands/cache.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/commands/check.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/commands/completion.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/commands/configuration.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/commands/debug.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/commands/download.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/commands/freeze.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/commands/hash.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/commands/help.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/commands/index.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/commands/inspect.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/commands/install.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/commands/list.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/commands/search.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/commands/show.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/commands/uninstall.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/commands/wheel.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/configuration.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/distributions/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/distributions/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/distributions/__pycache__/base.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/distributions/__pycache__/installed.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/distributions/__pycache__/sdist.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/distributions/__pycache__/wheel.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/distributions/base.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/distributions/installed.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/distributions/sdist.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/distributions/wheel.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/exceptions.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/index/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/index/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/index/__pycache__/collector.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/index/__pycache__/package_finder.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/index/__pycache__/sources.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/index/collector.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/index/package_finder.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/index/sources.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/locations/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/locations/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/locations/__pycache__/_distutils.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/locations/__pycache__/_sysconfig.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/locations/__pycache__/base.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/locations/_distutils.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/locations/_sysconfig.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/locations/base.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/main.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/metadata/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/metadata/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/metadata/__pycache__/_json.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/metadata/__pycache__/base.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/metadata/__pycache__/pkg_resources.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/metadata/_json.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/metadata/base.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/metadata/importlib/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/_compat.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/_dists.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/_envs.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/metadata/importlib/_compat.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/metadata/importlib/_dists.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/metadata/importlib/_envs.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/metadata/pkg_resources.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/models/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/models/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/models/__pycache__/candidate.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/models/__pycache__/direct_url.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/models/__pycache__/format_control.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/models/__pycache__/index.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/models/__pycache__/installation_report.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/models/__pycache__/link.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/models/__pycache__/scheme.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/models/__pycache__/search_scope.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/models/__pycache__/selection_prefs.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/models/__pycache__/target_python.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/models/__pycache__/wheel.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/models/candidate.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/models/direct_url.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/models/format_control.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/models/index.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/models/installation_report.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/models/link.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/models/scheme.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/models/search_scope.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/models/selection_prefs.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/models/target_python.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/models/wheel.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/network/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/network/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/network/__pycache__/auth.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/network/__pycache__/cache.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/network/__pycache__/download.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/network/__pycache__/lazy_wheel.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/network/__pycache__/session.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/network/__pycache__/utils.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/network/__pycache__/xmlrpc.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/network/auth.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/network/cache.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/network/download.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/network/lazy_wheel.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/network/session.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/network/utils.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/network/xmlrpc.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/operations/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/operations/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/operations/__pycache__/check.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/operations/__pycache__/freeze.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/operations/__pycache__/prepare.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/operations/build/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/build_tracker.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata_editable.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata_legacy.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel_editable.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel_legacy.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/operations/build/build_tracker.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/operations/build/metadata.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/operations/build/metadata_editable.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/operations/build/metadata_legacy.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/operations/build/wheel.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/operations/build/wheel_editable.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/operations/build/wheel_legacy.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/operations/check.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/operations/freeze.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/operations/install/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/editable_legacy.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/wheel.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/operations/install/editable_legacy.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/operations/install/wheel.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/operations/prepare.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/pyproject.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/req/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/req/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/req/__pycache__/constructors.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/req/__pycache__/req_file.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/req/__pycache__/req_install.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/req/__pycache__/req_set.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/req/__pycache__/req_uninstall.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/req/constructors.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/req/req_file.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/req/req_install.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/req/req_set.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/req/req_uninstall.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/resolution/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/resolution/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/resolution/__pycache__/base.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/resolution/base.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/resolution/legacy/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/resolution/legacy/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/resolution/legacy/__pycache__/resolver.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/resolution/legacy/resolver.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/base.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/candidates.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/factory.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/provider.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/requirements.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/base.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/candidates.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/factory.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/provider.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/reporter.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/requirements.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/resolver.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/self_outdated_check.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/__pycache__/_jaraco_text.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/__pycache__/_log.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/__pycache__/appdirs.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/__pycache__/compat.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/__pycache__/compatibility_tags.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/__pycache__/datetime.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/__pycache__/deprecation.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/__pycache__/direct_url_helpers.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/__pycache__/egg_link.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/__pycache__/encoding.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/__pycache__/entrypoints.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/__pycache__/filesystem.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/__pycache__/filetypes.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/__pycache__/glibc.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/__pycache__/hashes.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/__pycache__/logging.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/__pycache__/misc.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/__pycache__/packaging.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/__pycache__/retry.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/__pycache__/setuptools_build.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/__pycache__/subprocess.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/__pycache__/temp_dir.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/__pycache__/unpacking.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/__pycache__/urls.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/__pycache__/virtualenv.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/__pycache__/wheel.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/_jaraco_text.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/_log.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/appdirs.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/compat.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/compatibility_tags.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/datetime.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/deprecation.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/direct_url_helpers.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/egg_link.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/encoding.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/entrypoints.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/filesystem.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/filetypes.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/glibc.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/hashes.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/logging.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/misc.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/packaging.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/retry.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/setuptools_build.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/subprocess.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/temp_dir.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/unpacking.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/urls.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/virtualenv.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/utils/wheel.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/vcs/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/vcs/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/vcs/__pycache__/bazaar.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/vcs/__pycache__/git.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/vcs/__pycache__/mercurial.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/vcs/__pycache__/subversion.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/vcs/__pycache__/versioncontrol.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_internal/vcs/bazaar.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/vcs/git.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/vcs/mercurial.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/vcs/subversion.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/vcs/versioncontrol.py create mode 100644 backend/venv/Lib/site-packages/pip/_internal/wheel_builder.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/__pycache__/typing_extensions.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/cachecontrol/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/_cmd.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/adapter.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/cache.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/controller.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/filewrapper.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/heuristics.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/serialize.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/cachecontrol/_cmd.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/cachecontrol/adapter.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/cachecontrol/cache.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/file_cache.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/cachecontrol/controller.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/cachecontrol/filewrapper.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/cachecontrol/heuristics.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/cachecontrol/py.typed create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/cachecontrol/serialize.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/cachecontrol/wrapper.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/certifi/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/certifi/__main__.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/__main__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/core.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/certifi/cacert.pem create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/certifi/core.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/certifi/py.typed create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distlib/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/compat.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/database.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/index.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/locators.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/manifest.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/markers.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/metadata.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/resources.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/scripts.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/util.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/version.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/wheel.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distlib/compat.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distlib/database.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distlib/index.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distlib/locators.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distlib/manifest.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distlib/markers.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distlib/metadata.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distlib/resources.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distlib/scripts.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distlib/t32.exe create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distlib/t64-arm.exe create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distlib/t64.exe create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distlib/util.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distlib/version.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distlib/w32.exe create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distlib/w64-arm.exe create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distlib/w64.exe create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distlib/wheel.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distro/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distro/__main__.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distro/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distro/__pycache__/__main__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distro/__pycache__/distro.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distro/distro.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/distro/py.typed create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/idna/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/codec.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/compat.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/core.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/idnadata.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/intranges.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/package_data.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/uts46data.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/idna/codec.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/idna/compat.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/idna/core.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/idna/idnadata.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/idna/intranges.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/idna/package_data.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/idna/py.typed create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/idna/uts46data.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/msgpack/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/exceptions.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/ext.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/fallback.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/msgpack/exceptions.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/msgpack/ext.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/msgpack/fallback.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/packaging/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_elffile.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_manylinux.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_musllinux.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_parser.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_structures.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_tokenizer.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/markers.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/metadata.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/requirements.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/specifiers.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/tags.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/utils.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/version.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/packaging/_elffile.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/packaging/_manylinux.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/packaging/_musllinux.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/packaging/_parser.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/packaging/_structures.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/packaging/_tokenizer.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/packaging/markers.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/packaging/metadata.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/packaging/py.typed create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/packaging/requirements.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/packaging/specifiers.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/packaging/tags.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/packaging/utils.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/packaging/version.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pkg_resources/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pkg_resources/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/platformdirs/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/platformdirs/__main__.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/__main__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/android.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/api.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/macos.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/unix.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/version.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/windows.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/platformdirs/android.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/platformdirs/api.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/platformdirs/macos.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/platformdirs/py.typed create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/platformdirs/unix.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/platformdirs/version.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/platformdirs/windows.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/__main__.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/__main__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/cmdline.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/console.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/filter.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/formatter.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/lexer.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/modeline.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/plugin.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/regexopt.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/scanner.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/sphinxext.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/style.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/token.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/unistring.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/util.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/cmdline.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/console.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/filter.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/filters/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/filters/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/formatter.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/_mapping.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/bbcode.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/groff.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/html.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/img.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/irc.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/latex.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/other.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/pangomarkup.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/rtf.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/svg.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal256.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/formatters/_mapping.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/formatters/bbcode.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/formatters/groff.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/formatters/html.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/formatters/img.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/formatters/irc.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/formatters/latex.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/formatters/other.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/formatters/pangomarkup.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/formatters/rtf.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/formatters/svg.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/formatters/terminal.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/formatters/terminal256.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/lexer.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/lexers/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/lexers/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/lexers/__pycache__/_mapping.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/lexers/__pycache__/python.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/lexers/_mapping.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/lexers/python.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/modeline.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/plugin.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/regexopt.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/scanner.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/sphinxext.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/style.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/styles/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/styles/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/styles/__pycache__/_mapping.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/styles/_mapping.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/token.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/unistring.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pygments/util.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pyproject_hooks/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pyproject_hooks/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pyproject_hooks/__pycache__/_compat.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pyproject_hooks/__pycache__/_impl.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_compat.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_impl.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/_in_process.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/requests/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/__version__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/_internal_utils.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/adapters.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/api.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/auth.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/certs.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/compat.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/cookies.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/exceptions.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/help.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/hooks.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/models.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/packages.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/sessions.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/status_codes.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/structures.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/utils.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/requests/__version__.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/requests/_internal_utils.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/requests/adapters.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/requests/api.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/requests/auth.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/requests/certs.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/requests/compat.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/requests/cookies.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/requests/exceptions.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/requests/help.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/requests/hooks.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/requests/models.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/requests/packages.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/requests/sessions.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/requests/status_codes.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/requests/structures.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/requests/utils.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/resolvelib/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/providers.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/reporters.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/resolvers.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/structs.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/resolvelib/compat/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/resolvelib/compat/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/resolvelib/compat/__pycache__/collections_abc.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/resolvelib/compat/collections_abc.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/resolvelib/providers.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/resolvelib/py.typed create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/resolvelib/reporters.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/resolvelib/resolvers.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/resolvelib/structs.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__main__.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/__main__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_cell_widths.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_emoji_codes.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_emoji_replace.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_export_format.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_extension.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_fileno.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_inspect.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_log_render.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_loop.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_null_file.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_palettes.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_pick.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_ratio.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_spinners.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_stack.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_timer.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_win32_console.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_windows.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_windows_renderer.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_wrap.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/abc.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/align.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/ansi.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/bar.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/box.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/cells.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/color.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/color_triplet.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/columns.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/console.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/constrain.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/containers.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/control.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/default_styles.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/diagnose.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/emoji.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/errors.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/file_proxy.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/filesize.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/highlighter.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/json.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/jupyter.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/layout.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/live.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/live_render.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/logging.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/markup.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/measure.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/padding.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/pager.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/palette.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/panel.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/pretty.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/progress.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/progress_bar.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/prompt.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/protocol.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/region.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/repr.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/rule.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/scope.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/screen.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/segment.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/spinner.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/status.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/style.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/styled.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/syntax.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/table.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/terminal_theme.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/text.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/theme.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/themes.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/traceback.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/tree.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/_cell_widths.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/_emoji_codes.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/_emoji_replace.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/_export_format.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/_extension.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/_fileno.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/_inspect.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/_log_render.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/_loop.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/_null_file.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/_palettes.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/_pick.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/_ratio.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/_spinners.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/_stack.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/_timer.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/_win32_console.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/_windows.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/_windows_renderer.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/_wrap.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/abc.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/align.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/ansi.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/bar.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/box.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/cells.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/color.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/color_triplet.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/columns.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/console.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/constrain.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/containers.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/control.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/default_styles.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/diagnose.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/emoji.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/errors.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/file_proxy.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/filesize.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/highlighter.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/json.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/jupyter.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/layout.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/live.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/live_render.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/logging.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/markup.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/measure.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/padding.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/pager.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/palette.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/panel.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/pretty.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/progress.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/progress_bar.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/prompt.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/protocol.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/py.typed create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/region.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/repr.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/rule.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/scope.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/screen.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/segment.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/spinner.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/status.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/style.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/styled.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/syntax.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/table.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/terminal_theme.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/text.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/theme.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/themes.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/traceback.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/rich/tree.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/tomli/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/_parser.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/_re.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/_types.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/tomli/_parser.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/tomli/_re.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/tomli/_types.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/tomli/py.typed create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/truststore/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_api.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_macos.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_openssl.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_ssl_constants.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_windows.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/truststore/_api.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/truststore/_macos.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/truststore/_openssl.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/truststore/_ssl_constants.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/truststore/_windows.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/truststore/py.typed create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/typing_extensions.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/_collections.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/_version.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/connection.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/connectionpool.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/exceptions.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/fields.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/filepost.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/poolmanager.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/request.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/response.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/_collections.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/_version.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/connection.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/connectionpool.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/_appengine_environ.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/appengine.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/ntlmpool.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/pyopenssl.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/securetransport.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/socks.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_appengine_environ.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/bindings.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/low_level.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/bindings.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/low_level.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/appengine.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/ntlmpool.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/securetransport.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/socks.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/exceptions.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/fields.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/filepost.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/packages/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/packages/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/packages/__pycache__/six.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/makefile.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/weakref_finalize.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/weakref_finalize.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/packages/six.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/poolmanager.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/request.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/response.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/util/__init__.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/connection.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/proxy.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/queue.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/request.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/response.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/retry.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_match_hostname.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/ssltransport.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/timeout.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/url.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/wait.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/util/connection.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/util/proxy.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/util/queue.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/util/request.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/util/response.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/util/retry.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/util/ssl_.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/util/ssl_match_hostname.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/util/ssltransport.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/util/timeout.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/util/url.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/urllib3/util/wait.py create mode 100644 backend/venv/Lib/site-packages/pip/_vendor/vendor.txt create mode 100644 backend/venv/Lib/site-packages/pip/py.typed create mode 100644 backend/venv/Lib/site-packages/python_dotenv-1.1.1.dist-info/INSTALLER create mode 100644 backend/venv/Lib/site-packages/python_dotenv-1.1.1.dist-info/METADATA create mode 100644 backend/venv/Lib/site-packages/python_dotenv-1.1.1.dist-info/RECORD create mode 100644 backend/venv/Lib/site-packages/python_dotenv-1.1.1.dist-info/REQUESTED create mode 100644 backend/venv/Lib/site-packages/python_dotenv-1.1.1.dist-info/WHEEL create mode 100644 backend/venv/Lib/site-packages/python_dotenv-1.1.1.dist-info/entry_points.txt create mode 100644 backend/venv/Lib/site-packages/python_dotenv-1.1.1.dist-info/licenses/LICENSE create mode 100644 backend/venv/Lib/site-packages/python_dotenv-1.1.1.dist-info/top_level.txt create mode 100644 backend/venv/Lib/site-packages/requests-2.32.5.dist-info/INSTALLER create mode 100644 backend/venv/Lib/site-packages/requests-2.32.5.dist-info/METADATA create mode 100644 backend/venv/Lib/site-packages/requests-2.32.5.dist-info/RECORD create mode 100644 backend/venv/Lib/site-packages/requests-2.32.5.dist-info/REQUESTED create mode 100644 backend/venv/Lib/site-packages/requests-2.32.5.dist-info/WHEEL create mode 100644 backend/venv/Lib/site-packages/requests-2.32.5.dist-info/licenses/LICENSE create mode 100644 backend/venv/Lib/site-packages/requests-2.32.5.dist-info/top_level.txt create mode 100644 backend/venv/Lib/site-packages/requests/__init__.py create mode 100644 backend/venv/Lib/site-packages/requests/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/requests/__pycache__/__version__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/requests/__pycache__/_internal_utils.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/requests/__pycache__/adapters.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/requests/__pycache__/api.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/requests/__pycache__/auth.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/requests/__pycache__/certs.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/requests/__pycache__/compat.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/requests/__pycache__/cookies.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/requests/__pycache__/exceptions.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/requests/__pycache__/help.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/requests/__pycache__/hooks.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/requests/__pycache__/models.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/requests/__pycache__/packages.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/requests/__pycache__/sessions.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/requests/__pycache__/status_codes.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/requests/__pycache__/structures.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/requests/__pycache__/utils.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/requests/__version__.py create mode 100644 backend/venv/Lib/site-packages/requests/_internal_utils.py create mode 100644 backend/venv/Lib/site-packages/requests/adapters.py create mode 100644 backend/venv/Lib/site-packages/requests/api.py create mode 100644 backend/venv/Lib/site-packages/requests/auth.py create mode 100644 backend/venv/Lib/site-packages/requests/certs.py create mode 100644 backend/venv/Lib/site-packages/requests/compat.py create mode 100644 backend/venv/Lib/site-packages/requests/cookies.py create mode 100644 backend/venv/Lib/site-packages/requests/exceptions.py create mode 100644 backend/venv/Lib/site-packages/requests/help.py create mode 100644 backend/venv/Lib/site-packages/requests/hooks.py create mode 100644 backend/venv/Lib/site-packages/requests/models.py create mode 100644 backend/venv/Lib/site-packages/requests/packages.py create mode 100644 backend/venv/Lib/site-packages/requests/sessions.py create mode 100644 backend/venv/Lib/site-packages/requests/status_codes.py create mode 100644 backend/venv/Lib/site-packages/requests/structures.py create mode 100644 backend/venv/Lib/site-packages/requests/utils.py create mode 100644 backend/venv/Lib/site-packages/urllib3-2.5.0.dist-info/INSTALLER create mode 100644 backend/venv/Lib/site-packages/urllib3-2.5.0.dist-info/METADATA create mode 100644 backend/venv/Lib/site-packages/urllib3-2.5.0.dist-info/RECORD create mode 100644 backend/venv/Lib/site-packages/urllib3-2.5.0.dist-info/WHEEL create mode 100644 backend/venv/Lib/site-packages/urllib3-2.5.0.dist-info/licenses/LICENSE.txt create mode 100644 backend/venv/Lib/site-packages/urllib3/__init__.py create mode 100644 backend/venv/Lib/site-packages/urllib3/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/urllib3/__pycache__/_base_connection.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/urllib3/__pycache__/_collections.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/urllib3/__pycache__/_request_methods.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/urllib3/__pycache__/_version.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/urllib3/__pycache__/connection.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/urllib3/__pycache__/connectionpool.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/urllib3/__pycache__/exceptions.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/urllib3/__pycache__/fields.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/urllib3/__pycache__/filepost.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/urllib3/__pycache__/poolmanager.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/urllib3/__pycache__/response.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/urllib3/_base_connection.py create mode 100644 backend/venv/Lib/site-packages/urllib3/_collections.py create mode 100644 backend/venv/Lib/site-packages/urllib3/_request_methods.py create mode 100644 backend/venv/Lib/site-packages/urllib3/_version.py create mode 100644 backend/venv/Lib/site-packages/urllib3/connection.py create mode 100644 backend/venv/Lib/site-packages/urllib3/connectionpool.py create mode 100644 backend/venv/Lib/site-packages/urllib3/contrib/__init__.py create mode 100644 backend/venv/Lib/site-packages/urllib3/contrib/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/urllib3/contrib/__pycache__/pyopenssl.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/urllib3/contrib/__pycache__/socks.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/urllib3/contrib/emscripten/__init__.py create mode 100644 backend/venv/Lib/site-packages/urllib3/contrib/emscripten/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/urllib3/contrib/emscripten/__pycache__/connection.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/urllib3/contrib/emscripten/__pycache__/fetch.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/urllib3/contrib/emscripten/__pycache__/request.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/urllib3/contrib/emscripten/__pycache__/response.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/urllib3/contrib/emscripten/connection.py create mode 100644 backend/venv/Lib/site-packages/urllib3/contrib/emscripten/emscripten_fetch_worker.js create mode 100644 backend/venv/Lib/site-packages/urllib3/contrib/emscripten/fetch.py create mode 100644 backend/venv/Lib/site-packages/urllib3/contrib/emscripten/request.py create mode 100644 backend/venv/Lib/site-packages/urllib3/contrib/emscripten/response.py create mode 100644 backend/venv/Lib/site-packages/urllib3/contrib/pyopenssl.py create mode 100644 backend/venv/Lib/site-packages/urllib3/contrib/socks.py create mode 100644 backend/venv/Lib/site-packages/urllib3/exceptions.py create mode 100644 backend/venv/Lib/site-packages/urllib3/fields.py create mode 100644 backend/venv/Lib/site-packages/urllib3/filepost.py create mode 100644 backend/venv/Lib/site-packages/urllib3/http2/__init__.py create mode 100644 backend/venv/Lib/site-packages/urllib3/http2/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/urllib3/http2/__pycache__/connection.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/urllib3/http2/__pycache__/probe.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/urllib3/http2/connection.py create mode 100644 backend/venv/Lib/site-packages/urllib3/http2/probe.py create mode 100644 backend/venv/Lib/site-packages/urllib3/poolmanager.py create mode 100644 backend/venv/Lib/site-packages/urllib3/py.typed create mode 100644 backend/venv/Lib/site-packages/urllib3/response.py create mode 100644 backend/venv/Lib/site-packages/urllib3/util/__init__.py create mode 100644 backend/venv/Lib/site-packages/urllib3/util/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/urllib3/util/__pycache__/connection.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/urllib3/util/__pycache__/proxy.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/urllib3/util/__pycache__/request.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/urllib3/util/__pycache__/response.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/urllib3/util/__pycache__/retry.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/urllib3/util/__pycache__/ssl_.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/urllib3/util/__pycache__/ssl_match_hostname.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/urllib3/util/__pycache__/ssltransport.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/urllib3/util/__pycache__/timeout.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/urllib3/util/__pycache__/url.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/urllib3/util/__pycache__/util.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/urllib3/util/__pycache__/wait.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/urllib3/util/connection.py create mode 100644 backend/venv/Lib/site-packages/urllib3/util/proxy.py create mode 100644 backend/venv/Lib/site-packages/urllib3/util/request.py create mode 100644 backend/venv/Lib/site-packages/urllib3/util/response.py create mode 100644 backend/venv/Lib/site-packages/urllib3/util/retry.py create mode 100644 backend/venv/Lib/site-packages/urllib3/util/ssl_.py create mode 100644 backend/venv/Lib/site-packages/urllib3/util/ssl_match_hostname.py create mode 100644 backend/venv/Lib/site-packages/urllib3/util/ssltransport.py create mode 100644 backend/venv/Lib/site-packages/urllib3/util/timeout.py create mode 100644 backend/venv/Lib/site-packages/urllib3/util/url.py create mode 100644 backend/venv/Lib/site-packages/urllib3/util/util.py create mode 100644 backend/venv/Lib/site-packages/urllib3/util/wait.py create mode 100644 backend/venv/Lib/site-packages/werkzeug-3.1.3.dist-info/INSTALLER create mode 100644 backend/venv/Lib/site-packages/werkzeug-3.1.3.dist-info/LICENSE.txt create mode 100644 backend/venv/Lib/site-packages/werkzeug-3.1.3.dist-info/METADATA create mode 100644 backend/venv/Lib/site-packages/werkzeug-3.1.3.dist-info/RECORD create mode 100644 backend/venv/Lib/site-packages/werkzeug-3.1.3.dist-info/WHEEL create mode 100644 backend/venv/Lib/site-packages/werkzeug/__init__.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/__pycache__/_internal.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/__pycache__/_reloader.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/__pycache__/exceptions.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/__pycache__/formparser.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/__pycache__/http.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/__pycache__/local.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/__pycache__/security.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/__pycache__/serving.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/__pycache__/test.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/__pycache__/testapp.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/__pycache__/urls.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/__pycache__/user_agent.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/__pycache__/utils.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/__pycache__/wsgi.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/_internal.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/_reloader.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/datastructures/__init__.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/datastructures/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/datastructures/__pycache__/accept.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/datastructures/__pycache__/auth.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/datastructures/__pycache__/cache_control.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/datastructures/__pycache__/csp.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/datastructures/__pycache__/etag.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/datastructures/__pycache__/file_storage.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/datastructures/__pycache__/headers.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/datastructures/__pycache__/mixins.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/datastructures/__pycache__/range.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/datastructures/__pycache__/structures.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/datastructures/accept.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/datastructures/auth.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/datastructures/cache_control.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/datastructures/csp.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/datastructures/etag.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/datastructures/file_storage.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/datastructures/headers.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/datastructures/mixins.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/datastructures/range.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/datastructures/structures.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/debug/__init__.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/debug/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/debug/__pycache__/console.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/debug/__pycache__/repr.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/debug/__pycache__/tbtools.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/debug/console.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/debug/repr.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/debug/shared/ICON_LICENSE.md create mode 100644 backend/venv/Lib/site-packages/werkzeug/debug/shared/console.png create mode 100644 backend/venv/Lib/site-packages/werkzeug/debug/shared/debugger.js create mode 100644 backend/venv/Lib/site-packages/werkzeug/debug/shared/less.png create mode 100644 backend/venv/Lib/site-packages/werkzeug/debug/shared/more.png create mode 100644 backend/venv/Lib/site-packages/werkzeug/debug/shared/style.css create mode 100644 backend/venv/Lib/site-packages/werkzeug/debug/tbtools.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/exceptions.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/formparser.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/http.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/local.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/middleware/__init__.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/middleware/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/middleware/__pycache__/dispatcher.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/middleware/__pycache__/http_proxy.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/middleware/__pycache__/lint.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/middleware/__pycache__/profiler.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/middleware/__pycache__/proxy_fix.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/middleware/__pycache__/shared_data.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/middleware/dispatcher.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/middleware/http_proxy.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/middleware/lint.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/middleware/profiler.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/middleware/proxy_fix.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/middleware/shared_data.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/py.typed create mode 100644 backend/venv/Lib/site-packages/werkzeug/routing/__init__.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/routing/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/routing/__pycache__/converters.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/routing/__pycache__/exceptions.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/routing/__pycache__/map.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/routing/__pycache__/matcher.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/routing/__pycache__/rules.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/routing/converters.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/routing/exceptions.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/routing/map.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/routing/matcher.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/routing/rules.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/sansio/__init__.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/sansio/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/sansio/__pycache__/http.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/sansio/__pycache__/multipart.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/sansio/__pycache__/request.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/sansio/__pycache__/response.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/sansio/__pycache__/utils.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/sansio/http.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/sansio/multipart.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/sansio/request.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/sansio/response.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/sansio/utils.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/security.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/serving.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/test.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/testapp.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/urls.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/user_agent.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/utils.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/wrappers/__init__.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/wrappers/__pycache__/__init__.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/wrappers/__pycache__/request.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/wrappers/__pycache__/response.cpython-312.pyc create mode 100644 backend/venv/Lib/site-packages/werkzeug/wrappers/request.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/wrappers/response.py create mode 100644 backend/venv/Lib/site-packages/werkzeug/wsgi.py create mode 100644 backend/venv/Scripts/Activate.ps1 create mode 100644 backend/venv/Scripts/activate create mode 100644 backend/venv/Scripts/activate.bat create mode 100644 backend/venv/Scripts/deactivate.bat create mode 100644 backend/venv/Scripts/dotenv.exe create mode 100644 backend/venv/Scripts/flask.exe create mode 100644 backend/venv/Scripts/normalizer.exe create mode 100644 backend/venv/Scripts/pip.exe create mode 100644 backend/venv/Scripts/pip3.12.exe create mode 100644 backend/venv/Scripts/pip3.exe create mode 100644 backend/venv/Scripts/python.exe create mode 100644 backend/venv/Scripts/pythonw.exe create mode 100644 backend/venv/pyvenv.cfg diff --git a/backend/__pycache__/app.cpython-312.pyc b/backend/__pycache__/app.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b271bd28188022974bc365a30d92c5fb6c20bacc GIT binary patch literal 2422 zcmZ`5ZD?E9_1^a_$@*~oCBic0aarCBHay z$pPJa?m72--gC~=AN_tW0tkHf_xV{3p}+Ej3(_vK^9dlU$Up|pp*&9DypRy`VnW26 zCgh~NoRC|%m{SspfCwh)ZQPblXmFN^=APl6l<*KO+vA$q+YQ-JGWd>qTWHe^?LBmR zm!0qt)$l9~BSgDFI;F1fm`SgkpPqSR<>8J2JAMv%P+}QVcBv(CYA%oJwTV3FZr|fxRL|v}V zYr^|I65OtMjP4tfOU3B@D-v=*LmSFy3EKiRN{{oXNy>_QyQ~}j0nRCExIc=2+4pZ8bgvo?b zi<%E%P(}lk&j2RrG-ER{LmZ~<&L?nk;@ri_OE0I+PMu3#ntqLisBYRMHD}Qj&teID z;$bq`h7^E$NChbvls7&TbELq$WQivUQe(5wbbIWLyCf#s4vqRK{|qo0Mj~CNJnfX1 zBlp5Cf*gSd(H)&0;Y5iik9m05DV_}`w{pWUvHA2E*n{uSz7kJfvLW-y6UR@SSV*2P zkTGh$Ly}{}UT~~pa{Bzt)N9E_LKaRXsRa?7O3v!(1qdJsaf}p~Spc$;f_a;2r;VNg z6MQV#%aFJ#dZ?gK-_`P!@>cLrJ$Pu{duwbn_*`|esUZK!>i7c%X`zPZ{~*3Lzn0kO z9Ik7_HMyywKvyFaX>|5Ax_cjZs~5RDSh~nzY^7RZ|+>;nm4&lWRX+pZ!yJv^KUK zK5$dJu5BEC?&A}i;TN{TqxJCUr!$-3v!4&v!{fDc+a3F^zJBHPM&y~B;p^e`q0Pv# zMqmHx(zT^^?`Ge#je|pt_)EVZ{%rX37r&am8=umoh=h(wuNJ-<+(AS5K-#Yb8Pk62O*FS6Y9(bTiVebx-LcS)F zJihO~RZ;&m{`bRusH1z!cd+g|xaEu0eX(zmAjkd|>|Iko>{`F@yWWky;mu(5*7F;| zk$c+6f0{C|zqgOW6MXja>9LdO568n}vCtRVj{yH7CiC^=Gvm*TUv~D5kBDCmV~&r= zure)`%Ijt!mAYuwpuV6pWrNI?GE6E$dq@3Dp5tF>%0Ec00&cg3w?$2*EoxIf;ph-7 zTp6#vREmjEDir=1Kmk*$1g*wvgo(6N_z3L)is*}+ppE7&qm&~r(Q!EP|0i}HmZpd? z{+ELAu{w(W1@-?K1)*xxj@slet*Qtpma8-GdA2)GR|DHvx*T~oQj4$4Ym3#$CLVeq vjNsUgh=k!L$C|SkNgcJ7uf<41QZG-uJMqEMwTsn>d(vQ2MACjb1{VJZWXe$l literal 0 HcmV?d00001 diff --git a/backend/app.py b/backend/app.py new file mode 100644 index 0000000..9186cfd --- /dev/null +++ b/backend/app.py @@ -0,0 +1,66 @@ +# backend/app.py + +from flask import Flask, jsonify, request +from flask_cors import CORS +import requests + +# Initialize the Flask App +app = Flask(__name__) + +# Apply CORS to your app to allow frontend requests +CORS(app) + +GITHUB_API_URL = "https://api.github.com/search/issues" + +@app.route("/api/gfi", methods=["GET"]) +def get_gfi_issues(): + # Get the 'language' parameter from the request URL (e.g., /api/gfi?language=Python) + language = request.args.get("language", None) + + # Base query to find open "good first issues" + query = "label:\"good first issue\" state:open" + + # If a language is specified, add it to the query + if language: + query += f" language:{language}" + + # Parameters for the GitHub API request + params = { + "q": query, + "sort": "updated", + "order": "desc", + "per_page": 20 # Fetch 20 issues per request + } + + headers = {"Accept": "application/vnd.github+json"} + + try: + response = requests.get(GITHUB_API_URL, headers=headers, params=params) + response.raise_for_status() # Raise an exception for bad status codes (4xx or 5xx) + data = response.json() + + issues = [] + for item in data.get("items", []): + # Extract repository name from its URL + repo_name = item.get("repository_url", "").split("/")[-1] + + issues.append({ + "title": item.get("title"), + "url": item.get("html_url"), + "repository": repo_name, + "labels": [label.get("name") for label in item.get("labels", [])] + }) + + return jsonify({ + "language_filter": language or "any", + "count": len(issues), + "issues": issues + }) + + except requests.exceptions.RequestException as e: + # Handle API request errors gracefully + return jsonify({"error": str(e)}), 500 + +# This part allows you to run the app directly with 'python app.py' +if __name__ == "__main__": + app.run(debug=True, port=5000) # Runs on http://localhost:5000 \ No newline at end of file diff --git a/backend/package-lock.json b/backend/package-lock.json new file mode 100644 index 0000000..e1899d2 --- /dev/null +++ b/backend/package-lock.json @@ -0,0 +1,13 @@ +{ + "name": "backend", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "backend", + "version": "1.0.0", + "license": "ISC" + } + } +} diff --git a/backend/package.json b/backend/package.json new file mode 100644 index 0000000..d1ce950 --- /dev/null +++ b/backend/package.json @@ -0,0 +1,12 @@ +{ + "name": "backend", + "version": "1.0.0", + "description": "", + "license": "ISC", + "author": "", + "type": "commonjs", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + } +} diff --git a/backend/requirements.txt b/backend/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..31182e09c9024ab45080c0f476b55db5003c4e41 GIT binary patch literal 536 zcmYk3J5R$v5QL{j;-@6S4n$DUQXo-LP+uMjDpjgQ|9fIQ0Uuq-9!nTjDS}mN zL(&vT?$1-#%+P}+(C5hBYCI~G;W4GWCx4?CnB_l}Dd7Y4j(npIdgNT8wcfxM%)C5 +Requires-Python: >=3.9 +Description-Content-Type: text/markdown +Classifier: Development Status :: 5 - Production/Stable +Classifier: License :: OSI Approved :: MIT License +Classifier: Programming Language :: Python +Classifier: Typing :: Typed +Project-URL: Chat, https://discord.gg/pallets +Project-URL: Documentation, https://blinker.readthedocs.io +Project-URL: Source, https://github.com/pallets-eco/blinker/ + +# Blinker + +Blinker provides a fast dispatching system that allows any number of +interested parties to subscribe to events, or "signals". + + +## Pallets Community Ecosystem + +> [!IMPORTANT]\ +> This project is part of the Pallets Community Ecosystem. Pallets is the open +> source organization that maintains Flask; Pallets-Eco enables community +> maintenance of related projects. If you are interested in helping maintain +> this project, please reach out on [the Pallets Discord server][discord]. +> +> [discord]: https://discord.gg/pallets + + +## Example + +Signal receivers can subscribe to specific senders or receive signals +sent by any sender. + +```pycon +>>> from blinker import signal +>>> started = signal('round-started') +>>> def each(round): +... print(f"Round {round}") +... +>>> started.connect(each) + +>>> def round_two(round): +... print("This is round two.") +... +>>> started.connect(round_two, sender=2) + +>>> for round in range(1, 4): +... started.send(round) +... +Round 1! +Round 2! +This is round two. +Round 3! +``` + diff --git a/backend/venv/Lib/site-packages/blinker-1.9.0.dist-info/RECORD b/backend/venv/Lib/site-packages/blinker-1.9.0.dist-info/RECORD new file mode 100644 index 0000000..d4f985b --- /dev/null +++ b/backend/venv/Lib/site-packages/blinker-1.9.0.dist-info/RECORD @@ -0,0 +1,12 @@ +blinker-1.9.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +blinker-1.9.0.dist-info/LICENSE.txt,sha256=nrc6HzhZekqhcCXSrhvjg5Ykx5XphdTw6Xac4p-spGc,1054 +blinker-1.9.0.dist-info/METADATA,sha256=uIRiM8wjjbHkCtbCyTvctU37IAZk0kEe5kxAld1dvzA,1633 +blinker-1.9.0.dist-info/RECORD,, +blinker-1.9.0.dist-info/WHEEL,sha256=CpUCUxeHQbRN5UGRQHYRJorO5Af-Qy_fHMctcQ8DSGI,82 +blinker/__init__.py,sha256=I2EdZqpy4LyjX17Hn1yzJGWCjeLaVaPzsMgHkLfj_cQ,317 +blinker/__pycache__/__init__.cpython-312.pyc,, +blinker/__pycache__/_utilities.cpython-312.pyc,, +blinker/__pycache__/base.cpython-312.pyc,, +blinker/_utilities.py,sha256=0J7eeXXTUx0Ivf8asfpx0ycVkp0Eqfqnj117x2mYX9E,1675 +blinker/base.py,sha256=QpDuvXXcwJF49lUBcH5BiST46Rz9wSG7VW_p7N_027M,19132 +blinker/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 diff --git a/backend/venv/Lib/site-packages/blinker-1.9.0.dist-info/WHEEL b/backend/venv/Lib/site-packages/blinker-1.9.0.dist-info/WHEEL new file mode 100644 index 0000000..e3c6fee --- /dev/null +++ b/backend/venv/Lib/site-packages/blinker-1.9.0.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: flit 3.10.1 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/backend/venv/Lib/site-packages/blinker/__init__.py b/backend/venv/Lib/site-packages/blinker/__init__.py new file mode 100644 index 0000000..1772fa4 --- /dev/null +++ b/backend/venv/Lib/site-packages/blinker/__init__.py @@ -0,0 +1,17 @@ +from __future__ import annotations + +from .base import ANY +from .base import default_namespace +from .base import NamedSignal +from .base import Namespace +from .base import Signal +from .base import signal + +__all__ = [ + "ANY", + "default_namespace", + "NamedSignal", + "Namespace", + "Signal", + "signal", +] diff --git a/backend/venv/Lib/site-packages/blinker/__pycache__/__init__.cpython-312.pyc b/backend/venv/Lib/site-packages/blinker/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a330a86a38f7ae7e328de79904fcc594d52faa20 GIT binary patch literal 510 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 Q~2xOgc3R!jDNdTniX$R+b2T6XQU_VO3K> zE{cth-~k3@jigjv0?Q}b#Eg#-Q88k(pqbQ0M3_uTiBu8-gnA^Olj8|_D4|N}6g_8% zxOim~I%hU<-2!HE9V_Dy#*zTFBr%wCfH?+vL@WZ0+3+!DJu{@owD=IQuyo3*-Yuuo zTDL{VHdYU^RRa@)FdLCFW1z-ZM#rSFX~CRGv4kooGh-GgS`nfqDV1bptl2_Ozz+C) z>5kRE2RGPkA$cJ;u$N4aXf>cDZ5`ceapRmot4A`o<*=0?4(gkX)T__Ye$&V%r(T z9$E+Y7?{~;c(3X`H%GAT|9QTCEzk*0FCAO)3l+f?uTWZXsdB~VDGjUygqF5x&!vi6dk=mT{;$m+ zH{aO%%(Q30-*9X9qaUV!{PKT(`Nr;k6bLRodT`ov)8EL}>O{=YngCxAXf~MK{kQ0v zQ|?ZR<~(2UOuEw6>SP4Xm$o1z%WO$KY02pe-buIC;aC%_@0n88UfyleW42-H#VE&Y ziM(RMq=$63WRS4v?(gv~kYA6UCcUJip9vOuW3?_4rV(-%T$7%=*7ce_M_uRah}!;1 zFQ8QyfWqTBQR^rb9JAs=IU>-4Ytn-4n3W>%CcQK(L_24QtP8Glg7zTZ5Oo$@#b!`z zEu}dqR(eB0bv#ajrYBvKZfIr(CSVrCr31atxM4T** zrJ!h$BABq0%sgl^$w}!v8iDi}mtcBnvUFA*KcCVdBu%xHtKZbRF(A&Gx+N&#QflZ7 zv||afx?7Rca`zz2s=-M9WS);>n51n$0Oz%Dj?$rl6q^Bznol{j?1*%97|^K|sKA(x zJb>m@V@zlg;@)V1L_Cd<_dFsUvgD>TDpR*i<=3I@u<1@oqp(loW6&RXT^*~=pwfI7 zX!Lg3bbM5W6ebXK8S_S*97v#%{HBF;^p;it;8IFAQ|KZ3F^MPg%OnyOKmtn2jj3P( zkH#HJ7E~OjUd7XdOCz#21U(x=gfMbsGt^iblx+74<~giv00V}^p#w># z!QF+~fL5HsO7zJIUBz1DflFa{+WEMyO6Y>Q7ETqwrYRF7SL`GZfMen`;+Y-poZp

_Ka#5^h*W+D3ZZM33S8 z3PvlXCtz|uu4ySP2MJ4VifEMeiA*9m5z6c_b@;ewZYPji=(d&MmYY3?TY~IWvJ{cj zNmkM-ngYDUSb>R3Lw+02Cs9s+0$K{J8%d~Zo;`h|cFT16Qghpn+;5J4ukX+6KCJzZ zEz_mHC=cH1+_e;{pKV)g+?#FOd;RQ<#>1;_*8`Q)y_frE`ez^dB(Mc?|AF1+b2hML z*&nzZoC(gBX8o;;{`RcDeeR_N|L!G!VA0=@^*78ufUHG-XV%|&?ZAS6?{az7+cnwp zrn!deZHv2lv-rQUcg5qaSa)m3gG=GY+1|ybz1gO{*W)*u4x;g$)mJ==q1J4ub?!hm zv<+HDK$_e0-Xrfmk}cnH{lwzlW7)mO7WY2)$=>HyTqPB?OQG;$XiGM*pT4-uF>>#Vu5AyDhk?s#iinsD3&){o-`+i`(mk@P=OtV#T_jg-`^)|L1myWw|SA zmqX#J!8d|){%h?Ep`A;ibt@&vy`wi{LjQ8t*4|d(zdY8`yHoh9*3#aH`>(c%bl1PPz1I~XZOift!AjJ|16mT;|OxZf_HCuVio;LplDwS z6w*+B#{%UM?r0t`r?iR9`RqS>E-ptNPNYE7`lAu6 z*t@8%lcN5`l&};CT|PE*Y_@v#xw#VyfzG9xb<;BAbWDs>?qIzw|UZ*N#>fD(UezVn8S_|J64paX$_TKJmIw|C@t~=xrXFU<&?P?_cwC0fL{#bM)na4eemuw=Ee-a5!^2|4fCw_sj zU7WBLx6`9H?%D*Bcjn|1?8JY%4{8O;kd^J+l8H$DDa*F8y}bo$Q+$}wr9sHt?o4+{ znPfViU~ksYG)UJr_0|$6mWW*^;1Lux31eU5MD;R%;6%V!HTLvl6x0b7_;Lk=h7IJO zqcv*fYt*!Hy7%?3eKGqu{rrPYKEYT0o5b&U>V(Vqy;>@{=iHk_YhyjUU8^{1|^+5_0 zIAtt&rmKZ3(#+icQiqK6ER*FBFp0QMyCN2(!NIL&Kf2H(lK9d&IgwF2NLFRw$8d@Z zG9=*Y!A^-;30@t6arnT@eGFr}!`hp5 zZcf5^BU_D0nhX~K?OZ@I#?&#c2(tCCo;fS0{eO7`rW7_wY+7S`P-N#rLaIZVkr8rV zU_sK$a#ttlK)Up**0fK-^LwEzdW)z*pBQXz#6pW=tq&^UU`l3wJ)rFdw1m-J~ z?@%J6(rnmT0u_$SG&bi_jzu(vau$m2SHyWRv4?nxyvhU3c*S>k9W#9F4*_I<8)#A3;a0H^HWy>{Rw&eiCOUr@9 zh6DGICMy*}<5BU8<%R=y^fq+u)kDF$P@z7(wkE^RFy-7SQ`aW)JLi#U75%=N& zBo|TpZuX5Xj?>mR*+d1G9iBjzuO^PWCdIVREQA0C)J$992(~Y(IJ9%HqOei$5yW24 zX%!wJZf!#4hJFY$1kpaE&nF$a6VurWY*gl9hZ1Aqb)ow{Z-?`4>LgdK<-~b;98PE( z7}x&Ee8A430*e8$SBSd;=Fs+QFU4Y!I*h1;tpUYt(VX<4^+Bbk~wQE$-Unm0RvC3-g?K&J}} zq44FGzy0!3P5p9t@bY6bkG;L`lk(Q3nmTOB{n7Cm=z8^^1#7RI`_3zKZSQS=cl&&B z=e&O>cf>l;+H%DHhkK}AL=tIeBmA-v`+^H*x^Tv0zOjE1CDK;>jZH8_M8(TYviSE2 zu&fL2eN%PlL5*40{+;yL<1uT)VR3TO_kEGv-IoR@y+%s)2;(AC z5nb|8EZp;P6*gC%Aw;+f)0`78qaxe!P-t_47=Yv!=C7&gv^k}3+%-be;X46Cu)q<8 zbKZjfI9=DUMiHWTHVzvIBGxKjK*@Y;7FYP)QgMGr87E>EN6?DJVU(QnAj)(+=N?hh zxw5!!MwjMFh}R)FBj=`DIU)kg0N^}Up+xOk4r%RX1!?T`uf^P=1B?Svg6%ibtGFIxlz4iy62Y&2YhO&ZvEAl-*|bkt|MF5aqWQ{ zb^E4|EC=i6gDnUr_$=5kyY&Z8y!X_*Pb~y@{H$T)TaA#|H4RrD#pe8CxGfuQn>+dE z?F-=pOW~&F+NSRYmTQ~8Tlsm5(A4txEXv{4o^?HSV$5PC7!NTaJd3M$kbq2frSZ!z zNYoNLKoG2;+~G;I?6wPTN3P{XWTZ|yPr)_mnRMF(#)906go1*7?E|3}2^lOF3aGW* zrEIa_Ko;VL05@X}XrGGyVeiS0CGNG52u=wT0pN}p)({9hq>@w1plTM>L(U7GZ!>X; z_D={zV-9pW*5L4TS^D)F?U#%GZpqP6);G4n;*hHm=`f;@_>rD22jyFoP9m1oB;}h! zb-2zo3bBCXWcn*f&i)QR7pY9RG73F`Y>l>KSz%7PHgee3m#21OwqC(T6KZvY#@M;tdoxNATKoeB6NYA)paIcn&&&H%k3P;hp z7B8WewS6cC7S0fDBhoqdSZa(1iusuTT+fvdu0SDXNN4V!Gycxly>BRkLoR8)vu`0A z;j6WE?hqFj3EOBd9Q*g>;kSLCls7L0YZil2HYhCy+p-vG4fk)PAi^Q-P5>l)IML)6FCvjT9 zIW~%Xf-cC;QKfreHp4p)_b5o49Z<01`k-CdRE84wHW$7;c+uh}G0dTL5xD?K#nn?t zd=D{Nb}V@@GBNcty>7-;3^ivQMxIGJgeWGecyexiT+dY?mLDOKaw0wfHmx!4L^y=a z+T-});-453->fy`JxYwY#EFO@_Va@eO&MSZei-GyPgp}N4jZ_)eL}cyv8F9s)3#94 z&UlWL4M}tBe>8kEL`)^Tg{>zrmAW#q$xvNzf@=6=EYf2*Q%*)A5ddP?^p1kiF47q`=iyK_{- zA|TDLvxsETT~7+HiahwP00A%FKLSGZm=mlU)+R?u3$ZXm=3yi*r2bh5`4<=fAtVsZ z9E{_)Sggv7+ve9I)g$CCxb9LfgpgUt) z#M>4Ft=Ry=Nv|mjf!)h3o8Ecl%~uv%c4b?@!#*7PY0IH2<%}3MW|6wi=lnl z(7x;AH$#U$cMH;CF^?>&on*nufKh=qMB~CK3;HoaFPKU}!^kItF62zC|B`|I8ybg% zQXm4t|Ax2wJ_)wY`&;LOt$*k7lpYrIr~;*}i`I@Y;2$D!H}6$(**EM04j`)Qg6Pzh z&lJ&*O=f7WJnA(H!YODM7hELuHStpEq*zQtpja&vsow_Lb%j)4E&Tf(aA?9D|8fBMf8|F zJj~T?1oe{2Z1u>|OUJOkfv_+3C8?$|SX?KPY{fZD1mvZ8Sah09B-)6k;0v6!PT24YQEg0)YmpAy<8Xp}fpok( zMQ0n(>oJC?%+=~>QIg>rH3A68>WTs1*gIN~}yy@t2M z;B7Qfbe;kSH>_!})g*^mww(_KyWeq5O2uLstcwv|h_-Od!e|Z+Sb&@hOwld6JW2=4 zF$r{fW;~T)2nxieQ4yZd=@E`f6zP<=*e1Q2{lJN$3_r}zrVCz6B1DBj#X7RZ=Tl4Z zjA(oq2XKK_R_AcYg}J+d#;4^mK4Y>p6bCk|ph;R%^w2g!`(fKL$IM2sz?_F7UUFWX zA0O43C^9s0`u4*Z@e;gK5M`j9Lg{>E9A`X?$&We~+2-6uUj8X@?k4~VjJp#NSmbHB z7GCV=&USR)sC#JoiCY^t&yBn{`tInTq<*?_-y0QIyjRZU>NYHe*I#|=ji=_kbLpGm zuFt(f>wd_d`iHrO?PTy|!Z8NFfW+Mxd@*5fGHn(Xd!GtIUY#Op!9Ck4;x_s6IwT4v z_V?Nz4&o6eN>SvGeP(%WTq~{oCQM7tOG~3UyzPVvYoh1^YCtnu*jah%=qF>7Tr3HU04!vBioT*&&H)Z`z3;t$$#@U!f|Awr8!-BuXIux_$ zZ^`;wZu&QJMZ(4P1&V{_W~7H5&%ILyho3YF$p&Sb^lGkA__=!{KpEuYxZ`C?2R|(2 z0bV9}VJgre_Tf|!mC{mlgV`@=V{{{U6V(na{$$?^T~gl*DBg}&cWNE4916Yz7D2eP zAr^T;Mfc=%N;^p%?PA^K_ZQ%bVg1%n6rLE?+W_mWIjn~}PN(y1Lg@}2912_w{b0YhR6vJI)-Q6mqMHPgJJfoH7O>*=5!lo}O> z=F6f{2#ZXD(t&97TNydQ-)MA*i=X;)Bg~MWp$|r*j?W9>oE|Yac36-53ft&$H{Bkh z8~Mq!N9gt#-N=ckJw>;#(XEGWG>MjaM~!{$UtTsfE&Y%{^>@p68#l$ znm-Uece%a(l`^5ca;j&^^XPKx=BcA_tKaZ!UU7Nxrc&^&`?bsOJt(fakz8R(?DbJ@ zwYSI2rR43cA@3n^rA^qg|DzMPg&p4d+lpB4ZCKeO_`=Hvdsf`*yzNW%5&rw&BkXs% zwEfp!p+D{%aO_0i&S|T%w zm^EPf^O=f-XmWgPhlktZ<0;r>C&f{vW7%YiP_mnS@~C@|`k~`1Ix0eYNz+2q*pNyl z1BFQ%#)PrCMh)}x=d24%OE;Tk;h6?#ddom^{mZC*pI>Oo+v9;!!xbBv=kLLBX!~+z z5ZwPd=+FMh1C$uVU)Z1RFx_nKoLA34QPhZda~|rQq3>z0AcqOsTxpbl11cId^}Q)h zl2mCT+>c7eYDLVCVl0s&(16$QEZp)}%#@HXzh=R|0glwh=4sFCrE4`cLL3Z=pJyl- z5O&0AK&F0mK_r*EA~p(d;fw>!a|7uB!MfgZDegb^0HHknzxqd96RwA(ocJhw4KJe% zaY0QT({QJO8Xkz8hdz;{O(938`IRJNq!;l}I8t8yuW6*)@R~*%49}d;g8u|JPJ6Ih zctxLeUFo>8e)jNe`knDN$7e^c?VJy8oA+F54*6j)?>|H? z9O&oh<$1cjNH@l(X&E%?Awoj=O2yPfA{vEvWeU0MYcdD*1OHIAU|Z+3ofg1&C?Fv`&{;TzUloVa6z?-$at zfu-E6rI%({58*w1?jS~9c4lbWyX}Y|($sHd;u;+ddsZDIKfJ=+@URofi$H*w0Z33# z){O1uncQ>W@I2fH!?10$yYq)U4r5oqn$x1aZ+O%!A~w*OJC*)^_E;sNoUf#_JTiAVyJtGiWdm_8Oo#EFR3$SNL&OGHylQSm@a}yFS^0Aa210u=_##l_8o1zt{M~ID0)d+nezM7) zE$ww=fzcLB$s5QmoQ=zrN4Hf1MM~90;Zx7oI4sJ~RT(?NOsiuQr_r=_Y$p9~I0JNq zey0)T;&YGu6BRfRtViUb7(UW~n;6rg^wx*(|B-<&rnP738OKxE2Q8>H`<7C!42};v z#F>Z>G5s!A%A8v;s&u9e=1SnR8iOB>$L5zs@fFDg4q~V}|BeJLrdCd{OX$N7&&l}g zgSkwOhZ2DB#%>Hlr8=>V>LHbl^UiMT> z9eVBP?;V|v%~rkB_-5l=&$X&QTlfCDxhJy?+ZQ}Lro>mzEk#Q*=>Q+ wpZf)=>> Symbol('foo') is Symbol('foo') + True + >>> Symbol('foo') + foo + """ + + symbols: t.ClassVar[dict[str, Symbol]] = {} + + def __new__(cls, name: str) -> Symbol: + if name in cls.symbols: + return cls.symbols[name] + + obj = super().__new__(cls) + cls.symbols[name] = obj + return obj + + def __init__(self, name: str) -> None: + self.name = name + + def __repr__(self) -> str: + return self.name + + def __getnewargs__(self) -> tuple[t.Any, ...]: + return (self.name,) + + +def make_id(obj: object) -> c.Hashable: + """Get a stable identifier for a receiver or sender, to be used as a dict + key or in a set. + """ + if inspect.ismethod(obj): + # The id of a bound method is not stable, but the id of the unbound + # function and instance are. + return id(obj.__func__), id(obj.__self__) + + if isinstance(obj, (str, int)): + # Instances with the same value always compare equal and have the same + # hash, even if the id may change. + return obj + + # Assume other types are not hashable but will always be the same instance. + return id(obj) + + +def make_ref(obj: T, callback: c.Callable[[ref[T]], None] | None = None) -> ref[T]: + if inspect.ismethod(obj): + return WeakMethod(obj, callback) # type: ignore[arg-type, return-value] + + return ref(obj, callback) diff --git a/backend/venv/Lib/site-packages/blinker/base.py b/backend/venv/Lib/site-packages/blinker/base.py new file mode 100644 index 0000000..d051b94 --- /dev/null +++ b/backend/venv/Lib/site-packages/blinker/base.py @@ -0,0 +1,512 @@ +from __future__ import annotations + +import collections.abc as c +import sys +import typing as t +import weakref +from collections import defaultdict +from contextlib import contextmanager +from functools import cached_property +from inspect import iscoroutinefunction + +from ._utilities import make_id +from ._utilities import make_ref +from ._utilities import Symbol + +F = t.TypeVar("F", bound=c.Callable[..., t.Any]) + +ANY = Symbol("ANY") +"""Symbol for "any sender".""" + +ANY_ID = 0 + + +class Signal: + """A notification emitter. + + :param doc: The docstring for the signal. + """ + + ANY = ANY + """An alias for the :data:`~blinker.ANY` sender symbol.""" + + set_class: type[set[t.Any]] = set + """The set class to use for tracking connected receivers and senders. + Python's ``set`` is unordered. If receivers must be dispatched in the order + they were connected, an ordered set implementation can be used. + + .. versionadded:: 1.7 + """ + + @cached_property + def receiver_connected(self) -> Signal: + """Emitted at the end of each :meth:`connect` call. + + The signal sender is the signal instance, and the :meth:`connect` + arguments are passed through: ``receiver``, ``sender``, and ``weak``. + + .. versionadded:: 1.2 + """ + return Signal(doc="Emitted after a receiver connects.") + + @cached_property + def receiver_disconnected(self) -> Signal: + """Emitted at the end of each :meth:`disconnect` call. + + The sender is the signal instance, and the :meth:`disconnect` arguments + are passed through: ``receiver`` and ``sender``. + + This signal is emitted **only** when :meth:`disconnect` is called + explicitly. This signal cannot be emitted by an automatic disconnect + when a weakly referenced receiver or sender goes out of scope, as the + instance is no longer be available to be used as the sender for this + signal. + + An alternative approach is available by subscribing to + :attr:`receiver_connected` and setting up a custom weakref cleanup + callback on weak receivers and senders. + + .. versionadded:: 1.2 + """ + return Signal(doc="Emitted after a receiver disconnects.") + + def __init__(self, doc: str | None = None) -> None: + if doc: + self.__doc__ = doc + + self.receivers: dict[ + t.Any, weakref.ref[c.Callable[..., t.Any]] | c.Callable[..., t.Any] + ] = {} + """The map of connected receivers. Useful to quickly check if any + receivers are connected to the signal: ``if s.receivers:``. The + structure and data is not part of the public API, but checking its + boolean value is. + """ + + self.is_muted: bool = False + self._by_receiver: dict[t.Any, set[t.Any]] = defaultdict(self.set_class) + self._by_sender: dict[t.Any, set[t.Any]] = defaultdict(self.set_class) + self._weak_senders: dict[t.Any, weakref.ref[t.Any]] = {} + + def connect(self, receiver: F, sender: t.Any = ANY, weak: bool = True) -> F: + """Connect ``receiver`` to be called when the signal is sent by + ``sender``. + + :param receiver: The callable to call when :meth:`send` is called with + the given ``sender``, passing ``sender`` as a positional argument + along with any extra keyword arguments. + :param sender: Any object or :data:`ANY`. ``receiver`` will only be + called when :meth:`send` is called with this sender. If ``ANY``, the + receiver will be called for any sender. A receiver may be connected + to multiple senders by calling :meth:`connect` multiple times. + :param weak: Track the receiver with a :mod:`weakref`. The receiver will + be automatically disconnected when it is garbage collected. When + connecting a receiver defined within a function, set to ``False``, + otherwise it will be disconnected when the function scope ends. + """ + receiver_id = make_id(receiver) + sender_id = ANY_ID if sender is ANY else make_id(sender) + + if weak: + self.receivers[receiver_id] = make_ref( + receiver, self._make_cleanup_receiver(receiver_id) + ) + else: + self.receivers[receiver_id] = receiver + + self._by_sender[sender_id].add(receiver_id) + self._by_receiver[receiver_id].add(sender_id) + + if sender is not ANY and sender_id not in self._weak_senders: + # store a cleanup for weakref-able senders + try: + self._weak_senders[sender_id] = make_ref( + sender, self._make_cleanup_sender(sender_id) + ) + except TypeError: + pass + + if "receiver_connected" in self.__dict__ and self.receiver_connected.receivers: + try: + self.receiver_connected.send( + self, receiver=receiver, sender=sender, weak=weak + ) + except TypeError: + # TODO no explanation or test for this + self.disconnect(receiver, sender) + raise + + return receiver + + def connect_via(self, sender: t.Any, weak: bool = False) -> c.Callable[[F], F]: + """Connect the decorated function to be called when the signal is sent + by ``sender``. + + The decorated function will be called when :meth:`send` is called with + the given ``sender``, passing ``sender`` as a positional argument along + with any extra keyword arguments. + + :param sender: Any object or :data:`ANY`. ``receiver`` will only be + called when :meth:`send` is called with this sender. If ``ANY``, the + receiver will be called for any sender. A receiver may be connected + to multiple senders by calling :meth:`connect` multiple times. + :param weak: Track the receiver with a :mod:`weakref`. The receiver will + be automatically disconnected when it is garbage collected. When + connecting a receiver defined within a function, set to ``False``, + otherwise it will be disconnected when the function scope ends.= + + .. versionadded:: 1.1 + """ + + def decorator(fn: F) -> F: + self.connect(fn, sender, weak) + return fn + + return decorator + + @contextmanager + def connected_to( + self, receiver: c.Callable[..., t.Any], sender: t.Any = ANY + ) -> c.Generator[None, None, None]: + """A context manager that temporarily connects ``receiver`` to the + signal while a ``with`` block executes. When the block exits, the + receiver is disconnected. Useful for tests. + + :param receiver: The callable to call when :meth:`send` is called with + the given ``sender``, passing ``sender`` as a positional argument + along with any extra keyword arguments. + :param sender: Any object or :data:`ANY`. ``receiver`` will only be + called when :meth:`send` is called with this sender. If ``ANY``, the + receiver will be called for any sender. + + .. versionadded:: 1.1 + """ + self.connect(receiver, sender=sender, weak=False) + + try: + yield None + finally: + self.disconnect(receiver) + + @contextmanager + def muted(self) -> c.Generator[None, None, None]: + """A context manager that temporarily disables the signal. No receivers + will be called if the signal is sent, until the ``with`` block exits. + Useful for tests. + """ + self.is_muted = True + + try: + yield None + finally: + self.is_muted = False + + def send( + self, + sender: t.Any | None = None, + /, + *, + _async_wrapper: c.Callable[ + [c.Callable[..., c.Coroutine[t.Any, t.Any, t.Any]]], c.Callable[..., t.Any] + ] + | None = None, + **kwargs: t.Any, + ) -> list[tuple[c.Callable[..., t.Any], t.Any]]: + """Call all receivers that are connected to the given ``sender`` + or :data:`ANY`. Each receiver is called with ``sender`` as a positional + argument along with any extra keyword arguments. Return a list of + ``(receiver, return value)`` tuples. + + The order receivers are called is undefined, but can be influenced by + setting :attr:`set_class`. + + If a receiver raises an exception, that exception will propagate up. + This makes debugging straightforward, with an assumption that correctly + implemented receivers will not raise. + + :param sender: Call receivers connected to this sender, in addition to + those connected to :data:`ANY`. + :param _async_wrapper: Will be called on any receivers that are async + coroutines to turn them into sync callables. For example, could run + the receiver with an event loop. + :param kwargs: Extra keyword arguments to pass to each receiver. + + .. versionchanged:: 1.7 + Added the ``_async_wrapper`` argument. + """ + if self.is_muted: + return [] + + results = [] + + for receiver in self.receivers_for(sender): + if iscoroutinefunction(receiver): + if _async_wrapper is None: + raise RuntimeError("Cannot send to a coroutine function.") + + result = _async_wrapper(receiver)(sender, **kwargs) + else: + result = receiver(sender, **kwargs) + + results.append((receiver, result)) + + return results + + async def send_async( + self, + sender: t.Any | None = None, + /, + *, + _sync_wrapper: c.Callable[ + [c.Callable[..., t.Any]], c.Callable[..., c.Coroutine[t.Any, t.Any, t.Any]] + ] + | None = None, + **kwargs: t.Any, + ) -> list[tuple[c.Callable[..., t.Any], t.Any]]: + """Await all receivers that are connected to the given ``sender`` + or :data:`ANY`. Each receiver is called with ``sender`` as a positional + argument along with any extra keyword arguments. Return a list of + ``(receiver, return value)`` tuples. + + The order receivers are called is undefined, but can be influenced by + setting :attr:`set_class`. + + If a receiver raises an exception, that exception will propagate up. + This makes debugging straightforward, with an assumption that correctly + implemented receivers will not raise. + + :param sender: Call receivers connected to this sender, in addition to + those connected to :data:`ANY`. + :param _sync_wrapper: Will be called on any receivers that are sync + callables to turn them into async coroutines. For example, + could call the receiver in a thread. + :param kwargs: Extra keyword arguments to pass to each receiver. + + .. versionadded:: 1.7 + """ + if self.is_muted: + return [] + + results = [] + + for receiver in self.receivers_for(sender): + if not iscoroutinefunction(receiver): + if _sync_wrapper is None: + raise RuntimeError("Cannot send to a non-coroutine function.") + + result = await _sync_wrapper(receiver)(sender, **kwargs) + else: + result = await receiver(sender, **kwargs) + + results.append((receiver, result)) + + return results + + def has_receivers_for(self, sender: t.Any) -> bool: + """Check if there is at least one receiver that will be called with the + given ``sender``. A receiver connected to :data:`ANY` will always be + called, regardless of sender. Does not check if weakly referenced + receivers are still live. See :meth:`receivers_for` for a stronger + search. + + :param sender: Check for receivers connected to this sender, in addition + to those connected to :data:`ANY`. + """ + if not self.receivers: + return False + + if self._by_sender[ANY_ID]: + return True + + if sender is ANY: + return False + + return make_id(sender) in self._by_sender + + def receivers_for( + self, sender: t.Any + ) -> c.Generator[c.Callable[..., t.Any], None, None]: + """Yield each receiver to be called for ``sender``, in addition to those + to be called for :data:`ANY`. Weakly referenced receivers that are not + live will be disconnected and skipped. + + :param sender: Yield receivers connected to this sender, in addition + to those connected to :data:`ANY`. + """ + # TODO: test receivers_for(ANY) + if not self.receivers: + return + + sender_id = make_id(sender) + + if sender_id in self._by_sender: + ids = self._by_sender[ANY_ID] | self._by_sender[sender_id] + else: + ids = self._by_sender[ANY_ID].copy() + + for receiver_id in ids: + receiver = self.receivers.get(receiver_id) + + if receiver is None: + continue + + if isinstance(receiver, weakref.ref): + strong = receiver() + + if strong is None: + self._disconnect(receiver_id, ANY_ID) + continue + + yield strong + else: + yield receiver + + def disconnect(self, receiver: c.Callable[..., t.Any], sender: t.Any = ANY) -> None: + """Disconnect ``receiver`` from being called when the signal is sent by + ``sender``. + + :param receiver: A connected receiver callable. + :param sender: Disconnect from only this sender. By default, disconnect + from all senders. + """ + sender_id: c.Hashable + + if sender is ANY: + sender_id = ANY_ID + else: + sender_id = make_id(sender) + + receiver_id = make_id(receiver) + self._disconnect(receiver_id, sender_id) + + if ( + "receiver_disconnected" in self.__dict__ + and self.receiver_disconnected.receivers + ): + self.receiver_disconnected.send(self, receiver=receiver, sender=sender) + + def _disconnect(self, receiver_id: c.Hashable, sender_id: c.Hashable) -> None: + if sender_id == ANY_ID: + if self._by_receiver.pop(receiver_id, None) is not None: + for bucket in self._by_sender.values(): + bucket.discard(receiver_id) + + self.receivers.pop(receiver_id, None) + else: + self._by_sender[sender_id].discard(receiver_id) + self._by_receiver[receiver_id].discard(sender_id) + + def _make_cleanup_receiver( + self, receiver_id: c.Hashable + ) -> c.Callable[[weakref.ref[c.Callable[..., t.Any]]], None]: + """Create a callback function to disconnect a weakly referenced + receiver when it is garbage collected. + """ + + def cleanup(ref: weakref.ref[c.Callable[..., t.Any]]) -> None: + # If the interpreter is shutting down, disconnecting can result in a + # weird ignored exception. Don't call it in that case. + if not sys.is_finalizing(): + self._disconnect(receiver_id, ANY_ID) + + return cleanup + + def _make_cleanup_sender( + self, sender_id: c.Hashable + ) -> c.Callable[[weakref.ref[t.Any]], None]: + """Create a callback function to disconnect all receivers for a weakly + referenced sender when it is garbage collected. + """ + assert sender_id != ANY_ID + + def cleanup(ref: weakref.ref[t.Any]) -> None: + self._weak_senders.pop(sender_id, None) + + for receiver_id in self._by_sender.pop(sender_id, ()): + self._by_receiver[receiver_id].discard(sender_id) + + return cleanup + + def _cleanup_bookkeeping(self) -> None: + """Prune unused sender/receiver bookkeeping. Not threadsafe. + + Connecting & disconnecting leaves behind a small amount of bookkeeping + data. Typical workloads using Blinker, for example in most web apps, + Flask, CLI scripts, etc., are not adversely affected by this + bookkeeping. + + With a long-running process performing dynamic signal routing with high + volume, e.g. connecting to function closures, senders are all unique + object instances. Doing all of this over and over may cause memory usage + to grow due to extraneous bookkeeping. (An empty ``set`` for each stale + sender/receiver pair.) + + This method will prune that bookkeeping away, with the caveat that such + pruning is not threadsafe. The risk is that cleanup of a fully + disconnected receiver/sender pair occurs while another thread is + connecting that same pair. If you are in the highly dynamic, unique + receiver/sender situation that has lead you to this method, that failure + mode is perhaps not a big deal for you. + """ + for mapping in (self._by_sender, self._by_receiver): + for ident, bucket in list(mapping.items()): + if not bucket: + mapping.pop(ident, None) + + def _clear_state(self) -> None: + """Disconnect all receivers and senders. Useful for tests.""" + self._weak_senders.clear() + self.receivers.clear() + self._by_sender.clear() + self._by_receiver.clear() + + +class NamedSignal(Signal): + """A named generic notification emitter. The name is not used by the signal + itself, but matches the key in the :class:`Namespace` that it belongs to. + + :param name: The name of the signal within the namespace. + :param doc: The docstring for the signal. + """ + + def __init__(self, name: str, doc: str | None = None) -> None: + super().__init__(doc) + + #: The name of this signal. + self.name: str = name + + def __repr__(self) -> str: + base = super().__repr__() + return f"{base[:-1]}; {self.name!r}>" # noqa: E702 + + +class Namespace(dict[str, NamedSignal]): + """A dict mapping names to signals.""" + + def signal(self, name: str, doc: str | None = None) -> NamedSignal: + """Return the :class:`NamedSignal` for the given ``name``, creating it + if required. Repeated calls with the same name return the same signal. + + :param name: The name of the signal. + :param doc: The docstring of the signal. + """ + if name not in self: + self[name] = NamedSignal(name, doc) + + return self[name] + + +class _PNamespaceSignal(t.Protocol): + def __call__(self, name: str, doc: str | None = None) -> NamedSignal: ... + + +default_namespace: Namespace = Namespace() +"""A default :class:`Namespace` for creating named signals. :func:`signal` +creates a :class:`NamedSignal` in this namespace. +""" + +signal: _PNamespaceSignal = default_namespace.signal +"""Return a :class:`NamedSignal` in :data:`default_namespace` with the given +``name``, creating it if required. Repeated calls with the same name return the +same signal. +""" diff --git a/backend/venv/Lib/site-packages/blinker/py.typed b/backend/venv/Lib/site-packages/blinker/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/backend/venv/Lib/site-packages/certifi-2025.10.5.dist-info/INSTALLER b/backend/venv/Lib/site-packages/certifi-2025.10.5.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/backend/venv/Lib/site-packages/certifi-2025.10.5.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/backend/venv/Lib/site-packages/certifi-2025.10.5.dist-info/METADATA b/backend/venv/Lib/site-packages/certifi-2025.10.5.dist-info/METADATA new file mode 100644 index 0000000..ca094b1 --- /dev/null +++ b/backend/venv/Lib/site-packages/certifi-2025.10.5.dist-info/METADATA @@ -0,0 +1,78 @@ +Metadata-Version: 2.4 +Name: certifi +Version: 2025.10.5 +Summary: Python package for providing Mozilla's CA Bundle. +Home-page: https://github.com/certifi/python-certifi +Author: Kenneth Reitz +Author-email: me@kennethreitz.com +License: MPL-2.0 +Project-URL: Source, https://github.com/certifi/python-certifi +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0) +Classifier: Natural Language :: English +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Classifier: Programming Language :: Python :: 3.13 +Classifier: Programming Language :: Python :: 3.14 +Requires-Python: >=3.7 +License-File: LICENSE +Dynamic: author +Dynamic: author-email +Dynamic: classifier +Dynamic: description +Dynamic: home-page +Dynamic: license +Dynamic: license-file +Dynamic: project-url +Dynamic: requires-python +Dynamic: summary + +Certifi: Python SSL Certificates +================================ + +Certifi provides Mozilla's carefully curated collection of Root Certificates for +validating the trustworthiness of SSL certificates while verifying the identity +of TLS hosts. It has been extracted from the `Requests`_ project. + +Installation +------------ + +``certifi`` is available on PyPI. Simply install it with ``pip``:: + + $ pip install certifi + +Usage +----- + +To reference the installed certificate authority (CA) bundle, you can use the +built-in function:: + + >>> import certifi + + >>> certifi.where() + '/usr/local/lib/python3.7/site-packages/certifi/cacert.pem' + +Or from the command line:: + + $ python -m certifi + /usr/local/lib/python3.7/site-packages/certifi/cacert.pem + +Enjoy! + +.. _`Requests`: https://requests.readthedocs.io/en/master/ + +Addition/Removal of Certificates +-------------------------------- + +Certifi does not support any addition/removal or other modification of the +CA trust store content. This project is intended to provide a reliable and +highly portable root of trust to python deployments. Look to upstream projects +for methods to use alternate trust. diff --git a/backend/venv/Lib/site-packages/certifi-2025.10.5.dist-info/RECORD b/backend/venv/Lib/site-packages/certifi-2025.10.5.dist-info/RECORD new file mode 100644 index 0000000..d5a0fab --- /dev/null +++ b/backend/venv/Lib/site-packages/certifi-2025.10.5.dist-info/RECORD @@ -0,0 +1,14 @@ +certifi-2025.10.5.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +certifi-2025.10.5.dist-info/METADATA,sha256=RzyR4sT6xRN1pNNy24IHVOlZuDJh1BNfaMa04zEadtk,2474 +certifi-2025.10.5.dist-info/RECORD,, +certifi-2025.10.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91 +certifi-2025.10.5.dist-info/licenses/LICENSE,sha256=6TcW2mucDVpKHfYP5pWzcPBpVgPSH2-D8FPkLPwQyvc,989 +certifi-2025.10.5.dist-info/top_level.txt,sha256=KMu4vUCfsjLrkPbSNdgdekS-pVJzBAJFO__nI8NF6-U,8 +certifi/__init__.py,sha256=jWkaYHMk4oIPSSBEK5bLMbO_qrkyNm_cRFx-D16-3Ks,94 +certifi/__main__.py,sha256=xBBoj905TUWBLRGANOcf7oi6e-3dMP4cEoG9OyMs11g,243 +certifi/__pycache__/__init__.cpython-312.pyc,, +certifi/__pycache__/__main__.cpython-312.pyc,, +certifi/__pycache__/core.cpython-312.pyc,, +certifi/cacert.pem,sha256=IIn8WiWDZAH67pn3IkYLAbOTmZdGoPuBeUNmbW7MBFg,291366 +certifi/core.py,sha256=XFXycndG5pf37ayeF8N32HUuDafsyhkVMbO4BAPWHa0,3394 +certifi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 diff --git a/backend/venv/Lib/site-packages/certifi-2025.10.5.dist-info/WHEEL b/backend/venv/Lib/site-packages/certifi-2025.10.5.dist-info/WHEEL new file mode 100644 index 0000000..e7fa31b --- /dev/null +++ b/backend/venv/Lib/site-packages/certifi-2025.10.5.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: setuptools (80.9.0) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/backend/venv/Lib/site-packages/certifi-2025.10.5.dist-info/licenses/LICENSE b/backend/venv/Lib/site-packages/certifi-2025.10.5.dist-info/licenses/LICENSE new file mode 100644 index 0000000..62b076c --- /dev/null +++ b/backend/venv/Lib/site-packages/certifi-2025.10.5.dist-info/licenses/LICENSE @@ -0,0 +1,20 @@ +This package contains a modified version of ca-bundle.crt: + +ca-bundle.crt -- Bundle of CA Root Certificates + +This is a bundle of X.509 certificates of public Certificate Authorities +(CA). These were automatically extracted from Mozilla's root certificates +file (certdata.txt). This file can be found in the mozilla source tree: +https://hg.mozilla.org/mozilla-central/file/tip/security/nss/lib/ckfw/builtins/certdata.txt +It contains the certificates in PEM format and therefore +can be directly used with curl / libcurl / php_curl, or with +an Apache+mod_ssl webserver for SSL client authentication. +Just configure this file as the SSLCACertificateFile.# + +***** BEGIN LICENSE BLOCK ***** +This Source Code Form is subject to the terms of the Mozilla Public License, +v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain +one at http://mozilla.org/MPL/2.0/. + +***** END LICENSE BLOCK ***** +@(#) $RCSfile: certdata.txt,v $ $Revision: 1.80 $ $Date: 2011/11/03 15:11:58 $ diff --git a/backend/venv/Lib/site-packages/certifi-2025.10.5.dist-info/top_level.txt b/backend/venv/Lib/site-packages/certifi-2025.10.5.dist-info/top_level.txt new file mode 100644 index 0000000..963eac5 --- /dev/null +++ b/backend/venv/Lib/site-packages/certifi-2025.10.5.dist-info/top_level.txt @@ -0,0 +1 @@ +certifi diff --git a/backend/venv/Lib/site-packages/certifi/__init__.py b/backend/venv/Lib/site-packages/certifi/__init__.py new file mode 100644 index 0000000..c4b6c0b --- /dev/null +++ b/backend/venv/Lib/site-packages/certifi/__init__.py @@ -0,0 +1,4 @@ +from .core import contents, where + +__all__ = ["contents", "where"] +__version__ = "2025.10.05" diff --git a/backend/venv/Lib/site-packages/certifi/__main__.py b/backend/venv/Lib/site-packages/certifi/__main__.py new file mode 100644 index 0000000..8945b5d --- /dev/null +++ b/backend/venv/Lib/site-packages/certifi/__main__.py @@ -0,0 +1,12 @@ +import argparse + +from certifi import contents, where + +parser = argparse.ArgumentParser() +parser.add_argument("-c", "--contents", action="store_true") +args = parser.parse_args() + +if args.contents: + print(contents()) +else: + print(where()) diff --git a/backend/venv/Lib/site-packages/certifi/__pycache__/__init__.cpython-312.pyc b/backend/venv/Lib/site-packages/certifi/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b745fc042a1eeeecc1fb119cbafed232ef8064dd GIT binary patch literal 325 zcmYjMze~eF6uwJRTN~;of{Qw4FxEg85f?iaD~d}vJlfo|J(66)T}-Ky{s(UU4gM`I zj*>;ep|}ZM#K~7s@EgAOz3=_vJ#{*5f|!5JCzlxCm&qTjU$NLm@jwI-G$k30Xl6wg zCBhQ+*oti7M9!??t$a{y^Q^iR=c)u%nz}KafCg=&uN|bDcF+w%f4}Q@!xOJjJ8}NM zTsJu%rYYyO%XtOb$Xs#$NESFszTxrCLhuw6(TJ%M=tWvV%(1jZ5hM&O+udinN%jXblav+@MG%!< zyy>5y#Q(&Lp_SC}Qt=SH3B8CXXVPqQabV_s^L^iY^JeCAspKI!CVwW|r!xLjn_`$V zaC#)cI~1V^_fShkt%nn>r6qbx$4EnfI!=)^kHZ;knP7HGbG|^49vPAO$r|cs3`Wwo zSg7-OUdI8aW6b#i(FNIoE2maChxkmxXcx~k{eN1`{-uoTHBC5SmU2ir6Xwn~P}tMz z;htBopVJ=W83muyKGd+Vf{@2qTJwYx&~_eB2Eq=3^7vUy)qSXHR4hE8?S3N5ZYl>A z*3?PGg&>N2nK;#iH)YkH31hmNIgL~P5veahf8pUh@m*lDH3E5M*{MIqX-_ha(T|05BuPbA>I&!Or?$v$k7+GUf9-;Ev=KI?p zo_|5*BeZgCm&SHwWLFODEBnTYZogW6vHHz$-`qU7_0_oiL!#>kH(svOi?aAXZ6}~g literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/certifi/__pycache__/core.cpython-312.pyc b/backend/venv/Lib/site-packages/certifi/__pycache__/core.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..026169dd4686384a9d32c9adcb8bbe6646a21702 GIT binary patch literal 2072 zcmbVN%}*pn6tDgmrkNSG5fFx*4NNd9;|H3N-BnS;?qH%qU;}8}Nhh7AyMP{s?nzbg zrHSF-VLi!hIcy9E54*uXVE=?o^uRc4Ff9iYO$ay4kZAVgtDf#27&-Zpdhd1Bdo|s^ z->+(Z?C3}!u;YJ@mv46<^apK(MnnJ*K$$9LP-hR zn$e1_Xb6#hsBSCAR@;hgtMOu7K$d7IFxo8%Cl*C34m%`+T!B2bB|=9#baWK2tg1!z zKOKp49mz&VuHy@wFfn2FqCHaCN_-VrA~C;g)9k8it(9?>V75janq|v4Yde$~<+8zS z*U6S$vyr%qS<~Pc*g>V;c{4`=7~!u;o+qU(6mX1e|e)p`FjqwucwDaC|p z`8V_V6>Y}B6U1J}+61O6%&lm%Gjn&Qv<-|`u4}}lmGX6M!7x{_V`=NyS=XlQ1&!Ja zzg~e^V+m6&0PPLaB^Z$NRR0$n5a=e`BwQhU&>nEx=tx!%<#bg}@AmAnz4>3{R|w}m zC!X+cIZ67t7dNQBXqT}UZF}_ z#Wt2P!K5GZ=V8!EaNFpt6Q$Az$-%Q;lo|T|#fR;+q5R>{SaoRZ@l6n>tE$eLM5b%!8Sysn`BgGY3k>|D_8Ia+dh0e+CX14ERBC zL4?R$s`-ekQp7H75SS(XAcx(6Wo()}2P=eQ?!^ph+ICLx6zrI;Wjjkb$p?^dQF`qJ z8()7Ujhd*R(p2t*3`j6b-1byKfG2`Zyc)QRdxKy%LnRsO`SbZ zW&>e+vQN+e^j$zfh6x{q?;yFLW~Av-s-+kn z85fgpA%Yi`Nw}JG3h9R6DNC5?k>&`O4C&>rkGnK?{Jgh7>C4M^Z^I&eAKW>OrBUXE zy>}j#Ygfnqx2mFhfg^oURhHLhe!rOP9VIp^*uS!KHIa9P_7})c6zseZ|d>Q zr)uFqDFnn4zTb4N(~Il6<(hEbB)UZ#FmMFC)H+2|W|U(*L<7)tm_qMP7OB|#AW5@Ui~Paz@s z8|tXbg7E68g5>z2)LoUjcQ$^O29D+Y?_IsylfQQNZBL!beX(mhZ`Bcm)4ULy6L!oq c#N*!y6dM=LSEd`45Kc#h*hEk{A^6bz3tHr*M*si- literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/certifi/cacert.pem b/backend/venv/Lib/site-packages/certifi/cacert.pem new file mode 100644 index 0000000..0b68ebf --- /dev/null +++ b/backend/venv/Lib/site-packages/certifi/cacert.pem @@ -0,0 +1,4800 @@ + +# Issuer: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc. +# Subject: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc. +# Label: "Entrust Root Certification Authority" +# Serial: 1164660820 +# MD5 Fingerprint: d6:a5:c3:ed:5d:dd:3e:00:c1:3d:87:92:1f:1d:3f:e4 +# SHA1 Fingerprint: b3:1e:b1:b7:40:e3:6c:84:02:da:dc:37:d4:4d:f5:d4:67:49:52:f9 +# SHA256 Fingerprint: 73:c1:76:43:4f:1b:c6:d5:ad:f4:5b:0e:76:e7:27:28:7c:8d:e5:76:16:c1:e6:e6:14:1a:2b:2c:bc:7d:8e:4c +-----BEGIN CERTIFICATE----- +MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC +VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0 +Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW +KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl +cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw +NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw +NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy +ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV +BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ +KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo +Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4 +4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9 +KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI +rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi +94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB +sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi +gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo +kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE +vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA +A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t +O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua +AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP +9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/ +eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m +0vdXcDazv/wor3ElhVsT/h5/WrQ8 +-----END CERTIFICATE----- + +# Issuer: CN=QuoVadis Root CA 2 O=QuoVadis Limited +# Subject: CN=QuoVadis Root CA 2 O=QuoVadis Limited +# Label: "QuoVadis Root CA 2" +# Serial: 1289 +# MD5 Fingerprint: 5e:39:7b:dd:f8:ba:ec:82:e9:ac:62:ba:0c:54:00:2b +# SHA1 Fingerprint: ca:3a:fb:cf:12:40:36:4b:44:b2:16:20:88:80:48:39:19:93:7c:f7 +# SHA256 Fingerprint: 85:a0:dd:7d:d7:20:ad:b7:ff:05:f8:3d:54:2b:20:9d:c7:ff:45:28:f7:d6:77:b1:83:89:fe:a5:e5:c4:9e:86 +-----BEGIN CERTIFICATE----- +MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x +GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv +b3QgQ0EgMjAeFw0wNjExMjQxODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNV +BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W +YWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCa +GMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6XJxg +Fyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55J +WpzmM+Yklvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bB +rrcCaoF6qUWD4gXmuVbBlDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp ++ARz8un+XJiM9XOva7R+zdRcAitMOeGylZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1 +ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt66/3FsvbzSUr5R/7mp/i +Ucw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1JdxnwQ5hYIiz +PtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og +/zOhD7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UH +oycR7hYQe7xFSkyyBNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuI +yV77zGHcizN300QyNQliBJIWENieJ0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1Ud +EwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBQahGK8SEwzJQTU7tD2 +A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGUa6FJpEcwRTEL +MAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT +ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2f +BluornFdLwUvZ+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzn +g/iN/Ae42l9NLmeyhP3ZRPx3UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2Bl +fF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodmVjB3pjd4M1IQWK4/YY7yarHvGH5K +WWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK+JDSV6IZUaUtl0Ha +B0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrWIozc +hLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPR +TUIZ3Ph1WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWD +mbA4CD/pXvk1B+TJYm5Xf6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0Z +ohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y +4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8VCLAAVBpQ570su9t+Oza +8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u +-----END CERTIFICATE----- + +# Issuer: CN=QuoVadis Root CA 3 O=QuoVadis Limited +# Subject: CN=QuoVadis Root CA 3 O=QuoVadis Limited +# Label: "QuoVadis Root CA 3" +# Serial: 1478 +# MD5 Fingerprint: 31:85:3c:62:94:97:63:b9:aa:fd:89:4e:af:6f:e0:cf +# SHA1 Fingerprint: 1f:49:14:f7:d8:74:95:1d:dd:ae:02:c0:be:fd:3a:2d:82:75:51:85 +# SHA256 Fingerprint: 18:f1:fc:7f:20:5d:f8:ad:dd:eb:7f:e0:07:dd:57:e3:af:37:5a:9c:4d:8d:73:54:6b:f4:f1:fe:d1:e1:8d:35 +-----BEGIN CERTIFICATE----- +MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x +GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv +b3QgQ0EgMzAeFw0wNjExMjQxOTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNV +BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W +YWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDM +V0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNggDhoB +4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUr +H556VOijKTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd +8lyyBTNvijbO0BNO/79KDDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9Cabwv +vWhDFlaJKjdhkf2mrk7AyxRllDdLkgbvBNDInIjbC3uBr7E9KsRlOni27tyAsdLT +mZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwpp5ijJUMv7/FfJuGITfhe +btfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8nT8KKdjc +T5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDt +WAEXMJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZ +c6tsgLjoC2SToJyMGf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A +4iLItLRkT9a6fUg+qGkM17uGcclzuD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYD +VR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHTBgkrBgEEAb5YAAMwgcUwgZMG +CCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmljYXRlIGNvbnN0 +aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0 +aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVu +dC4wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2Nw +czALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4G +A1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4ywLQoUmkRzBFMQswCQYDVQQGEwJC +TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UEAxMSUXVvVmFkaXMg +Um9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZVqyM0 +7ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSem +d1o417+shvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd ++LJ2w/w4E6oM3kJpK27zPOuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B +4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadN +t54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp8kokUvd0/bpO5qgdAm6x +DYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBCbjPsMZ57 +k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6s +zHXug/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0j +Wy10QJLZYxkNc91pvGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeT +mJlglFwjz1onl14LBQaTNx47aTbrqZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK +4SVhM7JZG+Ju1zdXtg2pEto= +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert Assured ID Root CA" +# Serial: 17154717934120587862167794914071425081 +# MD5 Fingerprint: 87:ce:0b:7b:2a:0e:49:00:e1:58:71:9b:37:a8:93:72 +# SHA1 Fingerprint: 05:63:b8:63:0d:62:d7:5a:bb:c8:ab:1e:4b:df:b5:a8:99:b2:4d:43 +# SHA256 Fingerprint: 3e:90:99:b5:01:5e:8f:48:6c:00:bc:ea:9d:11:1e:e7:21:fa:ba:35:5a:89:bc:f1:df:69:56:1e:3d:c6:32:5c +-----BEGIN CERTIFICATE----- +MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv +b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl +cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c +JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP +mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+ +wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4 +VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/ +AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB +AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW +BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun +pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC +dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf +fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm +NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx +H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe ++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert Global Root CA" +# Serial: 10944719598952040374951832963794454346 +# MD5 Fingerprint: 79:e4:a9:84:0d:7d:3a:96:d7:c0:4f:e2:43:4c:89:2e +# SHA1 Fingerprint: a8:98:5d:3a:65:e5:e5:c4:b2:d7:d6:6d:40:c6:dd:2f:b1:9c:54:36 +# SHA256 Fingerprint: 43:48:a0:e9:44:4c:78:cb:26:5e:05:8d:5e:89:44:b4:d8:4f:96:62:bd:26:db:25:7f:89:34:a4:43:c7:01:61 +-----BEGIN CERTIFICATE----- +MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD +QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT +MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j +b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB +CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 +nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt +43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P +T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 +gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO +BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR +TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw +DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr +hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg +06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF +PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls +YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk +CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert High Assurance EV Root CA" +# Serial: 3553400076410547919724730734378100087 +# MD5 Fingerprint: d4:74:de:57:5c:39:b2:d3:9c:85:83:c5:c0:65:49:8a +# SHA1 Fingerprint: 5f:b7:ee:06:33:e2:59:db:ad:0c:4c:9a:e6:d3:8f:1a:61:c7:dc:25 +# SHA256 Fingerprint: 74:31:e5:f4:c3:c1:ce:46:90:77:4f:0b:61:e0:54:40:88:3b:a9:a0:1e:d0:0b:a6:ab:d7:80:6e:d3:b1:18:cf +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j +ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL +MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 +LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug +RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm ++9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW +PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM +xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB +Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3 +hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg +EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF +MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA +FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec +nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z +eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF +hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 +Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe +vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep ++OkuE6N36B9K +-----END CERTIFICATE----- + +# Issuer: CN=SwissSign Gold CA - G2 O=SwissSign AG +# Subject: CN=SwissSign Gold CA - G2 O=SwissSign AG +# Label: "SwissSign Gold CA - G2" +# Serial: 13492815561806991280 +# MD5 Fingerprint: 24:77:d9:a8:91:d1:3b:fa:88:2d:c2:ff:f8:cd:33:93 +# SHA1 Fingerprint: d8:c5:38:8a:b7:30:1b:1b:6e:d4:7a:e6:45:25:3a:6f:9f:1a:27:61 +# SHA256 Fingerprint: 62:dd:0b:e9:b9:f5:0a:16:3e:a0:f8:e7:5c:05:3b:1e:ca:57:ea:55:c8:68:8f:64:7c:68:81:f2:c8:35:7b:95 +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +# Issuer: CN=SecureTrust CA O=SecureTrust Corporation +# Subject: CN=SecureTrust CA O=SecureTrust Corporation +# Label: "SecureTrust CA" +# Serial: 17199774589125277788362757014266862032 +# MD5 Fingerprint: dc:32:c3:a7:6d:25:57:c7:68:09:9d:ea:2d:a9:a2:d1 +# SHA1 Fingerprint: 87:82:c6:c3:04:35:3b:cf:d2:96:92:d2:59:3e:7d:44:d9:34:ff:11 +# SHA256 Fingerprint: f1:c1:b5:0a:e5:a2:0d:d8:03:0e:c9:f6:bc:24:82:3d:d3:67:b5:25:57:59:b4:e7:1b:61:fc:e9:f7:37:5d:73 +-----BEGIN CERTIFICATE----- +MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBI +MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x +FzAVBgNVBAMTDlNlY3VyZVRydXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIz +MTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1NlY3VyZVRydXN0IENv +cnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQXOZEz +Zum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO +0gMdA+9tDWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIao +wW8xQmxSPmjL8xk037uHGFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj +7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b01k/unK8RCSc43Oz969XL0Imnal0ugBS +8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmHursCAwEAAaOBnTCBmjAT +BgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB +/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCeg +JYYjaHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGC +NxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt3 +6Z3q059c4EVlew3KW+JwULKUBRSuSceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/ +3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHfmbx8IVQr5Fiiu1cprp6poxkm +D5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZnMUFdAvnZyPS +CPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR +3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= +-----END CERTIFICATE----- + +# Issuer: CN=Secure Global CA O=SecureTrust Corporation +# Subject: CN=Secure Global CA O=SecureTrust Corporation +# Label: "Secure Global CA" +# Serial: 9751836167731051554232119481456978597 +# MD5 Fingerprint: cf:f4:27:0d:d4:ed:dc:65:16:49:6d:3d:da:bf:6e:de +# SHA1 Fingerprint: 3a:44:73:5a:e5:81:90:1f:24:86:61:46:1e:3b:9c:c4:5f:f5:3a:1b +# SHA256 Fingerprint: 42:00:f5:04:3a:c8:59:0e:bb:52:7d:20:9e:d1:50:30:29:fb:cb:d4:1c:a1:b5:06:ec:27:f1:5a:de:7d:ac:69 +-----BEGIN CERTIFICATE----- +MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBK +MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x +GTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkx +MjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3Qg +Q29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jxYDiJ +iQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa +/FHtaMbQbqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJ +jnIFHovdRIWCQtBJwB1g8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnI +HmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYVHDGA76oYa8J719rO+TMg1fW9ajMtgQT7 +sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi0XPnj3pDAgMBAAGjgZ0w +gZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQF +MAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCsw +KaAnoCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsG +AQQBgjcVAQQDAgEAMA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0L +URYD7xh8yOOvaliTFGCRsoTciE6+OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXO +H0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cnCDpOGR86p1hcF895P4vkp9Mm +I50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/53CYNv6ZHdAbY +iNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc +f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW +-----END CERTIFICATE----- + +# Issuer: CN=COMODO Certification Authority O=COMODO CA Limited +# Subject: CN=COMODO Certification Authority O=COMODO CA Limited +# Label: "COMODO Certification Authority" +# Serial: 104350513648249232941998508985834464573 +# MD5 Fingerprint: 5c:48:dc:f7:42:72:ec:56:94:6d:1c:cc:71:35:80:75 +# SHA1 Fingerprint: 66:31:bf:9e:f7:4f:9e:b6:c9:d5:a6:0c:ba:6a:be:d1:f7:bd:ef:7b +# SHA256 Fingerprint: 0c:2c:d6:3d:f7:80:6f:a3:99:ed:e8:09:11:6b:57:5b:f8:79:89:f0:65:18:f9:80:8c:86:05:03:17:8b:af:66 +-----BEGIN CERTIFICATE----- +MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB +gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G +A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV +BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw +MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl +YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P +RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3 +UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI +2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8 +Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp ++2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+ +DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O +nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW +/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g +PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u +QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY +SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv +IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ +RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4 +zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd +BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB +ZQ== +-----END CERTIFICATE----- + +# Issuer: CN=COMODO ECC Certification Authority O=COMODO CA Limited +# Subject: CN=COMODO ECC Certification Authority O=COMODO CA Limited +# Label: "COMODO ECC Certification Authority" +# Serial: 41578283867086692638256921589707938090 +# MD5 Fingerprint: 7c:62:ff:74:9d:31:53:5e:68:4a:d5:78:aa:1e:bf:23 +# SHA1 Fingerprint: 9f:74:4e:9f:2b:4d:ba:ec:0f:31:2c:50:b6:56:3b:8e:2d:93:c3:11 +# SHA256 Fingerprint: 17:93:92:7a:06:14:54:97:89:ad:ce:2f:8f:34:f7:f0:b6:6d:0f:3a:e3:a3:b8:4d:21:ec:15:db:ba:4f:ad:c7 +-----BEGIN CERTIFICATE----- +MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL +MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE +BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT +IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw +MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy +ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N +T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR +FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J +cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW +BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ +BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm +fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv +GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= +-----END CERTIFICATE----- + +# Issuer: CN=Certigna O=Dhimyotis +# Subject: CN=Certigna O=Dhimyotis +# Label: "Certigna" +# Serial: 18364802974209362175 +# MD5 Fingerprint: ab:57:a6:5b:7d:42:82:19:b5:d8:58:26:28:5e:fd:ff +# SHA1 Fingerprint: b1:2e:13:63:45:86:a4:6f:1a:b2:60:68:37:58:2d:c4:ac:fd:94:97 +# SHA256 Fingerprint: e3:b6:a2:db:2e:d7:ce:48:84:2f:7a:c5:32:41:c7:b7:1d:54:14:4b:fb:40:c1:1f:3f:1d:0b:42:f5:ee:a1:2d +-----BEGIN CERTIFICATE----- +MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNV +BAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4X +DTA3MDYyOTE1MTMwNVoXDTI3MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQ +BgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwIQ2VydGlnbmEwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7qXOEm7RFHYeGifBZ4 +QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyHGxny +gQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbw +zBfsV1/pogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q +130yGLMLLGq/jj8UEYkgDncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2 +JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKfIrjxwo1p3Po6WAbfAgMBAAGjgbwwgbkw +DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQtCRZvgHyUtVF9lo53BEw +ZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJBgNVBAYT +AkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzj +AQ/JSP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG +9w0BAQUFAAOCAQEAhQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8h +bV6lUmPOEvjvKtpv6zf+EwLHyzs+ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFnc +fca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1kluPBS1xp81HlDQwY9qcEQCYsuu +HWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY1gkIl2PlwS6w +t0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw +WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== +-----END CERTIFICATE----- + +# Issuer: O=Chunghwa Telecom Co., Ltd. OU=ePKI Root Certification Authority +# Subject: O=Chunghwa Telecom Co., Ltd. OU=ePKI Root Certification Authority +# Label: "ePKI Root Certification Authority" +# Serial: 28956088682735189655030529057352760477 +# MD5 Fingerprint: 1b:2e:00:ca:26:06:90:3d:ad:fe:6f:15:68:d3:6b:b3 +# SHA1 Fingerprint: 67:65:0d:f1:7e:8e:7e:5b:82:40:a4:f4:56:4b:cf:e2:3d:69:c6:f0 +# SHA256 Fingerprint: c0:a6:f4:dc:63:a2:4b:fd:cf:54:ef:2a:6a:08:2a:0a:72:de:35:80:3e:2f:f5:ff:52:7a:e5:d8:72:06:df:d5 +-----BEGIN CERTIFICATE----- +MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBe +MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0 +ZC4xKjAoBgNVBAsMIWVQS0kgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe +Fw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMxMjdaMF4xCzAJBgNVBAYTAlRXMSMw +IQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEqMCgGA1UECwwhZVBL +SSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEF +AAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAH +SyZbCUNsIZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAh +ijHyl3SJCRImHJ7K2RKilTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3X +DZoTM1PRYfl61dd4s5oz9wCGzh1NlDivqOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1 +TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX12ruOzjjK9SXDrkb5wdJ +fzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0OWQqraffA +sgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uU +WH1+ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLS +nT0IFaUQAS2zMnaolQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pH +dmX2Os+PYhcZewoozRrSgx4hxyy/vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJip +NiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXiZo1jDiVN1Rmy5nk3pyKdVDEC +AwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/QkqiMAwGA1UdEwQF +MAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH +ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGB +uvl2ICO1J2B01GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6Yl +PwZpVnPDimZI+ymBV3QGypzqKOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkP +JXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdVxrsStZf0X4OFunHB2WyBEXYKCrC/ +gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEPNXubrjlpC2JgQCA2 +j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+rGNm6 +5ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUB +o2M3IUxExJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS +/jQ6fbjpKdx2qcgw+BRxgMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2z +Gp1iro2C6pSe3VkQw63d4k3jMdXH7OjysP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTE +W9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmODBCEIZ43ygknQW/2xzQ+D +hNQ+IIX3Sj0rnP0qCglN6oH4EZw= +-----END CERTIFICATE----- + +# Issuer: O=certSIGN OU=certSIGN ROOT CA +# Subject: O=certSIGN OU=certSIGN ROOT CA +# Label: "certSIGN ROOT CA" +# Serial: 35210227249154 +# MD5 Fingerprint: 18:98:c0:d6:e9:3a:fc:f9:b0:f5:0c:f7:4b:01:44:17 +# SHA1 Fingerprint: fa:b7:ee:36:97:26:62:fb:2d:b0:2a:f6:bf:03:fd:e8:7c:4b:2f:9b +# SHA256 Fingerprint: ea:a9:62:c4:fa:4a:6b:af:eb:e4:15:19:6d:35:1c:cd:88:8d:4f:53:f3:fa:8a:e6:d7:c4:66:a9:4e:60:42:bb +-----BEGIN CERTIFICATE----- +MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYT +AlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBD +QTAeFw0wNjA3MDQxNzIwMDRaFw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJP +MREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7IJUqOtdu0KBuqV5Do +0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHHrfAQ +UySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5d +RdY4zTW2ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQ +OA7+j0xbm0bqQfWwCHTD0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwv +JoIQ4uNllAoEwF73XVv4EOLQunpL+943AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08C +AwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAcYwHQYDVR0O +BBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IBAQA+0hyJ +LjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecY +MnQ8SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ +44gx+FkagQnIl6Z0x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6I +Jd1hJyMctTEHBDa0GpC9oHRxUIltvBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNw +i/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7NzTogVZ96edhBiIL5VaZVDADlN +9u6wWk5JRFRYX0KD +-----END CERTIFICATE----- + +# Issuer: CN=NetLock Arany (Class Gold) F\u0151tan\xfas\xedtv\xe1ny O=NetLock Kft. OU=Tan\xfas\xedtv\xe1nykiad\xf3k (Certification Services) +# Subject: CN=NetLock Arany (Class Gold) F\u0151tan\xfas\xedtv\xe1ny O=NetLock Kft. OU=Tan\xfas\xedtv\xe1nykiad\xf3k (Certification Services) +# Label: "NetLock Arany (Class Gold) F\u0151tan\xfas\xedtv\xe1ny" +# Serial: 80544274841616 +# MD5 Fingerprint: c5:a1:b7:ff:73:dd:d6:d7:34:32:18:df:fc:3c:ad:88 +# SHA1 Fingerprint: 06:08:3f:59:3f:15:a1:04:a0:69:a4:6b:a9:03:d0:06:b7:97:09:91 +# SHA256 Fingerprint: 6c:61:da:c3:a2:de:f0:31:50:6b:e0:36:d2:a6:fe:40:19:94:fb:d1:3d:f9:c8:d4:66:59:92:74:c4:46:ec:98 +-----BEGIN CERTIFICATE----- +MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQG +EwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3 +MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNl +cnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWR +dGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgxMjA2MTUwODIxWjCB +pzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxOZXRM +b2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlm +aWNhdGlvbiBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNz +IEdvbGQpIEbFkXRhbsO6c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAxCRec75LbRTDofTjl5Bu0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrT +lF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw/HpYzY6b7cNGbIRwXdrz +AZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAkH3B5r9s5 +VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRG +ILdwfzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2 +BJtr+UBdADTHLpl1neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAG +AQH/AgEEMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2M +U9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwWqZw8UQCgwBEIBaeZ5m8BiFRh +bvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTtaYtOUZcTh5m2C ++C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC +bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2F +uLjbvrW5KfnaNwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2 +XjG4Kvte9nHfRCaexOYNkbQudZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= +-----END CERTIFICATE----- + +# Issuer: CN=Microsec e-Szigno Root CA 2009 O=Microsec Ltd. +# Subject: CN=Microsec e-Szigno Root CA 2009 O=Microsec Ltd. +# Label: "Microsec e-Szigno Root CA 2009" +# Serial: 14014712776195784473 +# MD5 Fingerprint: f8:49:f4:03:bc:44:2d:83:be:48:69:7d:29:64:fc:b1 +# SHA1 Fingerprint: 89:df:74:fe:5c:f4:0f:4a:80:f9:e3:37:7d:54:da:91:e1:01:31:8e +# SHA256 Fingerprint: 3c:5f:81:fe:a5:fa:b8:2c:64:bf:a2:ea:ec:af:cd:e8:e0:77:fc:86:20:a7:ca:e5:37:16:3d:f3:6e:db:f3:78 +-----BEGIN CERTIFICATE----- +MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD +VQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0 +ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0G +CSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTAeFw0wOTA2MTYxMTMwMThaFw0y +OTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3Qx +FjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3pp +Z25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o +dTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvP +kd6mJviZpWNwrZuuyjNAfW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tc +cbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG0IMZfcChEhyVbUr02MelTTMuhTlAdX4U +fIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKApxn1ntxVUwOXewdI/5n7 +N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm1HxdrtbC +xkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1 ++rUCAwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G +A1UdDgQWBBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPM +Pcu1SCOhGnqmKrs0aDAbBgNVHREEFDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqG +SIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0olZMEyL/azXm4Q5DwpL7v8u8h +mLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfXI/OMn74dseGk +ddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775 +tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c +2Pm2G2JwCz02yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5t +HMN1Rq41Bab2XD0h7lbwyYIiLXpUq3DDfSJlgnCW +-----END CERTIFICATE----- + +# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3 +# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3 +# Label: "GlobalSign Root CA - R3" +# Serial: 4835703278459759426209954 +# MD5 Fingerprint: c5:df:b8:49:ca:05:13:55:ee:2d:ba:1a:c3:3e:b0:28 +# SHA1 Fingerprint: d6:9b:56:11:48:f0:1c:77:c5:45:78:c1:09:26:df:5b:85:69:76:ad +# SHA256 Fingerprint: cb:b5:22:d7:b7:f1:27:ad:6a:01:13:86:5b:df:1c:d4:10:2e:7d:07:59:af:63:5a:7c:f4:72:0d:c9:63:c5:3b +-----BEGIN CERTIFICATE----- +MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G +A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp +Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4 +MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG +A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8 +RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT +gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm +KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd +QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ +XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw +DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o +LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU +RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp +jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK +6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX +mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs +Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH +WD9f +-----END CERTIFICATE----- + +# Issuer: CN=Izenpe.com O=IZENPE S.A. +# Subject: CN=Izenpe.com O=IZENPE S.A. +# Label: "Izenpe.com" +# Serial: 917563065490389241595536686991402621 +# MD5 Fingerprint: a6:b0:cd:85:80:da:5c:50:34:a3:39:90:2f:55:67:73 +# SHA1 Fingerprint: 2f:78:3d:25:52:18:a7:4a:65:39:71:b5:2c:a2:9c:45:15:6f:e9:19 +# SHA256 Fingerprint: 25:30:cc:8e:98:32:15:02:ba:d9:6f:9b:1f:ba:1b:09:9e:2d:29:9e:0f:45:48:bb:91:4f:36:3b:c0:d4:53:1f +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +# Issuer: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc. +# Subject: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc. +# Label: "Go Daddy Root Certificate Authority - G2" +# Serial: 0 +# MD5 Fingerprint: 80:3a:bc:22:c1:e6:fb:8d:9b:3b:27:4a:32:1b:9a:01 +# SHA1 Fingerprint: 47:be:ab:c9:22:ea:e8:0e:78:78:34:62:a7:9f:45:c2:54:fd:e6:8b +# SHA256 Fingerprint: 45:14:0b:32:47:eb:9c:c8:c5:b4:f0:d7:b5:30:91:f7:32:92:08:9e:6e:5a:63:e2:74:9d:d3:ac:a9:19:8e:da +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx +EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT +EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp +ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz +NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH +EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE +AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD +E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH +/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy +DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh +GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR +tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA +AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE +FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX +WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu +9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr +gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo +2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO +LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI +4uJEvlz36hz1 +-----END CERTIFICATE----- + +# Issuer: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc. +# Subject: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc. +# Label: "Starfield Root Certificate Authority - G2" +# Serial: 0 +# MD5 Fingerprint: d6:39:81:c6:52:7e:96:69:fc:fc:ca:66:ed:05:f2:96 +# SHA1 Fingerprint: b5:1c:06:7c:ee:2b:0c:3d:f8:55:ab:2d:92:f4:fe:39:d4:e7:0f:0e +# SHA256 Fingerprint: 2c:e1:cb:0b:f9:d2:f9:e1:02:99:3f:be:21:51:52:c3:b2:dd:0c:ab:de:1c:68:e5:31:9b:83:91:54:db:b7:f5 +-----BEGIN CERTIFICATE----- +MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx +EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT +HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs +ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw +MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 +b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj +aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp +Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg +nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1 +HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N +Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN +dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0 +HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO +BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G +CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU +sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3 +4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg +8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K +pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1 +mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 +-----END CERTIFICATE----- + +# Issuer: CN=Starfield Services Root Certificate Authority - G2 O=Starfield Technologies, Inc. +# Subject: CN=Starfield Services Root Certificate Authority - G2 O=Starfield Technologies, Inc. +# Label: "Starfield Services Root Certificate Authority - G2" +# Serial: 0 +# MD5 Fingerprint: 17:35:74:af:7b:61:1c:eb:f4:f9:3c:e2:ee:40:f9:a2 +# SHA1 Fingerprint: 92:5a:8f:8d:2c:6d:04:e0:66:5f:59:6a:ff:22:d8:63:e8:25:6f:3f +# SHA256 Fingerprint: 56:8d:69:05:a2:c8:87:08:a4:b3:02:51:90:ed:cf:ed:b1:97:4a:60:6a:13:c6:e5:29:0f:cb:2a:e6:3e:da:b5 +-----BEGIN CERTIFICATE----- +MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx +EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT +HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs +ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 +MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD +VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy +ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy +dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p +OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2 +8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K +Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe +hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk +6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw +DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q +AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI +bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB +ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z +qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd +iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn +0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN +sSi6 +-----END CERTIFICATE----- + +# Issuer: CN=AffirmTrust Commercial O=AffirmTrust +# Subject: CN=AffirmTrust Commercial O=AffirmTrust +# Label: "AffirmTrust Commercial" +# Serial: 8608355977964138876 +# MD5 Fingerprint: 82:92:ba:5b:ef:cd:8a:6f:a6:3d:55:f9:84:f6:d6:b7 +# SHA1 Fingerprint: f9:b5:b6:32:45:5f:9c:be:ec:57:5f:80:dc:e9:6e:2c:c7:b2:78:b7 +# SHA256 Fingerprint: 03:76:ab:1d:54:c5:f9:80:3c:e4:b2:e2:01:a0:ee:7e:ef:7b:57:b6:36:e8:a9:3c:9b:8d:48:60:c9:6f:5f:a7 +-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE +BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz +dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL +MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp +cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP +Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr +ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL +MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1 +yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr +VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/ +nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ +KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG +XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj +vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt +Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g +N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC +nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= +-----END CERTIFICATE----- + +# Issuer: CN=AffirmTrust Networking O=AffirmTrust +# Subject: CN=AffirmTrust Networking O=AffirmTrust +# Label: "AffirmTrust Networking" +# Serial: 8957382827206547757 +# MD5 Fingerprint: 42:65:ca:be:01:9a:9a:4c:a9:8c:41:49:cd:c0:d5:7f +# SHA1 Fingerprint: 29:36:21:02:8b:20:ed:02:f5:66:c5:32:d1:d6:ed:90:9f:45:00:2f +# SHA256 Fingerprint: 0a:81:ec:5a:92:97:77:f1:45:90:4a:f3:8d:5d:50:9f:66:b5:e2:c5:8f:cd:b5:31:05:8b:0e:17:f3:f0:b4:1b +-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE +BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz +dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL +MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp +cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y +YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua +kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL +QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp +6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG +yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i +QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ +KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO +tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu +QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ +Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u +olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48 +x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= +-----END CERTIFICATE----- + +# Issuer: CN=AffirmTrust Premium O=AffirmTrust +# Subject: CN=AffirmTrust Premium O=AffirmTrust +# Label: "AffirmTrust Premium" +# Serial: 7893706540734352110 +# MD5 Fingerprint: c4:5d:0e:48:b6:ac:28:30:4e:0a:bc:f9:38:16:87:57 +# SHA1 Fingerprint: d8:a6:33:2c:e0:03:6f:b1:85:f6:63:4f:7d:6a:06:65:26:32:28:27 +# SHA256 Fingerprint: 70:a7:3f:7f:37:6b:60:07:42:48:90:45:34:b1:14:82:d5:bf:0e:69:8e:cc:49:8d:f5:25:77:eb:f2:e9:3b:9a +-----BEGIN CERTIFICATE----- +MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE +BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz +dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG +A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U +cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf +qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ +JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ ++jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS +s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5 +HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7 +70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG +V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S +qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S +5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia +C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX +OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE +FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ +BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2 +KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg +Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B +8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ +MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc +0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ +u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF +u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH +YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8 +GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO +RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e +KeC2uAloGRwYQw== +-----END CERTIFICATE----- + +# Issuer: CN=AffirmTrust Premium ECC O=AffirmTrust +# Subject: CN=AffirmTrust Premium ECC O=AffirmTrust +# Label: "AffirmTrust Premium ECC" +# Serial: 8401224907861490260 +# MD5 Fingerprint: 64:b0:09:55:cf:b1:d5:99:e2:be:13:ab:a6:5d:ea:4d +# SHA1 Fingerprint: b8:23:6b:00:2f:1d:16:86:53:01:55:6c:11:a4:37:ca:eb:ff:c3:bb +# SHA256 Fingerprint: bd:71:fd:f6:da:97:e4:cf:62:d1:64:7a:dd:25:81:b0:7d:79:ad:f8:39:7e:b4:ec:ba:9c:5e:84:88:82:14:23 +-----BEGIN CERTIFICATE----- +MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC +VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ +cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ +BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt +VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D +0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9 +ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G +A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G +A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs +aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I +flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ== +-----END CERTIFICATE----- + +# Issuer: CN=Certum Trusted Network CA O=Unizeto Technologies S.A. OU=Certum Certification Authority +# Subject: CN=Certum Trusted Network CA O=Unizeto Technologies S.A. OU=Certum Certification Authority +# Label: "Certum Trusted Network CA" +# Serial: 279744 +# MD5 Fingerprint: d5:e9:81:40:c5:18:69:fc:46:2c:89:75:62:0f:aa:78 +# SHA1 Fingerprint: 07:e0:32:e0:20:b7:2c:3f:19:2f:06:28:a2:59:3a:19:a7:0f:06:9e +# SHA256 Fingerprint: 5c:58:46:8d:55:f5:8e:49:7e:74:39:82:d2:b5:00:10:b6:d1:65:37:4a:cf:83:a7:d4:a3:2d:b7:68:c4:40:8e +-----BEGIN CERTIFICATE----- +MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBM +MSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5D +ZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBU +cnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIyMTIwNzM3WhcNMjkxMjMxMTIwNzM3 +WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMg +Uy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSIw +IAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rH +UV+rpDKmYYe2bg+G0jACl/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LM +TXPb865Px1bVWqeWifrzq2jUI4ZZJ88JJ7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVU +BBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4fOQtf/WsX+sWn7Et0brM +kUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0cvW0QM8x +AcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNV +HQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15y +sHhE49wcrwn9I0j6vSrEuVUEtRCjjSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfL +I9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1mS1FhIrlQgnXdAIv94nYmem8 +J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5ajZt3hrvJBW8qY +VoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI +03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= +-----END CERTIFICATE----- + +# Issuer: CN=TWCA Root Certification Authority O=TAIWAN-CA OU=Root CA +# Subject: CN=TWCA Root Certification Authority O=TAIWAN-CA OU=Root CA +# Label: "TWCA Root Certification Authority" +# Serial: 1 +# MD5 Fingerprint: aa:08:8f:f6:f9:7b:b7:f2:b1:a7:1e:9b:ea:ea:bd:79 +# SHA1 Fingerprint: cf:9e:87:6d:d3:eb:fc:42:26:97:a3:b5:a3:7a:a0:76:a9:06:23:48 +# SHA256 Fingerprint: bf:d8:8f:e1:10:1c:41:ae:3e:80:1b:f8:be:56:35:0e:e9:ba:d1:a6:b9:bd:51:5e:dc:5c:6d:5b:87:11:ac:44 +-----BEGIN CERTIFICATE----- +MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzES +MBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFU +V0NBIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMz +WhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJVEFJV0FO +LUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlm +aWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFE +AcK0HMMxQhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HH +K3XLfJ+utdGdIzdjp9xCoi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeX +RfwZVzsrb+RH9JlF/h3x+JejiB03HFyP4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/z +rX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1ry+UPizgN7gr8/g+YnzAx +3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkq +hkiG9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeC +MErJk/9q56YAf4lCmtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdls +XebQ79NqZp4VKIV66IIArB6nCWlWQtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62D +lhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVYT0bf+215WfKEIlKuD8z7fDvn +aspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocnyYh0igzyXxfkZ +YiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== +-----END CERTIFICATE----- + +# Issuer: O=SECOM Trust Systems CO.,LTD. OU=Security Communication RootCA2 +# Subject: O=SECOM Trust Systems CO.,LTD. OU=Security Communication RootCA2 +# Label: "Security Communication RootCA2" +# Serial: 0 +# MD5 Fingerprint: 6c:39:7d:a4:0e:55:59:b2:3f:d6:41:b1:12:50:de:43 +# SHA1 Fingerprint: 5f:3b:8c:f2:f8:10:b3:7d:78:b4:ce:ec:19:19:c3:73:34:b9:c7:74 +# SHA256 Fingerprint: 51:3b:2c:ec:b8:10:d4:cd:e5:dd:85:39:1a:df:c6:c2:dd:60:d8:7b:b7:36:d2:b5:21:48:4a:a4:7a:0e:be:f6 +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDEl +MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMe +U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoX +DTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRy +dXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3VyaXR5IENvbW11bmlj +YXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANAV +OVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGr +zbl+dp+++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVM +VAX3NuRFg3sUZdbcDE3R3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQ +hNBqyjoGADdH5H5XTz+L62e4iKrFvlNVspHEfbmwhRkGeC7bYRr6hfVKkaHnFtWO +ojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1KEOtOghY6rCcMU/Gt1SSw +awNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8QIH4D5cs +OPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3 +DQEBCwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpF +coJxDjrSzG+ntKEju/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXc +okgfGT+Ok+vx+hfuzU7jBBJV1uXk3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8 +t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6qtnRGEmyR7jTV7JqR50S+kDFy +1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29mvVXIwAHIRc/ +SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 +-----END CERTIFICATE----- + +# Issuer: CN=Actalis Authentication Root CA O=Actalis S.p.A./03358520967 +# Subject: CN=Actalis Authentication Root CA O=Actalis S.p.A./03358520967 +# Label: "Actalis Authentication Root CA" +# Serial: 6271844772424770508 +# MD5 Fingerprint: 69:c1:0d:4f:07:a3:1b:c3:fe:56:3d:04:bc:11:f6:a6 +# SHA1 Fingerprint: f3:73:b3:87:06:5a:28:84:8a:f2:f3:4a:ce:19:2b:dd:c7:8e:9c:ac +# SHA256 Fingerprint: 55:92:60:84:ec:96:3a:64:b9:6e:2a:be:01:ce:0b:a8:6a:64:fb:fe:bc:c7:aa:b5:af:c1:55:b3:7f:d7:60:66 +-----BEGIN CERTIFICATE----- +MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UE +BhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8w +MzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290 +IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDkyMjExMjIwMlowazELMAkGA1UEBhMC +SVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1 +ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENB +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNv +UTufClrJwkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX +4ay8IMKx4INRimlNAJZaby/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9 +KK3giq0itFZljoZUj5NDKd45RnijMCO6zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/ +gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1fYVEiVRvjRuPjPdA1Yprb +rxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2oxgkg4YQ +51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2F +be8lEfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxe +KF+w6D9Fz8+vm2/7hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4F +v6MGn8i1zeQf1xcGDXqVdFUNaBr8EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbn +fpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5jF66CyCU3nuDuP/jVo23Eek7 +jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLYiDrIn3hm7Ynz +ezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt +ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAL +e3KHwGCmSUyIWOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70 +jsNjLiNmsGe+b7bAEzlgqqI0JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDz +WochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKxK3JCaKygvU5a2hi/a5iB0P2avl4V +SM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+Xlff1ANATIGk0k9j +pwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC4yyX +X04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+Ok +fcvHlXHo2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7R +K4X9p2jIugErsWx0Hbhzlefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btU +ZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXemOR/qnuOf0GZvBeyqdn6/axag67XH/JJU +LysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9vwGYT7JZVEc+NHt4bVaT +LnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg== +-----END CERTIFICATE----- + +# Issuer: CN=Buypass Class 2 Root CA O=Buypass AS-983163327 +# Subject: CN=Buypass Class 2 Root CA O=Buypass AS-983163327 +# Label: "Buypass Class 2 Root CA" +# Serial: 2 +# MD5 Fingerprint: 46:a7:d2:fe:45:fb:64:5a:a8:59:90:9b:78:44:9b:29 +# SHA1 Fingerprint: 49:0a:75:74:de:87:0a:47:fe:58:ee:f6:c7:6b:eb:c6:0b:12:40:99 +# SHA256 Fingerprint: 9a:11:40:25:19:7c:5b:b9:5d:94:e6:3d:55:cd:43:79:08:47:b6:46:b2:3c:df:11:ad:a4:a0:0e:ff:15:fb:48 +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd +MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg +Q2xhc3MgMiBSb290IENBMB4XDTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1ow +TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw +HgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB +BQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1g1Lr +6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPV +L4O2fuPn9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC91 +1K2GScuVr1QGbNgGE41b/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHx +MlAQTn/0hpPshNOOvEu/XAFOBz3cFIqUCqTqc/sLUegTBxj6DvEr0VQVfTzh97QZ +QmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeffawrbD02TTqigzXsu8lkB +arcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgIzRFo1clr +Us3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLi +FRhnBkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRS +P/TizPJhk9H9Z2vXUq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN +9SG9dKpN6nIDSdvHXx1iY8f93ZHsM+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxP +AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMmAd+BikoL1Rpzz +uvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAU18h +9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s +A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3t +OluwlN5E40EIosHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo ++fsicdl9sz1Gv7SEr5AcD48Saq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7 +KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYdDnkM/crqJIByw5c/8nerQyIKx+u2 +DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWDLfJ6v9r9jv6ly0Us +H8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0oyLQ +I+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK7 +5t98biGCwWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h +3PFaTWwyI0PurKju7koSCTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPz +Y11aWOIv4x3kqdbQCtCev9eBCfHJxyYNrJgWVqA= +-----END CERTIFICATE----- + +# Issuer: CN=Buypass Class 3 Root CA O=Buypass AS-983163327 +# Subject: CN=Buypass Class 3 Root CA O=Buypass AS-983163327 +# Label: "Buypass Class 3 Root CA" +# Serial: 2 +# MD5 Fingerprint: 3d:3b:18:9e:2c:64:5a:e8:d5:88:ce:0e:f9:37:c2:ec +# SHA1 Fingerprint: da:fa:f7:fa:66:84:ec:06:8f:14:50:bd:c7:c2:81:a5:bc:a9:64:57 +# SHA256 Fingerprint: ed:f7:eb:bc:a2:7a:2a:38:4d:38:7b:7d:40:10:c6:66:e2:ed:b4:84:3e:4c:29:b4:ae:1d:5b:93:32:e6:b2:4d +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd +MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg +Q2xhc3MgMyBSb290IENBMB4XDTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFow +TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw +HgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB +BQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRHsJ8Y +ZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3E +N3coTRiR5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9 +tznDDgFHmV0ST9tD+leh7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX +0DJq1l1sDPGzbjniazEuOQAnFN44wOwZZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c +/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH2xc519woe2v1n/MuwU8X +KhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV/afmiSTY +zIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvS +O1UQRwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D +34xFMFbG02SrZvPAXpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgP +K9Dx2hzLabjKSWJtyNBjYt1gD1iqj6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3 +AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFEe4zf/lb+74suwv +Tg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAACAj +QTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV +cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXS +IGrs/CIBKM+GuIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2 +HJLw5QY33KbmkJs4j1xrG0aGQ0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsa +O5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8ZORK15FTAaggiG6cX0S5y2CBNOxv +033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2KSb12tjE8nVhz36u +dmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz6MkE +kbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg41 +3OEMXbugUZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvD +u79leNKGef9JOxqDDPDeeOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq +4/g7u9xN12TyUb7mqqta6THuBrxzvxNiCp/HuZc= +-----END CERTIFICATE----- + +# Issuer: CN=T-TeleSec GlobalRoot Class 3 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center +# Subject: CN=T-TeleSec GlobalRoot Class 3 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center +# Label: "T-TeleSec GlobalRoot Class 3" +# Serial: 1 +# MD5 Fingerprint: ca:fb:40:a8:4e:39:92:8a:1d:fe:8e:2f:c4:27:ea:ef +# SHA1 Fingerprint: 55:a6:72:3e:cb:f2:ec:cd:c3:23:74:70:19:9d:2a:be:11:e3:81:d1 +# SHA256 Fingerprint: fd:73:da:d3:1c:64:4f:f1:b4:3b:ef:0c:cd:da:96:71:0b:9c:d9:87:5e:ca:7e:31:70:7a:f3:e9:6d:52:2b:bd +-----BEGIN CERTIFICATE----- +MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx +KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd +BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl +YyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgxMDAxMTAyOTU2WhcNMzMxMDAxMjM1 +OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy +aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50 +ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN +8ELg63iIVl6bmlQdTQyK9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/ +RLyTPWGrTs0NvvAgJ1gORH8EGoel15YUNpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4 +hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZFiP0Zf3WHHx+xGwpzJFu5 +ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W0eDrXltM +EnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGj +QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1 +A/d2O2GCahKqGFPrAyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOy +WL6ukK2YJ5f+AbGwUgC4TeQbIXQbfsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ +1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzTucpH9sry9uetuUg/vBa3wW30 +6gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7hP0HHRwA11fXT +91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml +e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4p +TpPDpFQUWw== +-----END CERTIFICATE----- + +# Issuer: CN=D-TRUST Root Class 3 CA 2 2009 O=D-Trust GmbH +# Subject: CN=D-TRUST Root Class 3 CA 2 2009 O=D-Trust GmbH +# Label: "D-TRUST Root Class 3 CA 2 2009" +# Serial: 623603 +# MD5 Fingerprint: cd:e0:25:69:8d:47:ac:9c:89:35:90:f7:fd:51:3d:2f +# SHA1 Fingerprint: 58:e8:ab:b0:36:15:33:fb:80:f7:9b:1b:6d:29:d3:ff:8d:5f:00:f0 +# SHA256 Fingerprint: 49:e7:a4:42:ac:f0:ea:62:87:05:00:54:b5:25:64:b6:50:e4:f4:9e:42:e3:48:d6:aa:38:e0:39:e9:57:b1:c1 +-----BEGIN CERTIFICATE----- +MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRF +MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBD +bGFzcyAzIENBIDIgMjAwOTAeFw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NTha +ME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMM +HkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOADER03 +UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42 +tSHKXzlABF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9R +ySPocq60vFYJfxLLHLGvKZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsM +lFqVlNpQmvH/pStmMaTJOKDfHR+4CS7zp+hnUquVH+BGPtikw8paxTGA6Eian5Rp +/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUCAwEAAaOCARowggEWMA8G +A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ4PGEMA4G +A1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVj +dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUy +MENBJTIwMiUyMDIwMDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRl +cmV2b2NhdGlvbmxpc3QwQ6BBoD+GPWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3Js +L2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAwOS5jcmwwDQYJKoZIhvcNAQEL +BQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm2H6NMLVwMeni +acfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0 +o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4K +zCUqNQT4YJEVdT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8 +PIWmawomDeCTmGCufsYkl4phX5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3Y +Johw1+qRzT65ysCQblrGXnRl11z+o+I= +-----END CERTIFICATE----- + +# Issuer: CN=D-TRUST Root Class 3 CA 2 EV 2009 O=D-Trust GmbH +# Subject: CN=D-TRUST Root Class 3 CA 2 EV 2009 O=D-Trust GmbH +# Label: "D-TRUST Root Class 3 CA 2 EV 2009" +# Serial: 623604 +# MD5 Fingerprint: aa:c6:43:2c:5e:2d:cd:c4:34:c0:50:4f:11:02:4f:b6 +# SHA1 Fingerprint: 96:c9:1b:0b:95:b4:10:98:42:fa:d0:d8:22:79:fe:60:fa:b9:16:83 +# SHA256 Fingerprint: ee:c5:49:6b:98:8c:e9:86:25:b9:34:09:2e:ec:29:08:be:d0:b0:f3:16:c2:d4:73:0c:84:ea:f1:f3:d3:48:81 +-----BEGIN CERTIFICATE----- +MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRF +MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBD +bGFzcyAzIENBIDIgRVYgMjAwOTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUw +NDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNV +BAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAwOTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfSegpn +ljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM0 +3TP1YtHhzRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6Z +qQTMFexgaDbtCHu39b+T7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lR +p75mpoo6Kr3HGrHhFPC+Oh25z1uxav60sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8 +HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure3511H3a6UCAwEAAaOCASQw +ggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyvcop9Ntea +HNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFw +Oi8vZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xh +c3MlMjAzJTIwQ0ElMjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1E +RT9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0MEagRKBChkBodHRwOi8vd3d3LmQt +dHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xhc3NfM19jYV8yX2V2XzIwMDku +Y3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+PPoeUSbrh/Yp +3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05 +nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNF +CSuGdXzfX2lXANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7na +xpeG0ILD5EJt/rDiZE4OJudANCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqX +KVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVvw9y4AyHqnxbxLFS1 +-----END CERTIFICATE----- + +# Issuer: CN=CA Disig Root R2 O=Disig a.s. +# Subject: CN=CA Disig Root R2 O=Disig a.s. +# Label: "CA Disig Root R2" +# Serial: 10572350602393338211 +# MD5 Fingerprint: 26:01:fb:d8:27:a7:17:9a:45:54:38:1a:43:01:3b:03 +# SHA1 Fingerprint: b5:61:eb:ea:a4:de:e4:25:4b:69:1a:98:a5:57:47:c2:34:c7:d9:71 +# SHA256 Fingerprint: e2:3d:4a:03:6d:7b:70:e9:f5:95:b1:42:20:79:d2:b9:1e:df:bb:1f:b6:51:a0:63:3e:aa:8a:9d:c5:f8:07:03 +-----BEGIN CERTIFICATE----- +MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNV +BAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMu +MRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQy +MDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sxEzARBgNVBAcTCkJyYXRpc2xhdmEx +EzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERpc2lnIFJvb3QgUjIw +ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbCw3Oe +NcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNH +PWSb6WiaxswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3I +x2ymrdMxp7zo5eFm1tL7A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbe +QTg06ov80egEFGEtQX6sx3dOy1FU+16SGBsEWmjGycT6txOgmLcRK7fWV8x8nhfR +yyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqVg8NTEQxzHQuyRpDRQjrO +QG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa5Beny912 +H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJ +QfYEkoopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUD +i/ZnWejBBhG93c+AAk9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORs +nLMOPReisjQS1n6yqEm70XooQL6iFh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1 +rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud +DwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5uQu0wDQYJKoZI +hvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM +tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqf +GopTpti72TVVsRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkb +lvdhuDvEK7Z4bLQjb/D907JedR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka ++elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W81k/BfDxujRNt+3vrMNDcTa/F1bal +TFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjxmHHEt38OFdAlab0i +nSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01utI3 +gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18Dr +G5gPcFw0sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3Os +zMOl6W8KjptlwlCFtaOgUxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8x +L4ysEr3vQCj8KWefshNPZiTEUxnpHikV7+ZtsH8tZ/3zbBt1RqPlShfppNcL +-----END CERTIFICATE----- + +# Issuer: CN=ACCVRAIZ1 O=ACCV OU=PKIACCV +# Subject: CN=ACCVRAIZ1 O=ACCV OU=PKIACCV +# Label: "ACCVRAIZ1" +# Serial: 6828503384748696800 +# MD5 Fingerprint: d0:a0:5a:ee:05:b6:09:94:21:a1:7d:f1:b2:29:82:02 +# SHA1 Fingerprint: 93:05:7a:88:15:c6:4f:ce:88:2f:fa:91:16:52:28:78:bc:53:64:17 +# SHA256 Fingerprint: 9a:6e:c0:12:e1:a7:da:9d:be:34:19:4d:47:8a:d7:c0:db:18:22:fb:07:1d:f1:29:81:49:6e:d1:04:38:41:13 +-----BEGIN CERTIFICATE----- +MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UE +AwwJQUNDVlJBSVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQsw +CQYDVQQGEwJFUzAeFw0xMTA1MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQ +BgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwHUEtJQUNDVjENMAsGA1UECgwEQUND +VjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCb +qau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gMjmoY +HtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWo +G2ioPej0RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpA +lHPrzg5XPAOBOp0KoVdDaaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhr +IA8wKFSVf+DuzgpmndFALW4ir50awQUZ0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/ +0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDGWuzndN9wrqODJerWx5eH +k6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs78yM2x/47 +4KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMO +m3WR5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpa +cXpkatcnYGMN285J9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPl +uUsXQA+xtrn13k/c4LOsOxFwYIRKQ26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYI +KwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRwOi8vd3d3LmFjY3YuZXMvZmls +ZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEuY3J0MB8GCCsG +AQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2 +VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeT +VfZW6oHlNsyMHj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIG +CCsGAQUFBwICMIIBFB6CARAAQQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUA +cgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBhAO0AegAgAGQAZQAgAGwAYQAgAEEA +QwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUAYwBuAG8AbABvAGcA +7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBjAHQA +cgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAA +QwBQAFMAIABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUA +czAwBggrBgEFBQcCARYkaHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2Mu +aHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRt +aW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2MV9kZXIuY3JsMA4GA1Ud +DwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZIhvcNAQEF +BQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdp +D70ER9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gU +JyCpZET/LtZ1qmxNYEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+m +AM/EKXMRNt6GGT6d7hmKG9Ww7Y49nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepD +vV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJTS+xJlsndQAJxGJ3KQhfnlms +tn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3sCPdK6jT2iWH +7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h +I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szA +h1xA2syVP1XgNce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xF +d3+YJ5oyXSrjhO7FmGYvliAd3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2H +pPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3pEfbRD0tVNEYqi4Y7 +-----END CERTIFICATE----- + +# Issuer: CN=TWCA Global Root CA O=TAIWAN-CA OU=Root CA +# Subject: CN=TWCA Global Root CA O=TAIWAN-CA OU=Root CA +# Label: "TWCA Global Root CA" +# Serial: 3262 +# MD5 Fingerprint: f9:03:7e:cf:e6:9e:3c:73:7a:2a:90:07:69:ff:2b:96 +# SHA1 Fingerprint: 9c:bb:48:53:f6:a4:f6:d3:52:a4:e8:32:52:55:60:13:f5:ad:af:65 +# SHA256 Fingerprint: 59:76:90:07:f7:68:5d:0f:cd:50:87:2f:9f:95:d5:75:5a:5b:2b:45:7d:81:f3:69:2b:61:0a:98:67:2f:0e:1b +-----BEGIN CERTIFICATE----- +MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcx +EjAQBgNVBAoTCVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMT +VFdDQSBHbG9iYWwgUm9vdCBDQTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5 +NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQKEwlUQUlXQU4tQ0ExEDAOBgNVBAsT +B1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3QgQ0EwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2CnJfF +10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz +0ALfUPZVr2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfCh +MBwqoJimFb3u/Rk28OKRQ4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbH +zIh1HrtsBv+baz4X7GGqcXzGHaL3SekVtTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc +46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1WKKD+u4ZqyPpcC1jcxkt2 +yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99sy2sbZCi +laLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYP +oA/pyJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQA +BDzfuBSO6N+pjWxnkjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcE +qYSjMq+u7msXi7Kx/mzhkIyIqJdIzshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm +4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB +/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6gcFGn90xHNcgL +1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn +LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WF +H6vPNOw/KP4M8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNo +RI2T9GRwoD2dKAXDOXC4Ynsg/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+ +nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlglPx4mI88k1HtQJAH32RjJMtOcQWh +15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryPA9gK8kxkRr05YuWW +6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3mi4TW +nsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5j +wa19hAM8EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWz +aGHQRiapIVJpLesux+t3zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmy +KwbQBM0= +-----END CERTIFICATE----- + +# Issuer: CN=TeliaSonera Root CA v1 O=TeliaSonera +# Subject: CN=TeliaSonera Root CA v1 O=TeliaSonera +# Label: "TeliaSonera Root CA v1" +# Serial: 199041966741090107964904287217786801558 +# MD5 Fingerprint: 37:41:49:1b:18:56:9a:26:f5:ad:c2:66:fb:40:a5:4c +# SHA1 Fingerprint: 43:13:bb:96:f1:d5:86:9b:c1:4e:6a:92:f6:cf:f6:34:69:87:82:37 +# SHA256 Fingerprint: dd:69:36:fe:21:f8:f0:77:c1:23:a1:a5:21:c1:22:24:f7:22:55:b7:3e:03:a7:26:06:93:e8:a2:4b:0f:a3:89 +-----BEGIN CERTIFICATE----- +MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAw +NzEUMBIGA1UECgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJv +b3QgQ0EgdjEwHhcNMDcxMDE4MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYD +VQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwWVGVsaWFTb25lcmEgUm9vdCBDQSB2 +MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+6yfwIaPzaSZVfp3F +VRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA3GV1 +7CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+X +Z75Ljo1kB1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+ +/jXh7VB7qTCNGdMJjmhnXb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs +81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxHoLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkm +dtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3F0fUTPHSiXk+TT2YqGHe +Oh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJoWjiUIMu +sDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4 +pgd7gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fs +slESl1MpWtTwEhDcTwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQ +arMCpgKIv7NHfirZ1fpoeDVNAgMBAAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYD +VR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qWDNXr+nuqF+gTEjANBgkqhkiG +9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNmzqjMDfz1mgbl +dxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx +0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1Tj +TQpgcmLNkQfWpb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBed +Y2gea+zDTYa4EzAvXUYNR0PVG6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7 +Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpcc41teyWRyu5FrgZLAMzTsVlQ2jqI +OylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOTJsjrDNYmiLbAJM+7 +vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2qReW +t88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcn +HL/EVlP6Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVx +SK236thZiNSQvxaz2emsWWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY= +-----END CERTIFICATE----- + +# Issuer: CN=T-TeleSec GlobalRoot Class 2 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center +# Subject: CN=T-TeleSec GlobalRoot Class 2 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center +# Label: "T-TeleSec GlobalRoot Class 2" +# Serial: 1 +# MD5 Fingerprint: 2b:9b:9e:e4:7b:6c:1f:00:72:1a:cc:c1:77:79:df:6a +# SHA1 Fingerprint: 59:0d:2d:7d:88:4f:40:2e:61:7e:a5:62:32:17:65:cf:17:d8:94:e9 +# SHA256 Fingerprint: 91:e2:f5:78:8d:58:10:eb:a7:ba:58:73:7d:e1:54:8a:8e:ca:cd:01:45:98:bc:0b:14:3e:04:1b:17:05:25:52 +-----BEGIN CERTIFICATE----- +MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx +KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd +BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl +YyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgxMDAxMTA0MDE0WhcNMzMxMDAxMjM1 +OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy +aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50 +ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUd +AqSzm1nzHoqvNK38DcLZSBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiC +FoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/FvudocP05l03Sx5iRUKrERLMjfTlH6VJi +1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx9702cu+fjOlbpSD8DT6Iavq +jnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGVWOHAD3bZ +wI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGj +QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/ +WSA2AHmgoCJrjNXyYdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhy +NsZt+U2e+iKo4YFWz827n+qrkRk4r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPAC +uvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNfvNoBYimipidx5joifsFvHZVw +IEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR3p1m0IvVVGb6 +g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN +9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlP +BSeOE6Fuwg== +-----END CERTIFICATE----- + +# Issuer: CN=Atos TrustedRoot 2011 O=Atos +# Subject: CN=Atos TrustedRoot 2011 O=Atos +# Label: "Atos TrustedRoot 2011" +# Serial: 6643877497813316402 +# MD5 Fingerprint: ae:b9:c4:32:4b:ac:7f:5d:66:cc:77:94:bb:2a:77:56 +# SHA1 Fingerprint: 2b:b1:f5:3e:55:0c:1d:c5:f1:d4:e6:b7:6a:46:4b:55:06:02:ac:21 +# SHA256 Fingerprint: f3:56:be:a2:44:b7:a9:1e:b3:5d:53:ca:9a:d7:86:4a:ce:01:8e:2d:35:d5:f8:f9:6d:df:68:a6:f4:1a:a4:74 +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UE +AwwVQXRvcyBUcnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQG +EwJERTAeFw0xMTA3MDcxNDU4MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMM +FUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMC +REUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVhTuXbyo7LjvPpvMp +Nb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr54rM +VD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+ +SZFhyBH+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ +4J7sVaE3IqKHBAUsR320HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0L +cp2AMBYHlT8oDv3FdU9T1nSatCQujgKRz3bFmx5VdJx4IbHwLfELn8LVlhgf8FQi +eowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7Rl+lwrrw7GWzbITAPBgNV +HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZbNshMBgG +A1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3 +DQEBCwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8j +vZfza1zv7v1Apt+hk6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kP +DpFrdRbhIfzYJsdHt6bPWHJxfrrhTZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pc +maHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a961qn8FYiqTxlVMYVqL2Gns2D +lmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G3mB/ufNPRJLv +KrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed +-----END CERTIFICATE----- + +# Issuer: CN=QuoVadis Root CA 1 G3 O=QuoVadis Limited +# Subject: CN=QuoVadis Root CA 1 G3 O=QuoVadis Limited +# Label: "QuoVadis Root CA 1 G3" +# Serial: 687049649626669250736271037606554624078720034195 +# MD5 Fingerprint: a4:bc:5b:3f:fe:37:9a:fa:64:f0:e2:fa:05:3d:0b:ab +# SHA1 Fingerprint: 1b:8e:ea:57:96:29:1a:c9:39:ea:b8:0a:81:1a:73:73:c0:93:79:67 +# SHA256 Fingerprint: 8a:86:6f:d1:b2:76:b5:7e:57:8e:92:1c:65:82:8a:2b:ed:58:e9:f2:f2:88:05:41:34:b7:f1:f4:bf:c9:cc:74 +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQEL +BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc +BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00 +MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEgRzMwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakEPBtV +wedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWe +rNrwU8lmPNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF341 +68Xfuw6cwI2H44g4hWf6Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh +4Pw5qlPafX7PGglTvF0FBM+hSo+LdoINofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXp +UhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/lg6AnhF4EwfWQvTA9xO+o +abw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV7qJZjqlc +3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/G +KubX9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSt +hfbZxbGL0eUQMk1fiyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KO +Tk0k+17kBL5yG6YnLUlamXrXXAkgt3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOt +zCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZIhvcNAQELBQAD +ggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC +MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2 +cDMT/uFPpiN3GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUN +qXsCHKnQO18LwIE6PWThv6ctTr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5 +YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP+V04ikkwj+3x6xn0dxoxGE1nVGwv +b2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh3jRJjehZrJ3ydlo2 +8hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fawx/k +NSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNj +ZgKAvQU6O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhp +q1467HxpvMc7hU6eFbm0FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFt +nh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOVhMJKzRwuJIczYOXD +-----END CERTIFICATE----- + +# Issuer: CN=QuoVadis Root CA 2 G3 O=QuoVadis Limited +# Subject: CN=QuoVadis Root CA 2 G3 O=QuoVadis Limited +# Label: "QuoVadis Root CA 2 G3" +# Serial: 390156079458959257446133169266079962026824725800 +# MD5 Fingerprint: af:0c:86:6e:bf:40:2d:7f:0b:3e:12:50:ba:12:3d:06 +# SHA1 Fingerprint: 09:3c:61:f3:8b:8b:dc:7d:55:df:75:38:02:05:00:e1:25:f5:c8:36 +# SHA256 Fingerprint: 8f:e4:fb:0a:f9:3a:4d:0d:67:db:0b:eb:b2:3e:37:c7:1b:f3:25:dc:bc:dd:24:0e:a0:4d:af:58:b4:7e:18:40 +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQEL +BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc +BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00 +MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIgRzMwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFhZiFf +qq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMW +n4rjyduYNM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ym +c5GQYaYDFCDy54ejiK2toIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+ +O7q414AB+6XrW7PFXmAqMaCvN+ggOp+oMiwMzAkd056OXbxMmO7FGmh77FOm6RQ1 +o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+lV0POKa2Mq1W/xPtbAd0j +IaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZoL1NesNKq +IcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz +8eQQsSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43eh +vNURG3YBZwjgQQvD6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l +7ZizlWNof/k19N+IxWA1ksB8aRxhlRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALG +cC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZIhvcNAQELBQAD +ggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66 +AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RC +roijQ1h5fq7KpVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0Ga +W/ZZGYjeVYg3UQt4XAoeo0L9x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4n +lv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgzdWqTHBLmYF5vHX/JHyPLhGGfHoJE ++V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6XU/IyAgkwo1jwDQHV +csaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+NwmNtd +dbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNg +KCLjsZWDzYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeM +HVOyToV7BjjHLPj4sHKNJeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4 +WSr2Rz0ZiC3oheGe7IUIarFsNMkd7EgrO3jtZsSOeWmD3n+M +-----END CERTIFICATE----- + +# Issuer: CN=QuoVadis Root CA 3 G3 O=QuoVadis Limited +# Subject: CN=QuoVadis Root CA 3 G3 O=QuoVadis Limited +# Label: "QuoVadis Root CA 3 G3" +# Serial: 268090761170461462463995952157327242137089239581 +# MD5 Fingerprint: df:7d:b9:ad:54:6f:68:a1:df:89:57:03:97:43:b0:d7 +# SHA1 Fingerprint: 48:12:bd:92:3c:a8:c4:39:06:e7:30:6d:27:96:e6:a4:cf:22:2e:7d +# SHA256 Fingerprint: 88:ef:81:de:20:2e:b0:18:45:2e:43:f8:64:72:5c:ea:5f:bd:1f:c2:d9:d2:05:73:07:09:c5:d8:b8:69:0f:46 +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQEL +BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc +BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00 +MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMgRzMwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286IxSR +/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNu +FoM7pmRLMon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXR +U7Ox7sWTaYI+FrUoRqHe6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+c +ra1AdHkrAj80//ogaX3T7mH1urPnMNA3I4ZyYUUpSFlob3emLoG+B01vr87ERROR +FHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3UVDmrJqMz6nWB2i3ND0/k +A9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f75li59wzw +eyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634Ryl +sSqiMd5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBp +VzgeAVuNVejH38DMdyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0Q +A4XN8f+MFrXBsj6IbGB/kE+V9/YtrQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ +ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZIhvcNAQELBQAD +ggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px +KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnI +FUBhynLWcKzSt/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5Wvv +oxXqA/4Ti2Tk08HS6IT7SdEQTXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFg +u/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9DuDcpmvJRPpq3t/O5jrFc/ZSXPsoaP +0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGibIh6BJpsQBJFxwAYf +3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmDhPbl +8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+ +DhcI00iX0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HN +PlopNLk9hM6xZdRZkZFWdSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ +ywaZWWDYWGWVjUTR939+J399roD1B0y2PpxxVJkES/1Y+Zj0 +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert Assured ID Root G2 O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert Assured ID Root G2 O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert Assured ID Root G2" +# Serial: 15385348160840213938643033620894905419 +# MD5 Fingerprint: 92:38:b9:f8:63:24:82:65:2c:57:33:e6:fe:81:8f:9d +# SHA1 Fingerprint: a1:4b:48:d9:43:ee:0a:0e:40:90:4f:3c:e0:a4:c0:91:93:51:5d:3f +# SHA256 Fingerprint: 7d:05:eb:b6:82:33:9f:8c:94:51:ee:09:4e:eb:fe:fa:79:53:a1:14:ed:b2:f4:49:49:45:2f:ab:7d:2f:c1:85 +-----BEGIN CERTIFICATE----- +MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBl +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv +b3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl +cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSA +n61UQbVH35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4Htecc +biJVMWWXvdMX0h5i89vqbFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9Hp +EgjAALAcKxHad3A2m67OeYfcgnDmCXRwVWmvo2ifv922ebPynXApVfSr/5Vh88lA +bx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OPYLfykqGxvYmJHzDNw6Yu +YjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+RnlTGNAgMB +AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQW +BBTOw0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPI +QW5pJ6d1Ee88hjZv0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I +0jJmwYrA8y8678Dj1JGG0VDjA9tzd29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4Gni +lmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAWhsI6yLETcDbYz+70CjTVW0z9 +B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0MjomZmWzwPDCv +ON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo +IhNzbM8m9Yop5w== +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert Assured ID Root G3 O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert Assured ID Root G3 O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert Assured ID Root G3" +# Serial: 15459312981008553731928384953135426796 +# MD5 Fingerprint: 7c:7f:65:31:0c:81:df:8d:ba:3e:99:e2:5c:ad:6e:fb +# SHA1 Fingerprint: f5:17:a2:4f:9a:48:c6:c9:f8:a2:00:26:9f:dc:0f:48:2c:ab:30:89 +# SHA256 Fingerprint: 7e:37:cb:8b:4c:47:09:0c:ab:36:55:1b:a6:f4:5d:b8:40:68:0f:ba:16:6a:95:2d:b1:00:71:7f:43:05:3f:c2 +-----BEGIN CERTIFICATE----- +MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQsw +CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu +ZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3Qg +RzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQGEwJV +UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu +Y29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQBgcq +hkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJf +Zn4f5dwbRXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17Q +RSAPWXYQ1qAk8C3eNvJsKTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ +BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgFUaFNN6KDec6NHSrkhDAKBggqhkjOPQQD +AwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5FyYZ5eEJJZVrmDxxDnOOlY +JjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy1vUhZscv +6pZjamVFkpUBtA== +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert Global Root G2 O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert Global Root G2 O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert Global Root G2" +# Serial: 4293743540046975378534879503202253541 +# MD5 Fingerprint: e4:a6:8a:c8:54:ac:52:42:46:0a:fd:72:48:1b:2a:44 +# SHA1 Fingerprint: df:3c:24:f9:bf:d6:66:76:1b:26:80:73:fe:06:d1:cc:8d:4f:82:a4 +# SHA256 Fingerprint: cb:3c:cb:b7:60:31:e5:e0:13:8f:8d:d3:9a:23:f9:de:47:ff:c3:5e:43:c1:14:4c:ea:27:d4:6a:5a:b1:cb:5f +-----BEGIN CERTIFICATE----- +MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH +MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT +MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j +b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI +2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx +1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ +q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz +tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ +vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP +BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV +5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY +1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4 +NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG +Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91 +8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe +pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl +MrY= +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert Global Root G3 O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert Global Root G3 O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert Global Root G3" +# Serial: 7089244469030293291760083333884364146 +# MD5 Fingerprint: f5:5d:a4:50:a5:fb:28:7e:1e:0f:0d:cc:96:57:56:ca +# SHA1 Fingerprint: 7e:04:de:89:6a:3e:66:6d:00:e6:87:d3:3f:fa:d9:3b:e8:3d:34:9e +# SHA256 Fingerprint: 31:ad:66:48:f8:10:41:38:c7:38:f3:9e:a4:32:01:33:39:3e:3a:18:cc:02:29:6e:f9:7c:2a:c9:ef:67:31:d0 +-----BEGIN CERTIFICATE----- +MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQsw +CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu +ZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAe +Fw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVTMRUw +EwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20x +IDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0CAQYF +K4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FG +fp4tn+6OYwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPO +Z9wj/wMco+I+o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAd +BgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNpYim8S8YwCgYIKoZIzj0EAwMDaAAwZQIx +AK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y3maTD/HMsQmP3Wyr+mt/ +oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34VOKa5Vt8 +sycX +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert Trusted Root G4 O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert Trusted Root G4 O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert Trusted Root G4" +# Serial: 7451500558977370777930084869016614236 +# MD5 Fingerprint: 78:f2:fc:aa:60:1f:2f:b4:eb:c9:37:ba:53:2e:75:49 +# SHA1 Fingerprint: dd:fb:16:cd:49:31:c9:73:a2:03:7d:3f:c8:3a:4d:7d:77:5d:05:e4 +# SHA256 Fingerprint: 55:2f:7b:dc:f1:a7:af:9e:6c:e6:72:01:7f:4f:12:ab:f7:72:40:c7:8e:76:1a:c2:03:d1:d9:d2:0a:c8:99:88 +-----BEGIN CERTIFICATE----- +MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBi +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3Qg +RzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBiMQswCQYDVQQGEwJV +UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu +Y29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3y +ithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1If +xp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDV +ySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfISKhmV1efVFiO +DCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jHtrHEtWoYOAMQ +jdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6MUSaM0C/ +CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCi +EhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADM +fRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QY +uKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXK +chYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4KJpn15GkvmB0t +9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +hjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD +ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2 +SV1EY+CtnJYYZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd ++SeuMIW59mdNOj6PWTkiU0TryF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWc +fFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy7zBZLq7gcfJW5GqXb5JQbZaNaHqa +sjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iahixTXTBmyUEFxPT9N +cCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN5r5N +0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie +4u1Ki7wb/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mI +r/OSmbaz5mEP0oUA51Aa5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1 +/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tKG48BtieVU+i2iW1bvGjUI+iLUaJW+fCm +gKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP82Z+ +-----END CERTIFICATE----- + +# Issuer: CN=COMODO RSA Certification Authority O=COMODO CA Limited +# Subject: CN=COMODO RSA Certification Authority O=COMODO CA Limited +# Label: "COMODO RSA Certification Authority" +# Serial: 101909084537582093308941363524873193117 +# MD5 Fingerprint: 1b:31:b0:71:40:36:cc:14:36:91:ad:c4:3e:fd:ec:18 +# SHA1 Fingerprint: af:e5:d2:44:a8:d1:19:42:30:ff:47:9f:e2:f8:97:bb:cd:7a:8c:b4 +# SHA256 Fingerprint: 52:f0:e1:c4:e5:8e:c6:29:29:1b:60:31:7f:07:46:71:b8:5d:7e:a8:0d:5b:07:27:34:63:53:4b:32:b4:02:34 +-----BEGIN CERTIFICATE----- +MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCB +hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G +A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV +BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMTE5 +MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgT +EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR +Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR +6FSS0gpWsawNJN3Fz0RndJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8X +pz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZFGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC +9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+5eNu/Nio5JIk2kNrYrhV +/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pGx8cgoLEf +Zd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z ++pUX2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7w +qP/0uK3pN/u6uPQLOvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZah +SL0896+1DSJMwBGB7FY79tOi4lu3sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVIC +u9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+CGCe01a60y1Dma/RMhnEw6abf +Fobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5WdYgGq/yapiq +crxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E +FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB +/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvl +wFTPoCWOAvn9sKIN9SCYPBMtrFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM +4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+nq6PK7o9mfjYcwlYRm6mnPTXJ9OV +2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSgtZx8jb8uk2Intzna +FxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwWsRqZ +CuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiK +boHGhfKppC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmcke +jkk9u+UJueBPSZI9FoJAzMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yL +S0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHqZJx64SIDqZxubw5lT2yHh17zbqD5daWb +QOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk527RH89elWsn2/x20Kk4yl +0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7ILaZRfyHB +NVOFBkpdn627G190 +-----END CERTIFICATE----- + +# Issuer: CN=USERTrust RSA Certification Authority O=The USERTRUST Network +# Subject: CN=USERTrust RSA Certification Authority O=The USERTRUST Network +# Label: "USERTrust RSA Certification Authority" +# Serial: 2645093764781058787591871645665788717 +# MD5 Fingerprint: 1b:fe:69:d1:91:b7:19:33:a3:72:a8:0f:e1:55:e5:b5 +# SHA1 Fingerprint: 2b:8f:1b:57:33:0d:bb:a2:d0:7a:6c:51:f7:0e:e9:0d:da:b9:ad:8e +# SHA256 Fingerprint: e7:93:c9:b0:2f:d8:aa:13:e2:1c:31:22:8a:cc:b0:81:19:64:3b:74:9c:89:89:64:b1:74:6d:46:c3:d4:cb:d2 +-----BEGIN CERTIFICATE----- +MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB +iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl +cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV +BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAw +MjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNV +BAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU +aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2Vy +dGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK +AoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B +3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR+OJv0OwWIJAJPuLodMkY +tJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFnRghRy4YUVD+8M/5+bJz/ +Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O+T23LLb2 +VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT +79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6 +c0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmT +Yo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97l +c6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexDJtC/QV9AqURE9JnnV4ee +UB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+eLf8ZxXhyVeE +Hg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd +BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8G +A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPF +Up/L+M+ZBn8b2kMVn54CVVeWFPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KO +VWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ7l8wXEskEVX/JJpuXior7gtNn3/3 +ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQEg9zKC7F4iRO/Fjs +8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM8WcR +iQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYze +Sf7dNXGiFSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZ +XHlKYC6SQK5MNyosycdiyA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/ +qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9cJ2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRB +VXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGwsAvgnEzDHNb842m1R0aB +L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG +jjxDah2nGN59PRbxYvnKkKj9 +-----END CERTIFICATE----- + +# Issuer: CN=USERTrust ECC Certification Authority O=The USERTRUST Network +# Subject: CN=USERTrust ECC Certification Authority O=The USERTRUST Network +# Label: "USERTrust ECC Certification Authority" +# Serial: 123013823720199481456569720443997572134 +# MD5 Fingerprint: fa:68:bc:d9:b5:7f:ad:fd:c9:1d:06:83:28:cc:24:c1 +# SHA1 Fingerprint: d1:cb:ca:5d:b2:d5:2a:7f:69:3b:67:4d:e5:f0:5a:1d:0c:95:7d:f0 +# SHA256 Fingerprint: 4f:f4:60:d5:4b:9c:86:da:bf:bc:fc:57:12:e0:40:0d:2b:ed:3f:bc:4d:4f:bd:aa:86:e0:6a:dc:d2:a9:ad:7a +-----BEGIN CERTIFICATE----- +MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDEL +MAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNl +eSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMT +JVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMjAx +MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT +Ck5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUg +VVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlm +aWNhdGlvbiBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqflo +I+d61SRvU8Za2EurxtW20eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinng +o4N+LZfQYcTxmdwlkWOrfzCjtHDix6EznPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0G +A1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNVHQ8BAf8EBAMCAQYwDwYD +VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBBHU6+4WMB +zzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbW +RNZu9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg= +-----END CERTIFICATE----- + +# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R5 +# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R5 +# Label: "GlobalSign ECC Root CA - R5" +# Serial: 32785792099990507226680698011560947931244 +# MD5 Fingerprint: 9f:ad:3b:1c:02:1e:8a:ba:17:74:38:81:0c:a2:bc:08 +# SHA1 Fingerprint: 1f:24:c6:30:cd:a4:18:ef:20:69:ff:ad:4f:dd:5f:46:3a:1b:69:aa +# SHA256 Fingerprint: 17:9f:bc:14:8a:3d:d0:0f:d2:4e:a1:34:58:cc:43:bf:a7:f5:9c:81:82:d7:83:a5:13:f6:eb:ec:10:0c:89:24 +-----BEGIN CERTIFICATE----- +MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEk +MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpH +bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX +DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD +QSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu +MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6SFkc +8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8ke +hOvRnkmSh5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD +VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYI +KoZIzj0EAwMDaAAwZQIxAOVpEslu28YxuglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg +515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7yFz9SO8NdCKoCOJuxUnO +xwy8p2Fp8fc74SrL+SvzZpA3 +-----END CERTIFICATE----- + +# Issuer: CN=IdenTrust Commercial Root CA 1 O=IdenTrust +# Subject: CN=IdenTrust Commercial Root CA 1 O=IdenTrust +# Label: "IdenTrust Commercial Root CA 1" +# Serial: 13298821034946342390520003877796839426 +# MD5 Fingerprint: b3:3e:77:73:75:ee:a0:d3:e3:7e:49:63:49:59:bb:c7 +# SHA1 Fingerprint: df:71:7e:aa:4a:d9:4e:c9:55:84:99:60:2d:48:de:5f:bc:f0:3a:25 +# SHA256 Fingerprint: 5d:56:49:9b:e4:d2:e0:8b:cf:ca:d0:8a:3e:38:72:3d:50:50:3b:de:70:69:48:e4:2f:55:60:30:19:e5:28:ae +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBK +MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVu +VHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQw +MTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScw +JQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ldhNlT +3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU ++ehcCuz/mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gp +S0l4PJNgiCL8mdo2yMKi1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1 +bVoE/c40yiTcdCMbXTMTEl3EASX2MN0CXZ/g1Ue9tOsbobtJSdifWwLziuQkkORi +T0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl3ZBWzvurpWCdxJ35UrCL +vYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzyNeVJSQjK +Vsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZK +dHzVWYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHT +c+XvvqDtMwt0viAgxGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hv +l7yTmvmcEpB4eoCHFddydJxVdHixuuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5N +iGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB +/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZIhvcNAQELBQAD +ggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH +6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwt +LRvM7Kqas6pgghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93 +nAbowacYXVKV7cndJZ5t+qntozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3 ++wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmVYjzlVYA211QC//G5Xc7UI2/YRYRK +W2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUXfeu+h1sXIFRRk0pT +AwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/rokTLq +l1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG +4iZZRHUe2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZ +mUlO+KWA2yUPHGNiiskzZ2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A +7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7RcGzM7vRX+Bi6hG6H +-----END CERTIFICATE----- + +# Issuer: CN=IdenTrust Public Sector Root CA 1 O=IdenTrust +# Subject: CN=IdenTrust Public Sector Root CA 1 O=IdenTrust +# Label: "IdenTrust Public Sector Root CA 1" +# Serial: 13298821034946342390521976156843933698 +# MD5 Fingerprint: 37:06:a5:b0:fc:89:9d:ba:f4:6b:8c:1a:64:cd:d5:ba +# SHA1 Fingerprint: ba:29:41:60:77:98:3f:f4:f3:ef:f2:31:05:3b:2e:ea:6d:4d:45:fd +# SHA256 Fingerprint: 30:d0:89:5a:9a:44:8a:26:20:91:63:55:22:d1:f5:20:10:b5:86:7a:ca:e1:2c:78:ef:95:8f:d4:f4:38:9f:2f +-----BEGIN CERTIFICATE----- +MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBN +MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVu +VHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcN +MzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0 +MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTyP4o7 +ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGy +RBb06tD6Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlS +bdsHyo+1W/CD80/HLaXIrcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF +/YTLNiCBWS2ab21ISGHKTN9T0a9SvESfqy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R +3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoSmJxZZoY+rfGwyj4GD3vw +EUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFnol57plzy +9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9V +GxyhLrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ +2fjXctscvG29ZV/viDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsV +WaFHVCkugyhfHMKiq3IXAAaOReyL4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gD +W/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ +BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMwDQYJKoZIhvcN +AQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj +t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHV +DRDtfULAj+7AmgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9 +TaDKQGXSc3z1i9kKlT/YPyNtGtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8G +lwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFtm6/n6J91eEyrRjuazr8FGF1NFTwW +mhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMxNRF4eKLg6TCMf4Df +WN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4Mhn5 ++bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJ +tshquDDIajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhA +GaQdp/lLQzfcaFpPz+vCZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv +8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ3Wl9af0AVqW3rLatt8o+Ae+c +-----END CERTIFICATE----- + +# Issuer: CN=Entrust Root Certification Authority - G2 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2009 Entrust, Inc. - for authorized use only +# Subject: CN=Entrust Root Certification Authority - G2 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2009 Entrust, Inc. - for authorized use only +# Label: "Entrust Root Certification Authority - G2" +# Serial: 1246989352 +# MD5 Fingerprint: 4b:e2:c9:91:96:65:0c:f4:0e:5a:93:92:a0:0a:fe:b2 +# SHA1 Fingerprint: 8c:f4:27:fd:79:0c:3a:d1:66:06:8d:e8:1e:57:ef:bb:93:22:72:d4 +# SHA256 Fingerprint: 43:df:57:74:b0:3e:7f:ef:5f:e4:0d:93:1a:7b:ed:f1:bb:2e:6b:42:73:8c:4e:6d:38:41:10:3d:3a:a7:f3:39 +-----BEGIN CERTIFICATE----- +MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMC +VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50 +cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3Qs +IEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVz +dCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwHhcNMDkwNzA3MTcy +NTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUVu +dHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwt +dGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0 +aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5IC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP/vaCeb9zYQYKpSfYs1/T +RU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXzHHfV1IWN +cCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hW +wcKUs/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1 +U1+cPvQXLOZprE4yTGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0 +jaWvYkxN4FisZDQSA/i2jZRjJKRxAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAP +BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ60B7vfec7aVHUbI2fkBJmqzAN +BgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5ZiXMRrEPR9RP/ +jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ +Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v +1fN2D807iDginWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4R +nAuknZoh8/CbCzB428Hch0P+vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmH +VHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xOe4pIb4tF9g== +-----END CERTIFICATE----- + +# Issuer: CN=Entrust Root Certification Authority - EC1 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2012 Entrust, Inc. - for authorized use only +# Subject: CN=Entrust Root Certification Authority - EC1 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2012 Entrust, Inc. - for authorized use only +# Label: "Entrust Root Certification Authority - EC1" +# Serial: 51543124481930649114116133369 +# MD5 Fingerprint: b6:7e:1d:f0:58:c5:49:6c:24:3b:3d:ed:98:18:ed:bc +# SHA1 Fingerprint: 20:d8:06:40:df:9b:25:f5:12:25:3a:11:ea:f7:59:8a:eb:14:b5:47 +# SHA256 Fingerprint: 02:ed:0e:b2:8c:14:da:45:16:5c:56:67:91:70:0d:64:51:d7:fb:56:f0:b2:ab:1d:3b:8e:b0:70:e5:6e:df:f5 +-----BEGIN CERTIFICATE----- +MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkG +A1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3 +d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVu +dHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEzMDEGA1UEAxMq +RW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRUMxMB4XDTEy +MTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYwFAYD +VQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0 +L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0g +Zm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBD +ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEVDMTB2MBAGByqGSM49AgEGBSuBBAAi +A2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHyAsWfoPZb1YsGGYZPUxBt +ByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef9eNi1KlH +Bz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O +BBYEFLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVC +R98crlOZF7ZvHH3hvxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nX +hTcGtXsI/esni0qU+eH6p44mCOh8kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G +-----END CERTIFICATE----- + +# Issuer: CN=CFCA EV ROOT O=China Financial Certification Authority +# Subject: CN=CFCA EV ROOT O=China Financial Certification Authority +# Label: "CFCA EV ROOT" +# Serial: 407555286 +# MD5 Fingerprint: 74:e1:b6:ed:26:7a:7a:44:30:33:94:ab:7b:27:81:30 +# SHA1 Fingerprint: e2:b8:29:4b:55:84:ab:6b:58:c2:90:46:6c:ac:3f:b8:39:8f:84:83 +# SHA256 Fingerprint: 5c:c3:d7:8e:4e:1d:5e:45:54:7a:04:e6:87:3e:64:f9:0c:f9:53:6d:1c:cc:2e:f8:00:f3:55:c4:c5:fd:70:fd +-----BEGIN CERTIFICATE----- +MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJD +TjEwMC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9y +aXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkx +MjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEwMC4GA1UECgwnQ2hpbmEgRmluYW5j +aWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJP +T1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnVBU03 +sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpL +TIpTUnrD7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5 +/ZOkVIBMUtRSqy5J35DNuF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp +7hZZLDRJGqgG16iI0gNyejLi6mhNbiyWZXvKWfry4t3uMCz7zEasxGPrb382KzRz +EpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7xzbh72fROdOXW3NiGUgt +hxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9fpy25IGvP +a931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqot +aK8KgWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNg +TnYGmE69g60dWIolhdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfV +PKPtl8MeNPo4+QgO48BdK4PRVmrJtqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hv +cWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAfBgNVHSMEGDAWgBTj/i39KNAL +tbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAd +BgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB +ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObT +ej/tUxPQ4i9qecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdL +jOztUmCypAbqTuv0axn96/Ua4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBS +ESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sGE5uPhnEFtC+NiWYzKXZUmhH4J/qy +P5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfXBDrDMlI1Dlb4pd19 +xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjnaH9d +Ci77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN +5mydLIhyPDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe +/v5WOaHIz16eGWRGENoXkbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+Z +AAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3CekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ +5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su +-----END CERTIFICATE----- + +# Issuer: CN=OISTE WISeKey Global Root GB CA O=WISeKey OU=OISTE Foundation Endorsed +# Subject: CN=OISTE WISeKey Global Root GB CA O=WISeKey OU=OISTE Foundation Endorsed +# Label: "OISTE WISeKey Global Root GB CA" +# Serial: 157768595616588414422159278966750757568 +# MD5 Fingerprint: a4:eb:b9:61:28:2e:b7:2f:98:b0:35:26:90:99:51:1d +# SHA1 Fingerprint: 0f:f9:40:76:18:d3:d7:6a:4b:98:f0:a8:35:9e:0c:fd:27:ac:cc:ed +# SHA256 Fingerprint: 6b:9c:08:e8:6e:b0:f7:67:cf:ad:65:cd:98:b6:21:49:e5:49:4a:67:f5:84:5e:7b:d1:ed:01:9f:27:b8:6b:d6 +-----BEGIN CERTIFICATE----- +MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBt +MQswCQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUg +Rm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9i +YWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAwMzJaFw0zOTEyMDExNTEwMzFaMG0x +CzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBG +b3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh +bCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3 +HEokKtaXscriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGx +WuR51jIjK+FTzJlFXHtPrby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX +1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNk +u7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4oQnc/nSMbsrY9gBQHTC5P +99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvgGUpuuy9r +M2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUB +BAMCAQAwDQYJKoZIhvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrgh +cViXfa43FK8+5/ea4n32cZiZBKpDdHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5 +gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0VQreUGdNZtGn//3ZwLWoo4rO +ZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEuiHZeeevJuQHHf +aPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic +Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM= +-----END CERTIFICATE----- + +# Issuer: CN=SZAFIR ROOT CA2 O=Krajowa Izba Rozliczeniowa S.A. +# Subject: CN=SZAFIR ROOT CA2 O=Krajowa Izba Rozliczeniowa S.A. +# Label: "SZAFIR ROOT CA2" +# Serial: 357043034767186914217277344587386743377558296292 +# MD5 Fingerprint: 11:64:c1:89:b0:24:b1:8c:b1:07:7e:89:9e:51:9e:99 +# SHA1 Fingerprint: e2:52:fa:95:3f:ed:db:24:60:bd:6e:28:f3:9c:cc:cf:5e:b3:3f:de +# SHA256 Fingerprint: a1:33:9d:33:28:1a:0b:56:e5:57:d3:d3:2b:1c:e7:f9:36:7e:b0:94:bd:5f:a7:2a:7e:50:04:c8:de:d7:ca:fe +-----BEGIN CERTIFICATE----- +MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQEL +BQAwUTELMAkGA1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6 +ZW5pb3dhIFMuQS4xGDAWBgNVBAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkw +NzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJBgNVBAYTAlBMMSgwJgYDVQQKDB9L +cmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYDVQQDDA9TWkFGSVIg +Uk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5QqEvN +QLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT +3PSQ1hNKDJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw +3gAeqDRHu5rr/gsUvTaE2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr6 +3fE9biCloBK0TXC5ztdyO4mTp4CEHCdJckm1/zuVnsHMyAHs6A6KCpbns6aH5db5 +BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwiieDhZNRnvDF5YTy7ykHN +XGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD +AgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsF +AAOCAQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw +8PRBEew/R40/cof5O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOG +nXkZ7/e7DDWQw4rtTw/1zBLZpD67oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCP +oky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul4+vJhaAlIDf7js4MNIThPIGy +d05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6+/NNIxuZMzSg +LvWpCz/UXeHPhJ/iGcJfitYgHuNztw== +-----END CERTIFICATE----- + +# Issuer: CN=Certum Trusted Network CA 2 O=Unizeto Technologies S.A. OU=Certum Certification Authority +# Subject: CN=Certum Trusted Network CA 2 O=Unizeto Technologies S.A. OU=Certum Certification Authority +# Label: "Certum Trusted Network CA 2" +# Serial: 44979900017204383099463764357512596969 +# MD5 Fingerprint: 6d:46:9e:d9:25:6d:08:23:5b:5e:74:7d:1e:27:db:f2 +# SHA1 Fingerprint: d3:dd:48:3e:2b:bf:4c:05:e8:af:10:f5:fa:76:26:cf:d3:dc:30:92 +# SHA256 Fingerprint: b6:76:f2:ed:da:e8:77:5c:d3:6c:b0:f6:3c:d1:d4:60:39:61:f4:9e:62:65:ba:01:3a:2f:03:07:b6:d0:b8:04 +-----BEGIN CERTIFICATE----- +MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCB +gDELMAkGA1UEBhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMu +QS4xJzAlBgNVBAsTHkNlcnR1bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIG +A1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29yayBDQSAyMCIYDzIwMTExMDA2MDgz +OTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQTDEiMCAGA1UEChMZ +VW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3 +b3JrIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWA +DGSdhhuWZGc/IjoedQF97/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn +0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+oCgCXhVqqndwpyeI1B+twTUrWwbNWuKFB +OJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40bRr5HMNUuctHFY9rnY3lE +fktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2puTRZCr+E +Sv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1m +o130GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02i +sx7QBlrd9pPPV3WZ9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOW +OZV7bIBaTxNyxtd9KXpEulKkKtVBRgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgez +Tv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pyehizKV/Ma5ciSixqClnrDvFAS +adgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vMBhBgu4M1t15n +3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMC +AQYwDQYJKoZIhvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQ +F/xlhMcQSZDe28cmk4gmb3DWAl45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTf +CVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuAL55MYIR4PSFk1vtBHxgP58l1cb29 +XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMoclm2q8KMZiYcdywm +djWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tMpkT/ +WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jb +AoJnwTnbw3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksq +P/ujmv5zMnHCnsZy4YpoJ/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Ko +b7a6bINDd82Kkhehnlt4Fj1F4jNy3eFmypnTycUm/Q1oBEauttmbjL4ZvrHG8hnj +XALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLXis7VmFxWlgPF7ncGNf/P +5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7zAYspsbi +DrW5viSP +-----END CERTIFICATE----- + +# Issuer: CN=Hellenic Academic and Research Institutions RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority +# Subject: CN=Hellenic Academic and Research Institutions RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority +# Label: "Hellenic Academic and Research Institutions RootCA 2015" +# Serial: 0 +# MD5 Fingerprint: ca:ff:e2:db:03:d9:cb:4b:e9:0f:ad:84:fd:7b:18:ce +# SHA1 Fingerprint: 01:0c:06:95:a6:98:19:14:ff:bf:5f:c6:b0:b6:95:ea:29:e9:12:a6 +# SHA256 Fingerprint: a0:40:92:9a:02:ce:53:b4:ac:f4:f2:ff:c6:98:1c:e4:49:6f:75:5e:6d:45:fe:0b:2a:69:2b:cd:52:52:3f:36 +-----BEGIN CERTIFICATE----- +MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1Ix +DzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5k +IFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMT +N0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9v +dENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAxMTIxWjCBpjELMAkG +A1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNh +ZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkx +QDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1 +dGlvbnMgUm9vdENBIDIwMTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC +AQDC+Kk/G4n8PDwEXT2QNrCROnk8ZlrvbTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA +4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+ehiGsxr/CL0BgzuNtFajT0 +AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+6PAQZe10 +4S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06C +ojXdFPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV +9Cz82XBST3i4vTwri5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrD +gfgXy5I2XdGj2HUb4Ysn6npIQf1FGQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6 +Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2fu/Z8VFRfS0myGlZYeCsargq +NhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9muiNX6hME6wGko +LfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc +Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNV +HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVd +ctA4GGqd83EkVAswDQYJKoZIhvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0I +XtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+D1hYc2Ryx+hFjtyp8iY/xnmMsVMI +M4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrMd/K4kPFox/la/vot +9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+yd+2V +Z5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/ea +j8GsGsVn82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnh +X9izjFk0WaSrT2y7HxjbdavYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQ +l033DlZdwJVqwjbDG2jJ9SrcR5q+ss7FJej6A7na+RZukYT1HCjI/CbM1xyQVqdf +bzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVtJ94Cj8rDtSvK6evIIVM4 +pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGaJI7ZjnHK +e7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0 +vm9qp/UsQu0yrbYhnr68 +-----END CERTIFICATE----- + +# Issuer: CN=Hellenic Academic and Research Institutions ECC RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority +# Subject: CN=Hellenic Academic and Research Institutions ECC RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority +# Label: "Hellenic Academic and Research Institutions ECC RootCA 2015" +# Serial: 0 +# MD5 Fingerprint: 81:e5:b4:17:eb:c2:f5:e1:4b:0d:41:7b:49:92:fe:ef +# SHA1 Fingerprint: 9f:f1:71:8d:92:d5:9a:f3:7d:74:97:b4:bc:6f:84:68:0b:ba:b6:66 +# SHA256 Fingerprint: 44:b5:45:aa:8a:25:e6:5a:73:ca:15:dc:27:fc:36:d2:4c:1c:b9:95:3a:06:65:39:b1:15:82:dc:48:7b:48:33 +-----BEGIN CERTIFICATE----- +MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzAN +BgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl +c2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hl +bGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgRUNDIFJv +b3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEwMzcxMlowgaoxCzAJ +BgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmljIEFj +YWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5 +MUQwQgYDVQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0 +dXRpb25zIEVDQyBSb290Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKg +QehLgoRc4vgxEZmGZE4JJS+dQS8KrjVPdJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJa +jq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoKVlp8aQuqgAkkbH7BRqNC +MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFLQi +C4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaep +lSTAGiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7Sof +TUwJCA3sS61kFyjndc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR +-----END CERTIFICATE----- + +# Issuer: CN=ISRG Root X1 O=Internet Security Research Group +# Subject: CN=ISRG Root X1 O=Internet Security Research Group +# Label: "ISRG Root X1" +# Serial: 172886928669790476064670243504169061120 +# MD5 Fingerprint: 0c:d2:f9:e0:da:17:73:e9:ed:86:4d:a5:e3:70:e7:4e +# SHA1 Fingerprint: ca:bd:2a:79:a1:07:6a:31:f2:1d:25:36:35:cb:03:9d:43:29:a5:e8 +# SHA256 Fingerprint: 96:bc:ec:06:26:49:76:f3:74:60:77:9a:cf:28:c5:a7:cf:e8:a3:c0:aa:e1:1a:8f:fc:ee:05:c0:bd:df:08:c6 +-----BEGIN CERTIFICATE----- +MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw +TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh +cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4 +WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu +ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY +MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc +h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+ +0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U +A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW +T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH +B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC +B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv +KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn +OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn +jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw +qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI +rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq +hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL +ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ +3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK +NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5 +ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur +TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC +jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc +oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq +4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA +mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d +emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc= +-----END CERTIFICATE----- + +# Issuer: O=FNMT-RCM OU=AC RAIZ FNMT-RCM +# Subject: O=FNMT-RCM OU=AC RAIZ FNMT-RCM +# Label: "AC RAIZ FNMT-RCM" +# Serial: 485876308206448804701554682760554759 +# MD5 Fingerprint: e2:09:04:b4:d3:bd:d1:a0:14:fd:1a:d2:47:c4:57:1d +# SHA1 Fingerprint: ec:50:35:07:b2:15:c4:95:62:19:e2:a8:9a:5b:42:99:2c:4c:2c:20 +# SHA256 Fingerprint: eb:c5:57:0c:29:01:8c:4d:67:b1:aa:12:7b:af:12:f7:03:b4:61:1e:bc:17:b7:da:b5:57:38:94:17:9b:93:fa +-----BEGIN CERTIFICATE----- +MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsx +CzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJ +WiBGTk1ULVJDTTAeFw0wODEwMjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJ +BgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBG +Tk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALpxgHpMhm5/ +yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcfqQgf +BBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAz +WHFctPVrbtQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxF +tBDXaEAUwED653cXeuYLj2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z +374jNUUeAlz+taibmSXaXvMiwzn15Cou08YfxGyqxRxqAQVKL9LFwag0Jl1mpdIC +IfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mwWsXmo8RZZUc1g16p6DUL +mbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnTtOmlcYF7 +wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peS +MKGJ47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2 +ZSysV4999AeU14ECll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMet +UqIJ5G+GR4of6ygnXYMgrwTJbFaai0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFPd9xf3E6Jobd2Sn9R2gzL+H +YJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1odHRwOi8vd3d3 +LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD +nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1 +RXxlDPiyN8+sD8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYM +LVN0V2Ue1bLdI4E7pWYjJ2cJj+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf +77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrTQfv6MooqtyuGC2mDOL7Nii4LcK2N +JpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW+YJF1DngoABd15jm +fZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7Ixjp +6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp +1txyM/1d8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B +9kiABdcPUXmsEKvU7ANm5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wok +RqEIr9baRRmW1FMdW4R58MD3R++Lj8UGrp1MYp3/RgT408m2ECVAdf4WqslKYIYv +uu8wd+RU4riEmViAqhOLUTpPSPaLtrM= +-----END CERTIFICATE----- + +# Issuer: CN=Amazon Root CA 1 O=Amazon +# Subject: CN=Amazon Root CA 1 O=Amazon +# Label: "Amazon Root CA 1" +# Serial: 143266978916655856878034712317230054538369994 +# MD5 Fingerprint: 43:c6:bf:ae:ec:fe:ad:2f:18:c6:88:68:30:fc:c8:e6 +# SHA1 Fingerprint: 8d:a7:f9:65:ec:5e:fc:37:91:0f:1c:6e:59:fd:c1:cc:6a:6e:de:16 +# SHA256 Fingerprint: 8e:cd:e6:88:4f:3d:87:b1:12:5b:a3:1a:c3:fc:b1:3d:70:16:de:7f:57:cc:90:4f:e1:cb:97:c6:ae:98:19:6e +-----BEGIN CERTIFICATE----- +MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF +ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 +b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL +MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv +b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj +ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM +9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw +IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 +VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L +93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm +jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA +A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI +U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs +N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv +o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU +5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy +rqXRfboQnoZsG4q5WTP468SQvvG5 +-----END CERTIFICATE----- + +# Issuer: CN=Amazon Root CA 2 O=Amazon +# Subject: CN=Amazon Root CA 2 O=Amazon +# Label: "Amazon Root CA 2" +# Serial: 143266982885963551818349160658925006970653239 +# MD5 Fingerprint: c8:e5:8d:ce:a8:42:e2:7a:c0:2a:5c:7c:9e:26:bf:66 +# SHA1 Fingerprint: 5a:8c:ef:45:d7:a6:98:59:76:7a:8c:8b:44:96:b5:78:cf:47:4b:1a +# SHA256 Fingerprint: 1b:a5:b2:aa:8c:65:40:1a:82:96:01:18:f8:0b:ec:4f:62:30:4d:83:ce:c4:71:3a:19:c3:9c:01:1e:a4:6d:b4 +-----BEGIN CERTIFICATE----- +MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwF +ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 +b24gUm9vdCBDQSAyMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTEL +MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv +b3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK2Wny2cSkxK +gXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4kHbZ +W0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg +1dKmSYXpN+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K +8nu+NQWpEjTj82R0Yiw9AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r +2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvdfLC6HM783k81ds8P+HgfajZRRidhW+me +z/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAExkv8LV/SasrlX6avvDXbR +8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSSbtqDT6Zj +mUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz +7Mt0Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6 ++XUyo05f7O0oYtlNc/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI +0u1ufm8/0i2BWSlmy5A5lREedCf+3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMB +Af8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSwDPBMMPQFWAJI/TPlUq9LhONm +UjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oAA7CXDpO8Wqj2 +LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY ++gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kS +k5Nrp+gvU5LEYFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl +7uxMMne0nxrpS10gxdr9HIcWxkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygm +btmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQgj9sAq+uEjonljYE1x2igGOpm/Hl +urR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbWaQbLU8uz/mtBzUF+ +fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoVYh63 +n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE +76KlXIx3KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H +9jVlpNMKVv/1F2Rs76giJUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT +4PsJYGw= +-----END CERTIFICATE----- + +# Issuer: CN=Amazon Root CA 3 O=Amazon +# Subject: CN=Amazon Root CA 3 O=Amazon +# Label: "Amazon Root CA 3" +# Serial: 143266986699090766294700635381230934788665930 +# MD5 Fingerprint: a0:d4:ef:0b:f7:b5:d8:49:95:2a:ec:f5:c4:fc:81:87 +# SHA1 Fingerprint: 0d:44:dd:8c:3c:8c:1a:1a:58:75:64:81:e9:0f:2e:2a:ff:b3:d2:6e +# SHA256 Fingerprint: 18:ce:6c:fe:7b:f1:4e:60:b2:e3:47:b8:df:e8:68:cb:31:d0:2e:bb:3a:da:27:15:69:f5:03:43:b4:6d:b3:a4 +-----BEGIN CERTIFICATE----- +MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5 +MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g +Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG +A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg +Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl +ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j +QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr +ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr +BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM +YyRIHN8wfdVoOw== +-----END CERTIFICATE----- + +# Issuer: CN=Amazon Root CA 4 O=Amazon +# Subject: CN=Amazon Root CA 4 O=Amazon +# Label: "Amazon Root CA 4" +# Serial: 143266989758080763974105200630763877849284878 +# MD5 Fingerprint: 89:bc:27:d5:eb:17:8d:06:6a:69:d5:fd:89:47:b4:cd +# SHA1 Fingerprint: f6:10:84:07:d6:f8:bb:67:98:0c:c2:e2:44:c2:eb:ae:1c:ef:63:be +# SHA256 Fingerprint: e3:5d:28:41:9e:d0:20:25:cf:a6:90:38:cd:62:39:62:45:8d:a5:c6:95:fb:de:a3:c2:2b:0b:fb:25:89:70:92 +-----BEGIN CERTIFICATE----- +MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5 +MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g +Um9vdCBDQSA0MB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG +A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg +Q0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN/sGKe0uoe0ZLY7Bi +9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri83Bk +M6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB +/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WB +MAoGCCqGSM49BAMDA2gAMGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlw +CkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1AE47xDqUEpHJWEadIRNyp4iciuRMStuW +1KyLa2tJElMzrdfkviT8tQp21KW8EA== +-----END CERTIFICATE----- + +# Issuer: CN=TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 O=Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK OU=Kamu Sertifikasyon Merkezi - Kamu SM +# Subject: CN=TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 O=Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK OU=Kamu Sertifikasyon Merkezi - Kamu SM +# Label: "TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1" +# Serial: 1 +# MD5 Fingerprint: dc:00:81:dc:69:2f:3e:2f:b0:3b:f6:3d:5a:91:8e:49 +# SHA1 Fingerprint: 31:43:64:9b:ec:ce:27:ec:ed:3a:3f:0b:8f:0d:e4:e8:91:dd:ee:ca +# SHA256 Fingerprint: 46:ed:c3:68:90:46:d5:3a:45:3f:b3:10:4a:b8:0d:ca:ec:65:8b:26:60:ea:16:29:dd:7e:86:79:90:64:87:16 +-----BEGIN CERTIFICATE----- +MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIx +GDAWBgNVBAcTD0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxp +bXNlbCB2ZSBUZWtub2xvamlrIEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0w +KwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24gTWVya2V6aSAtIEthbXUgU00xNjA0 +BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRpZmlrYXNpIC0gU3Vy +dW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYDVQQG +EwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXll +IEJpbGltc2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklU +QUsxLTArBgNVBAsTJEthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBT +TTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11IFNNIFNTTCBLb2sgU2VydGlmaWthc2kg +LSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr3UwM6q7 +a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y86Ij5iySr +LqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INr +N3wcwv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2X +YacQuFWQfw4tJzh03+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/ +iSIzL+aFCr2lqBs23tPcLG07xxO9WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4f +AJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQUZT/HiobGPN08VFw1+DrtUgxH +V8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL +BQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh +AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPf +IPP54+M638yclNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4 +lzwDGrpDxpa5RXI4s6ehlj2Re37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c +8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0jq5Rm+K37DwhuJi1/FwcJsoz7UMCf +lo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM= +-----END CERTIFICATE----- + +# Issuer: CN=GDCA TrustAUTH R5 ROOT O=GUANG DONG CERTIFICATE AUTHORITY CO.,LTD. +# Subject: CN=GDCA TrustAUTH R5 ROOT O=GUANG DONG CERTIFICATE AUTHORITY CO.,LTD. +# Label: "GDCA TrustAUTH R5 ROOT" +# Serial: 9009899650740120186 +# MD5 Fingerprint: 63:cc:d9:3d:34:35:5c:6f:53:a3:e2:08:70:48:1f:b4 +# SHA1 Fingerprint: 0f:36:38:5b:81:1a:25:c3:9b:31:4e:83:ca:e9:34:66:70:cc:74:b4 +# SHA256 Fingerprint: bf:ff:8f:d0:44:33:48:7d:6a:8a:a6:0c:1a:29:76:7a:9f:c2:bb:b0:5e:42:0f:71:3a:13:b9:92:89:1d:38:93 +-----BEGIN CERTIFICATE----- +MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UE +BhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ +IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0 +MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVowYjELMAkGA1UEBhMCQ04xMjAwBgNV +BAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8w +HQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0BAQEF +AAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJj +Dp6L3TQsAlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBj +TnnEt1u9ol2x8kECK62pOqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+u +KU49tm7srsHwJ5uu4/Ts765/94Y9cnrrpftZTqfrlYwiOXnhLQiPzLyRuEH3FMEj +qcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ9Cy5WmYqsBebnh52nUpm +MUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQxXABZG12 +ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloP +zgsMR6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3Gk +L30SgLdTMEZeS1SZD2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeC +jGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4oR24qoAATILnsn8JuLwwoC8N9VKejveSswoA +HQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx9hoh49pwBiFYFIeFd3mqgnkC +AwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlRMA8GA1UdEwEB +/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg +p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZm +DRd9FBUb1Ov9H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5 +COmSdI31R9KrO9b7eGZONn356ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ry +L3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd+PwyvzeG5LuOmCd+uh8W4XAR8gPf +JWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQHtZa37dG/OaG+svg +IHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBDF8Io +2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV +09tL7ECQ8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQ +XR4EzzffHqhmsYzmIGrv/EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrq +T8p+ck0LcIymSLumoRT2+1hEmRSuqguTaaApJUqlyyvdimYHFngVV3Eb7PVHhPOe +MTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g== +-----END CERTIFICATE----- + +# Issuer: CN=SSL.com Root Certification Authority RSA O=SSL Corporation +# Subject: CN=SSL.com Root Certification Authority RSA O=SSL Corporation +# Label: "SSL.com Root Certification Authority RSA" +# Serial: 8875640296558310041 +# MD5 Fingerprint: 86:69:12:c0:70:f1:ec:ac:ac:c2:d5:bc:a5:5b:a1:29 +# SHA1 Fingerprint: b7:ab:33:08:d1:ea:44:77:ba:14:80:12:5a:6f:bd:a9:36:49:0c:bb +# SHA256 Fingerprint: 85:66:6a:56:2e:e0:be:5c:e9:25:c1:d8:89:0a:6f:76:a8:7e:c1:6d:4d:7d:5f:29:ea:74:19:cf:20:12:3b:69 +-----BEGIN CERTIFICATE----- +MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UE +BhMCVVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQK +DA9TU0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eSBSU0EwHhcNMTYwMjEyMTczOTM5WhcNNDEwMjEyMTcz +OTM5WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv +dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv +bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTCCAiIwDQYJKoZIhvcN +AQEBBQADggIPADCCAgoCggIBAPkP3aMrfcvQKv7sZ4Wm5y4bunfh4/WvpOz6Sl2R +xFdHaxh3a3by/ZPkPQ/CFp4LZsNWlJ4Xg4XOVu/yFv0AYvUiCVToZRdOQbngT0aX +qhvIuG5iXmmxX9sqAn78bMrzQdjt0Oj8P2FI7bADFB0QDksZ4LtO7IZl/zbzXmcC +C52GVWH9ejjt/uIZALdvoVBidXQ8oPrIJZK0bnoix/geoeOy3ZExqysdBP+lSgQ3 +6YWkMyv94tZVNHwZpEpox7Ko07fKoZOI68GXvIz5HdkihCR0xwQ9aqkpk8zruFvh +/l8lqjRYyMEjVJ0bmBHDOJx+PYZspQ9AhnwC9FwCTyjLrnGfDzrIM/4RJTXq/LrF +YD3ZfBjVsqnTdXgDciLKOsMf7yzlLqn6niy2UUb9rwPW6mBo6oUWNmuF6R7As93E +JNyAKoFBbZQ+yODJgUEAnl6/f8UImKIYLEJAs/lvOCdLToD0PYFH4Ih86hzOtXVc +US4cK38acijnALXRdMbX5J+tB5O2UzU1/Dfkw/ZdFr4hc96SCvigY2q8lpJqPvi8 +ZVWb3vUNiSYE/CUapiVpy8JtynziWV+XrOvvLsi81xtZPCvM8hnIk2snYxnP/Okm ++Mpxm3+T/jRnhE6Z6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRWCk4sbE6x/c+cCbqi +M+2HAgMBAAGjYzBhMB0GA1UdDgQWBBTdBAkHovV6fVJTEpKV7jiAJQ2mWTAPBgNV +HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFN0ECQei9Xp9UlMSkpXuOIAlDaZZMA4G +A1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAIBgRlCn7Jp0cHh5wYfGV +cpNxJK1ok1iOMq8bs3AD/CUrdIWQPXhq9LmLpZc7tRiRux6n+UBbkflVma8eEdBc +Hadm47GUBwwyOabqG7B52B2ccETjit3E+ZUfijhDPwGFpUenPUayvOUiaPd7nNgs +PgohyC0zrL/FgZkxdMF1ccW+sfAjRfSda/wZY52jvATGGAslu1OJD7OAUN5F7kR/ +q5R4ZJjT9ijdh9hwZXT7DrkT66cPYakylszeu+1jTBi7qUD3oFRuIIhxdRjqerQ0 +cuAjJ3dctpDqhiVAq+8zD8ufgr6iIPv2tS0a5sKFsXQP+8hlAqRSAUfdSSLBv9jr +a6x+3uxjMxW3IwiPxg+NQVrdjsW5j+VFP3jbutIbQLH+cU0/4IGiul607BXgk90I +H37hVZkLId6Tngr75qNJvTYw/ud3sqB1l7UtgYgXZSD32pAAn8lSzDLKNXz1PQ/Y +K9f1JmzJBjSWFupwWRoyeXkLtoh/D1JIPb9s2KJELtFOt3JY04kTlf5Eq/jXixtu +nLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406ywKBjYZC6VWg3dGq2ktuf +oYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NIWuuA8ShY +Ic2wBlX7Jz9TkHCpBB5XJ7k= +-----END CERTIFICATE----- + +# Issuer: CN=SSL.com Root Certification Authority ECC O=SSL Corporation +# Subject: CN=SSL.com Root Certification Authority ECC O=SSL Corporation +# Label: "SSL.com Root Certification Authority ECC" +# Serial: 8495723813297216424 +# MD5 Fingerprint: 2e:da:e4:39:7f:9c:8f:37:d1:70:9f:26:17:51:3a:8e +# SHA1 Fingerprint: c3:19:7c:39:24:e6:54:af:1b:c4:ab:20:95:7a:e2:c3:0e:13:02:6a +# SHA256 Fingerprint: 34:17:bb:06:cc:60:07:da:1b:96:1c:92:0b:8a:b4:ce:3f:ad:82:0e:4a:a3:0b:9a:cb:c4:a7:4e:bd:ce:bc:65 +-----BEGIN CERTIFICATE----- +MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMC +VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T +U0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0 +aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNDAzWhcNNDEwMjEyMTgxNDAz +WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hvdXN0 +b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNvbSBS +b290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB +BAAiA2IABEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI +7Z4INcgn64mMU1jrYor+8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPg +CemB+vNH06NjMGEwHQYDVR0OBBYEFILRhXMw5zUE044CkvvlpNHEIejNMA8GA1Ud +EwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTTjgKS++Wk0cQh6M0wDgYD +VR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCWe+0F+S8T +kdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+ +gA0z5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl +-----END CERTIFICATE----- + +# Issuer: CN=SSL.com EV Root Certification Authority RSA R2 O=SSL Corporation +# Subject: CN=SSL.com EV Root Certification Authority RSA R2 O=SSL Corporation +# Label: "SSL.com EV Root Certification Authority RSA R2" +# Serial: 6248227494352943350 +# MD5 Fingerprint: e1:1e:31:58:1a:ae:54:53:02:f6:17:6a:11:7b:4d:95 +# SHA1 Fingerprint: 74:3a:f0:52:9b:d0:32:a0:f4:4a:83:cd:d4:ba:a9:7b:7c:2e:c4:9a +# SHA256 Fingerprint: 2e:7b:f1:6c:c2:24:85:a7:bb:e2:aa:86:96:75:07:61:b0:ae:39:be:3b:2f:e9:d0:cc:6d:4e:f7:34:91:42:5c +-----BEGIN CERTIFICATE----- +MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNV +BAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UE +CgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2Vy +dGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMB4XDTE3MDUzMTE4MTQzN1oXDTQy +MDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4G +A1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQD +DC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvq +M0fNTPl9fb69LT3w23jhhqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssuf +OePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7wcXHswxzpY6IXFJ3vG2fThVUCAtZJycxa +4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTOZw+oz12WGQvE43LrrdF9 +HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+B6KjBSYR +aZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcA +b9ZhCBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQ +Gp8hLH94t2S42Oim9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQV +PWKchjgGAGYS5Fl2WlPAApiiECtoRHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMO +pgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+SlmJuwgUHfbSguPvuUCYHBBXtSu +UDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48+qvWBkofZ6aY +MBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV +HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa4 +9QaAJadz20ZpqJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBW +s47LCp1Jjr+kxJG7ZhcFUZh1++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5 +Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nxY/hoLVUE0fKNsKTPvDxeH3jnpaAg +cLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2GguDKBAdRUNf/ktUM +79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDzOFSz +/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXt +ll9ldDz7CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEm +Kf7GUmG6sXP/wwyc5WxqlD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKK +QbNmC1r7fSOl8hqw/96bg5Qu0T/fkreRrwU7ZcegbLHNYhLDkBvjJc40vG93drEQ +w/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1hlMYegouCRw2n5H9gooi +S9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX9hwJ1C07 +mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w== +-----END CERTIFICATE----- + +# Issuer: CN=SSL.com EV Root Certification Authority ECC O=SSL Corporation +# Subject: CN=SSL.com EV Root Certification Authority ECC O=SSL Corporation +# Label: "SSL.com EV Root Certification Authority ECC" +# Serial: 3182246526754555285 +# MD5 Fingerprint: 59:53:22:65:83:42:01:54:c0:ce:42:b9:5a:7c:f2:90 +# SHA1 Fingerprint: 4c:dd:51:a3:d1:f5:20:32:14:b0:c6:c5:32:23:03:91:c7:46:42:6d +# SHA256 Fingerprint: 22:a2:c1:f7:bd:ed:70:4c:c1:e7:01:b5:f4:08:c3:10:88:0f:e9:56:b5:de:2a:4a:44:f9:9c:87:3a:25:a7:c8 +-----BEGIN CERTIFICATE----- +MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMC +VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T +U0wgQ29ycG9yYXRpb24xNDAyBgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNTIzWhcNNDEwMjEyMTgx +NTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv +dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NMLmNv +bSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49 +AgEGBSuBBAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMA +VIbc/R/fALhBYlzccBYy3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1Kthku +WnBaBu2+8KGwytAJKaNjMGEwHQYDVR0OBBYEFFvKXuXe0oGqzagtZFG22XKbl+ZP +MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe5d7SgarNqC1kUbbZcpuX +5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJN+vp1RPZ +ytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZg +h5Mmm7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg== +-----END CERTIFICATE----- + +# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R6 +# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R6 +# Label: "GlobalSign Root CA - R6" +# Serial: 1417766617973444989252670301619537 +# MD5 Fingerprint: 4f:dd:07:e4:d4:22:64:39:1e:0c:37:42:ea:d1:c6:ae +# SHA1 Fingerprint: 80:94:64:0e:b5:a7:a1:ca:11:9c:1f:dd:d5:9f:81:02:63:a7:fb:d1 +# SHA256 Fingerprint: 2c:ab:ea:fe:37:d0:6c:a2:2a:ba:73:91:c0:03:3d:25:98:29:52:c4:53:64:73:49:76:3a:3a:b5:ad:6c:cf:69 +-----BEGIN CERTIFICATE----- +MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEg +MB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2Jh +bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQx +MjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSNjET +MBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCAiIwDQYJ +KoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQssgrRI +xutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1k +ZguSgMpE3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxD +aNc9PIrFsmbVkJq3MQbFvuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJw +LnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqMPKq0pPbzlUoSB239jLKJz9CgYXfIWHSw +1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+azayOeSsJDa38O+2HBNX +k7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05OWgtH8wY2 +SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/h +bguyCLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4n +WUx2OVvq+aWh2IMP0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpY +rZxCRXluDocZXFSxZba/jJvcE+kNb7gu3GduyYsRtYQUigAZcIN5kZeR1Bonvzce +MgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTAD +AQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNVHSMEGDAWgBSu +bAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN +nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGt +Ixg93eFyRJa0lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr61 +55wsTLxDKZmOMNOsIeDjHfrYBzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLj +vUYAGm0CuiVdjaExUd1URhxN25mW7xocBFymFe944Hn+Xds+qkxV/ZoVqW/hpvvf +cDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr3TsTjxKM4kEaSHpz +oHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB10jZp +nOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfs +pA9MRf/TuTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+v +JJUEeKgDu+6B5dpffItKoZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R +8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+tJDfLRVpOoERIyNiwmcUVhAn21klJwGW4 +5hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA= +-----END CERTIFICATE----- + +# Issuer: CN=OISTE WISeKey Global Root GC CA O=WISeKey OU=OISTE Foundation Endorsed +# Subject: CN=OISTE WISeKey Global Root GC CA O=WISeKey OU=OISTE Foundation Endorsed +# Label: "OISTE WISeKey Global Root GC CA" +# Serial: 44084345621038548146064804565436152554 +# MD5 Fingerprint: a9:d6:b9:2d:2f:93:64:f8:a5:69:ca:91:e9:68:07:23 +# SHA1 Fingerprint: e0:11:84:5e:34:de:be:88:81:b9:9c:f6:16:26:d1:96:1f:c3:b9:31 +# SHA256 Fingerprint: 85:60:f9:1c:36:24:da:ba:95:70:b5:fe:a0:db:e3:6f:f1:1a:83:23:be:94:86:85:4f:b3:f3:4a:55:71:19:8d +-----BEGIN CERTIFICATE----- +MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQsw +CQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91 +bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwg +Um9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRaFw00MjA1MDkwOTU4MzNaMG0xCzAJ +BgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBGb3Vu +ZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2JhbCBS +b290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4ni +eUqjFqdrVCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4W +p2OQ0jnUsYd4XxiWD1AbNTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7T +rYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0EAwMDaAAwZQIwJsdpW9zV +57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtkAjEA2zQg +Mgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9 +-----END CERTIFICATE----- + +# Issuer: CN=UCA Global G2 Root O=UniTrust +# Subject: CN=UCA Global G2 Root O=UniTrust +# Label: "UCA Global G2 Root" +# Serial: 124779693093741543919145257850076631279 +# MD5 Fingerprint: 80:fe:f0:c4:4a:f0:5c:62:32:9f:1c:ba:78:a9:50:f8 +# SHA1 Fingerprint: 28:f9:78:16:19:7a:ff:18:25:18:aa:44:fe:c1:a0:ce:5c:b6:4c:8a +# SHA256 Fingerprint: 9b:ea:11:c9:76:fe:01:47:64:c1:be:56:a6:f9:14:b5:a5:60:31:7a:bd:99:88:39:33:82:e5:16:1a:a0:49:3c +-----BEGIN CERTIFICATE----- +MIIFRjCCAy6gAwIBAgIQXd+x2lqj7V2+WmUgZQOQ7zANBgkqhkiG9w0BAQsFADA9 +MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxGzAZBgNVBAMMElVDQSBH +bG9iYWwgRzIgUm9vdDAeFw0xNjAzMTEwMDAwMDBaFw00MDEyMzEwMDAwMDBaMD0x +CzAJBgNVBAYTAkNOMREwDwYDVQQKDAhVbmlUcnVzdDEbMBkGA1UEAwwSVUNBIEds +b2JhbCBHMiBSb290MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxeYr +b3zvJgUno4Ek2m/LAfmZmqkywiKHYUGRO8vDaBsGxUypK8FnFyIdK+35KYmToni9 +kmugow2ifsqTs6bRjDXVdfkX9s9FxeV67HeToI8jrg4aA3++1NDtLnurRiNb/yzm +VHqUwCoV8MmNsHo7JOHXaOIxPAYzRrZUEaalLyJUKlgNAQLx+hVRZ2zA+te2G3/R +VogvGjqNO7uCEeBHANBSh6v7hn4PJGtAnTRnvI3HLYZveT6OqTwXS3+wmeOwcWDc +C/Vkw85DvG1xudLeJ1uK6NjGruFZfc8oLTW4lVYa8bJYS7cSN8h8s+1LgOGN+jIj +tm+3SJUIsUROhYw6AlQgL9+/V087OpAh18EmNVQg7Mc/R+zvWr9LesGtOxdQXGLY +D0tK3Cv6brxzks3sx1DoQZbXqX5t2Okdj4q1uViSukqSKwxW/YDrCPBeKW4bHAyv +j5OJrdu9o54hyokZ7N+1wxrrFv54NkzWbtA+FxyQF2smuvt6L78RHBgOLXMDj6Dl +NaBa4kx1HXHhOThTeEDMg5PXCp6dW4+K5OXgSORIskfNTip1KnvyIvbJvgmRlld6 +iIis7nCs+dwp4wwcOxJORNanTrAmyPPZGpeRaOrvjUYG0lZFWJo8DA+DuAUlwznP +O6Q0ibd5Ei9Hxeepl2n8pndntd978XplFeRhVmUCAwEAAaNCMEAwDgYDVR0PAQH/ +BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFIHEjMz15DD/pQwIX4wV +ZyF0Ad/fMA0GCSqGSIb3DQEBCwUAA4ICAQATZSL1jiutROTL/7lo5sOASD0Ee/oj +L3rtNtqyzm325p7lX1iPyzcyochltq44PTUbPrw7tgTQvPlJ9Zv3hcU2tsu8+Mg5 +1eRfB70VVJd0ysrtT7q6ZHafgbiERUlMjW+i67HM0cOU2kTC5uLqGOiiHycFutfl +1qnN3e92mI0ADs0b+gO3joBYDic/UvuUospeZcnWhNq5NXHzJsBPd+aBJ9J3O5oU +b3n09tDh05S60FdRvScFDcH9yBIw7m+NESsIndTUv4BFFJqIRNow6rSn4+7vW4LV +PtateJLbXDzz2K36uGt/xDYotgIVilQsnLAXc47QN6MUPJiVAAwpBVueSUmxX8fj +y88nZY41F7dXyDDZQVu5FLbowg+UMaeUmMxq67XhJ/UQqAHojhJi6IjMtX9Gl8Cb +EGY4GjZGXyJoPd/JxhMnq1MGrKI8hgZlb7F+sSlEmqO6SWkoaY/X5V+tBIZkbxqg +DMUIYs6Ao9Dz7GjevjPHF1t/gMRMTLGmhIrDO7gJzRSBuhjjVFc2/tsvfEehOjPI ++Vg7RE+xygKJBJYoaMVLuCaJu9YzL1DV/pqJuhgyklTGW+Cd+V7lDSKb9triyCGy +YiGqhkCyLmTTX8jjfhFnRR8F/uOi77Oos/N9j/gMHyIfLXC0uAE0djAA5SN4p1bX +UB+K+wb1whnw0A== +-----END CERTIFICATE----- + +# Issuer: CN=UCA Extended Validation Root O=UniTrust +# Subject: CN=UCA Extended Validation Root O=UniTrust +# Label: "UCA Extended Validation Root" +# Serial: 106100277556486529736699587978573607008 +# MD5 Fingerprint: a1:f3:5f:43:c6:34:9b:da:bf:8c:7e:05:53:ad:96:e2 +# SHA1 Fingerprint: a3:a1:b0:6f:24:61:23:4a:e3:36:a5:c2:37:fc:a6:ff:dd:f0:d7:3a +# SHA256 Fingerprint: d4:3a:f9:b3:54:73:75:5c:96:84:fc:06:d7:d8:cb:70:ee:5c:28:e7:73:fb:29:4e:b4:1e:e7:17:22:92:4d:24 +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgIQT9Irj/VkyDOeTzRYZiNwYDANBgkqhkiG9w0BAQsFADBH +MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBF +eHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwHhcNMTUwMzEzMDAwMDAwWhcNMzgxMjMx +MDAwMDAwWjBHMQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNV +BAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQCpCQcoEwKwmeBkqh5DFnpzsZGgdT6o+uM4AHrsiWog +D4vFsJszA1qGxliG1cGFu0/GnEBNyr7uaZa4rYEwmnySBesFK5pI0Lh2PpbIILvS +sPGP2KxFRv+qZ2C0d35qHzwaUnoEPQc8hQ2E0B92CvdqFN9y4zR8V05WAT558aop +O2z6+I9tTcg1367r3CTueUWnhbYFiN6IXSV8l2RnCdm/WhUFhvMJHuxYMjMR83dk +sHYf5BA1FxvyDrFspCqjc/wJHx4yGVMR59mzLC52LqGj3n5qiAno8geK+LLNEOfi +c0CTuwjRP+H8C5SzJe98ptfRr5//lpr1kXuYC3fUfugH0mK1lTnj8/FtDw5lhIpj +VMWAtuCeS31HJqcBCF3RiJ7XwzJE+oJKCmhUfzhTA8ykADNkUVkLo4KRel7sFsLz +KuZi2irbWWIQJUoqgQtHB0MGcIfS+pMRKXpITeuUx3BNr2fVUbGAIAEBtHoIppB/ +TuDvB0GHr2qlXov7z1CymlSvw4m6WC31MJixNnI5fkkE/SmnTHnkBVfblLkWU41G +sx2VYVdWf6/wFlthWG82UBEL2KwrlRYaDh8IzTY0ZRBiZtWAXxQgXy0MoHgKaNYs +1+lvK9JKBZP8nm9rZ/+I8U6laUpSNwXqxhaN0sSZ0YIrO7o1dfdRUVjzyAfd5LQD +fwIDAQABo0IwQDAdBgNVHQ4EFgQU2XQ65DA9DfcS3H5aBZ8eNJr34RQwDwYDVR0T +AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBADaN +l8xCFWQpN5smLNb7rhVpLGsaGvdftvkHTFnq88nIua7Mui563MD1sC3AO6+fcAUR +ap8lTwEpcOPlDOHqWnzcSbvBHiqB9RZLcpHIojG5qtr8nR/zXUACE/xOHAbKsxSQ +VBcZEhrxH9cMaVr2cXj0lH2RC47skFSOvG+hTKv8dGT9cZr4QQehzZHkPJrgmzI5 +c6sq1WnIeJEmMX3ixzDx/BR4dxIOE/TdFpS/S2d7cFOFyrC78zhNLJA5wA3CXWvp +4uXViI3WLL+rG761KIcSF3Ru/H38j9CHJrAb+7lsq+KePRXBOy5nAliRn+/4Qh8s +t2j1da3Ptfb/EX3C8CSlrdP6oDyp+l3cpaDvRKS+1ujl5BOWF3sGPjLtx7dCvHaj +2GU4Kzg1USEODm8uNBNA4StnDG1KQTAYI1oyVZnJF+A83vbsea0rWBmirSwiGpWO +vpaQXUJXxPkUAzUrHC1RVwinOt4/5Mi0A3PCwSaAuwtCH60NryZy2sy+s6ODWA2C +xR9GUeOcGMyNm43sSet1UNWMKFnKdDTajAshqx7qG+XH/RU+wBeq+yNuJkbL+vmx +cmtpzyKEC2IPrNkZAJSidjzULZrtBJ4tBmIQN1IchXIbJ+XMxjHsN+xjWZsLHXbM +fjKaiJUINlK73nZfdklJrX+9ZSCyycErdhh2n1ax +-----END CERTIFICATE----- + +# Issuer: CN=Certigna Root CA O=Dhimyotis OU=0002 48146308100036 +# Subject: CN=Certigna Root CA O=Dhimyotis OU=0002 48146308100036 +# Label: "Certigna Root CA" +# Serial: 269714418870597844693661054334862075617 +# MD5 Fingerprint: 0e:5c:30:62:27:eb:5b:bc:d7:ae:62:ba:e9:d5:df:77 +# SHA1 Fingerprint: 2d:0d:52:14:ff:9e:ad:99:24:01:74:20:47:6e:6c:85:27:27:f5:43 +# SHA256 Fingerprint: d4:8d:3d:23:ee:db:50:a4:59:e5:51:97:60:1c:27:77:4b:9d:7b:18:c9:4d:5a:05:95:11:a1:02:50:b9:31:68 +-----BEGIN CERTIFICATE----- +MIIGWzCCBEOgAwIBAgIRAMrpG4nxVQMNo+ZBbcTjpuEwDQYJKoZIhvcNAQELBQAw +WjELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczEcMBoGA1UECwwTMDAw +MiA0ODE0NjMwODEwMDAzNjEZMBcGA1UEAwwQQ2VydGlnbmEgUm9vdCBDQTAeFw0x +MzEwMDEwODMyMjdaFw0zMzEwMDEwODMyMjdaMFoxCzAJBgNVBAYTAkZSMRIwEAYD +VQQKDAlEaGlteW90aXMxHDAaBgNVBAsMEzAwMDIgNDgxNDYzMDgxMDAwMzYxGTAX +BgNVBAMMEENlcnRpZ25hIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw +ggIKAoICAQDNGDllGlmx6mQWDoyUJJV8g9PFOSbcDO8WV43X2KyjQn+Cyu3NW9sO +ty3tRQgXstmzy9YXUnIo245Onoq2C/mehJpNdt4iKVzSs9IGPjA5qXSjklYcoW9M +CiBtnyN6tMbaLOQdLNyzKNAT8kxOAkmhVECe5uUFoC2EyP+YbNDrihqECB63aCPu +I9Vwzm1RaRDuoXrC0SIxwoKF0vJVdlB8JXrJhFwLrN1CTivngqIkicuQstDuI7pm +TLtipPlTWmR7fJj6o0ieD5Wupxj0auwuA0Wv8HT4Ks16XdG+RCYyKfHx9WzMfgIh +C59vpD++nVPiz32pLHxYGpfhPTc3GGYo0kDFUYqMwy3OU4gkWGQwFsWq4NYKpkDf +ePb1BHxpE4S80dGnBs8B92jAqFe7OmGtBIyT46388NtEbVncSVmurJqZNjBBe3Yz +IoejwpKGbvlw7q6Hh5UbxHq9MfPU0uWZ/75I7HX1eBYdpnDBfzwboZL7z8g81sWT +Co/1VTp2lc5ZmIoJlXcymoO6LAQ6l73UL77XbJuiyn1tJslV1c/DeVIICZkHJC1k +JWumIWmbat10TWuXekG9qxf5kBdIjzb5LdXF2+6qhUVB+s06RbFo5jZMm5BX7CO5 +hwjCxAnxl4YqKE3idMDaxIzb3+KhF1nOJFl0Mdp//TBt2dzhauH8XwIDAQABo4IB +GjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE +FBiHVuBud+4kNTxOc5of1uHieX4rMB8GA1UdIwQYMBaAFBiHVuBud+4kNTxOc5of +1uHieX4rMEQGA1UdIAQ9MDswOQYEVR0gADAxMC8GCCsGAQUFBwIBFiNodHRwczov +L3d3d3cuY2VydGlnbmEuZnIvYXV0b3JpdGVzLzBtBgNVHR8EZjBkMC+gLaArhilo +dHRwOi8vY3JsLmNlcnRpZ25hLmZyL2NlcnRpZ25hcm9vdGNhLmNybDAxoC+gLYYr +aHR0cDovL2NybC5kaGlteW90aXMuY29tL2NlcnRpZ25hcm9vdGNhLmNybDANBgkq +hkiG9w0BAQsFAAOCAgEAlLieT/DjlQgi581oQfccVdV8AOItOoldaDgvUSILSo3L +6btdPrtcPbEo/uRTVRPPoZAbAh1fZkYJMyjhDSSXcNMQH+pkV5a7XdrnxIxPTGRG +HVyH41neQtGbqH6mid2PHMkwgu07nM3A6RngatgCdTer9zQoKJHyBApPNeNgJgH6 +0BGM+RFq7q89w1DTj18zeTyGqHNFkIwgtnJzFyO+B2XleJINugHA64wcZr+shncB +lA2c5uk5jR+mUYyZDDl34bSb+hxnV29qao6pK0xXeXpXIs/NX2NGjVxZOob4Mkdi +o2cNGJHc+6Zr9UhhcyNZjgKnvETq9Emd8VRY+WCv2hikLyhF3HqgiIZd8zvn/yk1 +gPxkQ5Tm4xxvvq0OKmOZK8l+hfZx6AYDlf7ej0gcWtSS6Cvu5zHbugRqh5jnxV/v +faci9wHYTfmJ0A6aBVmknpjZbyvKcL5kwlWj9Omvw5Ip3IgWJJk8jSaYtlu3zM63 +Nwf9JtmYhST/WSMDmu2dnajkXjjO11INb9I/bbEFa0nOipFGc/T2L/Coc3cOZayh +jWZSaX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw +3kAP+HwV96LOPNdeE4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0= +-----END CERTIFICATE----- + +# Issuer: CN=emSign Root CA - G1 O=eMudhra Technologies Limited OU=emSign PKI +# Subject: CN=emSign Root CA - G1 O=eMudhra Technologies Limited OU=emSign PKI +# Label: "emSign Root CA - G1" +# Serial: 235931866688319308814040 +# MD5 Fingerprint: 9c:42:84:57:dd:cb:0b:a7:2e:95:ad:b6:f3:da:bc:ac +# SHA1 Fingerprint: 8a:c7:ad:8f:73:ac:4e:c1:b5:75:4d:a5:40:f4:fc:cf:7c:b5:8e:8c +# SHA256 Fingerprint: 40:f6:af:03:46:a9:9a:a1:cd:1d:55:5a:4e:9c:ce:62:c7:f9:63:46:03:ee:40:66:15:83:3d:c8:c8:d0:03:67 +-----BEGIN CERTIFICATE----- +MIIDlDCCAnygAwIBAgIKMfXkYgxsWO3W2DANBgkqhkiG9w0BAQsFADBnMQswCQYD +VQQGEwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBU +ZWNobm9sb2dpZXMgTGltaXRlZDEcMBoGA1UEAxMTZW1TaWduIFJvb3QgQ0EgLSBH +MTAeFw0xODAyMTgxODMwMDBaFw00MzAyMTgxODMwMDBaMGcxCzAJBgNVBAYTAklO +MRMwEQYDVQQLEwplbVNpZ24gUEtJMSUwIwYDVQQKExxlTXVkaHJhIFRlY2hub2xv +Z2llcyBMaW1pdGVkMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEcxMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk0u76WaK7p1b1TST0Bsew+eeuGQz +f2N4aLTNLnF115sgxk0pvLZoYIr3IZpWNVrzdr3YzZr/k1ZLpVkGoZM0Kd0WNHVO +8oG0x5ZOrRkVUkr+PHB1cM2vK6sVmjM8qrOLqs1D/fXqcP/tzxE7lM5OMhbTI0Aq +d7OvPAEsbO2ZLIvZTmmYsvePQbAyeGHWDV/D+qJAkh1cF+ZwPjXnorfCYuKrpDhM +tTk1b+oDafo6VGiFbdbyL0NVHpENDtjVaqSW0RM8LHhQ6DqS0hdW5TUaQBw+jSzt +Od9C4INBdN+jzcKGYEho42kLVACL5HZpIQ15TjQIXhTCzLG3rdd8cIrHhQIDAQAB +o0IwQDAdBgNVHQ4EFgQU++8Nhp6w492pufEhF38+/PB3KxowDgYDVR0PAQH/BAQD +AgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFn/8oz1h31x +PaOfG1vR2vjTnGs2vZupYeveFix0PZ7mddrXuqe8QhfnPZHr5X3dPpzxz5KsbEjM +wiI/aTvFthUvozXGaCocV685743QNcMYDHsAVhzNixl03r4PEuDQqqE/AjSxcM6d +GNYIAwlG7mDgfrbESQRRfXBgvKqy/3lyeqYdPV8q+Mri/Tm3R7nrft8EI6/6nAYH +6ftjk4BAtcZsCjEozgyfz7MjNYBBjWzEN3uBL4ChQEKF6dk4jeihU80Bv2noWgby +RQuQ+q7hv53yrlc8pa6yVvSLZUDp/TGBLPQ5Cdjua6e0ph0VpZj3AYHYhX3zUVxx +iN66zB+Afko= +-----END CERTIFICATE----- + +# Issuer: CN=emSign ECC Root CA - G3 O=eMudhra Technologies Limited OU=emSign PKI +# Subject: CN=emSign ECC Root CA - G3 O=eMudhra Technologies Limited OU=emSign PKI +# Label: "emSign ECC Root CA - G3" +# Serial: 287880440101571086945156 +# MD5 Fingerprint: ce:0b:72:d1:9f:88:8e:d0:50:03:e8:e3:b8:8b:67:40 +# SHA1 Fingerprint: 30:43:fa:4f:f2:57:dc:a0:c3:80:ee:2e:58:ea:78:b2:3f:e6:bb:c1 +# SHA256 Fingerprint: 86:a1:ec:ba:08:9c:4a:8d:3b:be:27:34:c6:12:ba:34:1d:81:3e:04:3c:f9:e8:a8:62:cd:5c:57:a3:6b:be:6b +-----BEGIN CERTIFICATE----- +MIICTjCCAdOgAwIBAgIKPPYHqWhwDtqLhDAKBggqhkjOPQQDAzBrMQswCQYDVQQG +EwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNo +bm9sb2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0g +RzMwHhcNMTgwMjE4MTgzMDAwWhcNNDMwMjE4MTgzMDAwWjBrMQswCQYDVQQGEwJJ +TjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9s +b2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0gRzMw +djAQBgcqhkjOPQIBBgUrgQQAIgNiAAQjpQy4LRL1KPOxst3iAhKAnjlfSU2fySU0 +WXTsuwYc58Byr+iuL+FBVIcUqEqy6HyC5ltqtdyzdc6LBtCGI79G1Y4PPwT01xyS +fvalY8L1X44uT6EYGQIrMgqCZH0Wk9GjQjBAMB0GA1UdDgQWBBR8XQKEE9TMipuB +zhccLikenEhjQjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggq +hkjOPQQDAwNpADBmAjEAvvNhzwIQHWSVB7gYboiFBS+DCBeQyh+KTOgNG3qxrdWB +CUfvO6wIBHxcmbHtRwfSAjEAnbpV/KlK6O3t5nYBQnvI+GDZjVGLVTv7jHvrZQnD ++JbNR6iC8hZVdyR+EhCVBCyj +-----END CERTIFICATE----- + +# Issuer: CN=emSign Root CA - C1 O=eMudhra Inc OU=emSign PKI +# Subject: CN=emSign Root CA - C1 O=eMudhra Inc OU=emSign PKI +# Label: "emSign Root CA - C1" +# Serial: 825510296613316004955058 +# MD5 Fingerprint: d8:e3:5d:01:21:fa:78:5a:b0:df:ba:d2:ee:2a:5f:68 +# SHA1 Fingerprint: e7:2e:f1:df:fc:b2:09:28:cf:5d:d4:d5:67:37:b1:51:cb:86:4f:01 +# SHA256 Fingerprint: 12:56:09:aa:30:1d:a0:a2:49:b9:7a:82:39:cb:6a:34:21:6f:44:dc:ac:9f:39:54:b1:42:92:f2:e8:c8:60:8f +-----BEGIN CERTIFICATE----- +MIIDczCCAlugAwIBAgILAK7PALrEzzL4Q7IwDQYJKoZIhvcNAQELBQAwVjELMAkG +A1UEBhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEg +SW5jMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEMxMB4XDTE4MDIxODE4MzAw +MFoXDTQzMDIxODE4MzAwMFowVjELMAkGA1UEBhMCVVMxEzARBgNVBAsTCmVtU2ln +biBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQDExNlbVNpZ24gUm9v +dCBDQSAtIEMxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz+upufGZ +BczYKCFK83M0UYRWEPWgTywS4/oTmifQz/l5GnRfHXk5/Fv4cI7gklL35CX5VIPZ +HdPIWoU/Xse2B+4+wM6ar6xWQio5JXDWv7V7Nq2s9nPczdcdioOl+yuQFTdrHCZH +3DspVpNqs8FqOp099cGXOFgFixwR4+S0uF2FHYP+eF8LRWgYSKVGczQ7/g/IdrvH +GPMF0Ybzhe3nudkyrVWIzqa2kbBPrH4VI5b2P/AgNBbeCsbEBEV5f6f9vtKppa+c +xSMq9zwhbL2vj07FOrLzNBL834AaSaTUqZX3noleoomslMuoaJuvimUnzYnu3Yy1 +aylwQ6BpC+S5DwIDAQABo0IwQDAdBgNVHQ4EFgQU/qHgcB4qAzlSWkK+XJGFehiq +TbUwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL +BQADggEBAMJKVvoVIXsoounlHfv4LcQ5lkFMOycsxGwYFYDGrK9HWS8mC+M2sO87 +/kOXSTKZEhVb3xEp/6tT+LvBeA+snFOvV71ojD1pM/CjoCNjO2RnIkSt1XHLVip4 +kqNPEjE2NuLe/gDEo2APJ62gsIq1NnpSob0n9CAnYuhNlCQT5AoE6TyrLshDCUrG +YQTlSTR+08TI9Q/Aqum6VF7zYytPT1DU/rl7mYw9wC68AivTxEDkigcxHpvOJpkT ++xHqmiIMERnHXhuBUDDIlhJu58tBf5E7oke3VIAb3ADMmpDqw8NQBmIMMMAVSKeo +WXzhriKi4gp6D/piq1JM4fHfyr6DDUI= +-----END CERTIFICATE----- + +# Issuer: CN=emSign ECC Root CA - C3 O=eMudhra Inc OU=emSign PKI +# Subject: CN=emSign ECC Root CA - C3 O=eMudhra Inc OU=emSign PKI +# Label: "emSign ECC Root CA - C3" +# Serial: 582948710642506000014504 +# MD5 Fingerprint: 3e:53:b3:a3:81:ee:d7:10:f8:d3:b0:1d:17:92:f5:d5 +# SHA1 Fingerprint: b6:af:43:c2:9b:81:53:7d:f6:ef:6b:c3:1f:1f:60:15:0c:ee:48:66 +# SHA256 Fingerprint: bc:4d:80:9b:15:18:9d:78:db:3e:1d:8c:f4:f9:72:6a:79:5d:a1:64:3c:a5:f1:35:8e:1d:db:0e:dc:0d:7e:b3 +-----BEGIN CERTIFICATE----- +MIICKzCCAbGgAwIBAgIKe3G2gla4EnycqDAKBggqhkjOPQQDAzBaMQswCQYDVQQG +EwJVUzETMBEGA1UECxMKZW1TaWduIFBLSTEUMBIGA1UEChMLZU11ZGhyYSBJbmMx +IDAeBgNVBAMTF2VtU2lnbiBFQ0MgUm9vdCBDQSAtIEMzMB4XDTE4MDIxODE4MzAw +MFoXDTQzMDIxODE4MzAwMFowWjELMAkGA1UEBhMCVVMxEzARBgNVBAsTCmVtU2ln +biBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMSAwHgYDVQQDExdlbVNpZ24gRUND +IFJvb3QgQ0EgLSBDMzB2MBAGByqGSM49AgEGBSuBBAAiA2IABP2lYa57JhAd6bci +MK4G9IGzsUJxlTm801Ljr6/58pc1kjZGDoeVjbk5Wum739D+yAdBPLtVb4Ojavti +sIGJAnB9SMVK4+kiVCJNk7tCDK93nCOmfddhEc5lx/h//vXyqaNCMEAwHQYDVR0O +BBYEFPtaSNCAIEDyqOkAB2kZd6fmw/TPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMB +Af8EBTADAQH/MAoGCCqGSM49BAMDA2gAMGUCMQC02C8Cif22TGK6Q04ThHK1rt0c +3ta13FaPWEBaLd4gTCKDypOofu4SQMfWh0/434UCMBwUZOR8loMRnLDRWmFLpg9J +0wD8ofzkpf9/rdcw0Md3f76BB1UwUCAU9Vc4CqgxUQ== +-----END CERTIFICATE----- + +# Issuer: CN=Hongkong Post Root CA 3 O=Hongkong Post +# Subject: CN=Hongkong Post Root CA 3 O=Hongkong Post +# Label: "Hongkong Post Root CA 3" +# Serial: 46170865288971385588281144162979347873371282084 +# MD5 Fingerprint: 11:fc:9f:bd:73:30:02:8a:fd:3f:f3:58:b9:cb:20:f0 +# SHA1 Fingerprint: 58:a2:d0:ec:20:52:81:5b:c1:f3:f8:64:02:24:4e:c2:8e:02:4b:02 +# SHA256 Fingerprint: 5a:2f:c0:3f:0c:83:b0:90:bb:fa:40:60:4b:09:88:44:6c:76:36:18:3d:f9:84:6e:17:10:1a:44:7f:b8:ef:d6 +-----BEGIN CERTIFICATE----- +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 +mpv0 +-----END CERTIFICATE----- + +# Issuer: CN=Microsoft ECC Root Certificate Authority 2017 O=Microsoft Corporation +# Subject: CN=Microsoft ECC Root Certificate Authority 2017 O=Microsoft Corporation +# Label: "Microsoft ECC Root Certificate Authority 2017" +# Serial: 136839042543790627607696632466672567020 +# MD5 Fingerprint: dd:a1:03:e6:4a:93:10:d1:bf:f0:19:42:cb:fe:ed:67 +# SHA1 Fingerprint: 99:9a:64:c3:7f:f4:7d:9f:ab:95:f1:47:69:89:14:60:ee:c4:c3:c5 +# SHA256 Fingerprint: 35:8d:f3:9d:76:4a:f9:e1:b7:66:e9:c9:72:df:35:2e:e1:5c:fa:c2:27:af:6a:d1:d7:0e:8e:4a:6e:dc:ba:02 +-----BEGIN CERTIFICATE----- +MIICWTCCAd+gAwIBAgIQZvI9r4fei7FK6gxXMQHC7DAKBggqhkjOPQQDAzBlMQsw +CQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYD +VQQDEy1NaWNyb3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIw +MTcwHhcNMTkxMjE4MjMwNjQ1WhcNNDIwNzE4MjMxNjA0WjBlMQswCQYDVQQGEwJV +UzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNy +b3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwdjAQBgcq +hkjOPQIBBgUrgQQAIgNiAATUvD0CQnVBEyPNgASGAlEvaqiBYgtlzPbKnR5vSmZR +ogPZnZH6thaxjG7efM3beaYvzrvOcS/lpaso7GMEZpn4+vKTEAXhgShC48Zo9OYb +hGBKia/teQ87zvH2RPUBeMCjVDBSMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8E +BTADAQH/MB0GA1UdDgQWBBTIy5lycFIM+Oa+sgRXKSrPQhDtNTAQBgkrBgEEAYI3 +FQEEAwIBADAKBggqhkjOPQQDAwNoADBlAjBY8k3qDPlfXu5gKcs68tvWMoQZP3zV +L8KxzJOuULsJMsbG7X7JNpQS5GiFBqIb0C8CMQCZ6Ra0DvpWSNSkMBaReNtUjGUB +iudQZsIxtzm6uBoiB078a1QWIP8rtedMDE2mT3M= +-----END CERTIFICATE----- + +# Issuer: CN=Microsoft RSA Root Certificate Authority 2017 O=Microsoft Corporation +# Subject: CN=Microsoft RSA Root Certificate Authority 2017 O=Microsoft Corporation +# Label: "Microsoft RSA Root Certificate Authority 2017" +# Serial: 40975477897264996090493496164228220339 +# MD5 Fingerprint: 10:ff:00:ff:cf:c9:f8:c7:7a:c0:ee:35:8e:c9:0f:47 +# SHA1 Fingerprint: 73:a5:e6:4a:3b:ff:83:16:ff:0e:dc:cc:61:8a:90:6e:4e:ae:4d:74 +# SHA256 Fingerprint: c7:41:f7:0f:4b:2a:8d:88:bf:2e:71:c1:41:22:ef:53:ef:10:eb:a0:cf:a5:e6:4c:fa:20:f4:18:85:30:73:e0 +-----BEGIN CERTIFICATE----- +MIIFqDCCA5CgAwIBAgIQHtOXCV/YtLNHcB6qvn9FszANBgkqhkiG9w0BAQwFADBl +MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYw +NAYDVQQDEy1NaWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 +IDIwMTcwHhcNMTkxMjE4MjI1MTIyWhcNNDIwNzE4MjMwMDIzWjBlMQswCQYDVQQG +EwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1N +aWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKW76UM4wplZEWCpW9R2LBifOZ +Nt9GkMml7Xhqb0eRaPgnZ1AzHaGm++DlQ6OEAlcBXZxIQIJTELy/xztokLaCLeX0 +ZdDMbRnMlfl7rEqUrQ7eS0MdhweSE5CAg2Q1OQT85elss7YfUJQ4ZVBcF0a5toW1 +HLUX6NZFndiyJrDKxHBKrmCk3bPZ7Pw71VdyvD/IybLeS2v4I2wDwAW9lcfNcztm +gGTjGqwu+UcF8ga2m3P1eDNbx6H7JyqhtJqRjJHTOoI+dkC0zVJhUXAoP8XFWvLJ +jEm7FFtNyP9nTUwSlq31/niol4fX/V4ggNyhSyL71Imtus5Hl0dVe49FyGcohJUc +aDDv70ngNXtk55iwlNpNhTs+VcQor1fznhPbRiefHqJeRIOkpcrVE7NLP8TjwuaG +YaRSMLl6IE9vDzhTyzMMEyuP1pq9KsgtsRx9S1HKR9FIJ3Jdh+vVReZIZZ2vUpC6 +W6IYZVcSn2i51BVrlMRpIpj0M+Dt+VGOQVDJNE92kKz8OMHY4Xu54+OU4UZpyw4K +UGsTuqwPN1q3ErWQgR5WrlcihtnJ0tHXUeOrO8ZV/R4O03QK0dqq6mm4lyiPSMQH ++FJDOvTKVTUssKZqwJz58oHhEmrARdlns87/I6KJClTUFLkqqNfs+avNJVgyeY+Q +W5g5xAgGwax/Dj0ApQIDAQABo1QwUjAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/ +BAUwAwEB/zAdBgNVHQ4EFgQUCctZf4aycI8awznjwNnpv7tNsiMwEAYJKwYBBAGC +NxUBBAMCAQAwDQYJKoZIhvcNAQEMBQADggIBAKyvPl3CEZaJjqPnktaXFbgToqZC +LgLNFgVZJ8og6Lq46BrsTaiXVq5lQ7GPAJtSzVXNUzltYkyLDVt8LkS/gxCP81OC +gMNPOsduET/m4xaRhPtthH80dK2Jp86519efhGSSvpWhrQlTM93uCupKUY5vVau6 +tZRGrox/2KJQJWVggEbbMwSubLWYdFQl3JPk+ONVFT24bcMKpBLBaYVu32TxU5nh +SnUgnZUP5NbcA/FZGOhHibJXWpS2qdgXKxdJ5XbLwVaZOjex/2kskZGT4d9Mozd2 +TaGf+G0eHdP67Pv0RR0Tbc/3WeUiJ3IrhvNXuzDtJE3cfVa7o7P4NHmJweDyAmH3 +pvwPuxwXC65B2Xy9J6P9LjrRk5Sxcx0ki69bIImtt2dmefU6xqaWM/5TkshGsRGR +xpl/j8nWZjEgQRCHLQzWwa80mMpkg/sTV9HB8Dx6jKXB/ZUhoHHBk2dxEuqPiApp +GWSZI1b7rCoucL5mxAyE7+WL85MB+GqQk2dLsmijtWKP6T+MejteD+eMuMZ87zf9 +dOLITzNy4ZQ5bb0Sr74MTnB8G2+NszKTc0QWbej09+CVgI+WXTik9KveCjCHk9hN +AHFiRSdLOkKEW39lt2c0Ui2cFmuqqNh7o0JMcccMyj6D5KbvtwEwXlGjefVwaaZB +RA+GsCyRxj3qrg+E +-----END CERTIFICATE----- + +# Issuer: CN=e-Szigno Root CA 2017 O=Microsec Ltd. +# Subject: CN=e-Szigno Root CA 2017 O=Microsec Ltd. +# Label: "e-Szigno Root CA 2017" +# Serial: 411379200276854331539784714 +# MD5 Fingerprint: de:1f:f6:9e:84:ae:a7:b4:21:ce:1e:58:7d:d1:84:98 +# SHA1 Fingerprint: 89:d4:83:03:4f:9e:9a:48:80:5f:72:37:d4:a9:a6:ef:cb:7c:1f:d1 +# SHA256 Fingerprint: be:b0:0b:30:83:9b:9b:c3:2c:32:e4:44:79:05:95:06:41:f2:64:21:b1:5e:d0:89:19:8b:51:8a:e2:ea:1b:99 +-----BEGIN CERTIFICATE----- +MIICQDCCAeWgAwIBAgIMAVRI7yH9l1kN9QQKMAoGCCqGSM49BAMCMHExCzAJBgNV +BAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMgTHRk +LjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25vIFJv +b3QgQ0EgMjAxNzAeFw0xNzA4MjIxMjA3MDZaFw00MjA4MjIxMjA3MDZaMHExCzAJ +BgNVBAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMg +THRkLjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25v +IFJvb3QgQ0EgMjAxNzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJbcPYrYsHtv +xie+RJCxs1YVe45DJH0ahFnuY2iyxl6H0BVIHqiQrb1TotreOpCmYF9oMrWGQd+H +Wyx7xf58etqjYzBhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G +A1UdDgQWBBSHERUI0arBeAyxr87GyZDvvzAEwDAfBgNVHSMEGDAWgBSHERUI0arB +eAyxr87GyZDvvzAEwDAKBggqhkjOPQQDAgNJADBGAiEAtVfd14pVCzbhhkT61Nlo +jbjcI4qKDdQvfepz7L9NbKgCIQDLpbQS+ue16M9+k/zzNY9vTlp8tLxOsvxyqltZ ++efcMQ== +-----END CERTIFICATE----- + +# Issuer: O=CERTSIGN SA OU=certSIGN ROOT CA G2 +# Subject: O=CERTSIGN SA OU=certSIGN ROOT CA G2 +# Label: "certSIGN Root CA G2" +# Serial: 313609486401300475190 +# MD5 Fingerprint: 8c:f1:75:8a:c6:19:cf:94:b7:f7:65:20:87:c3:97:c7 +# SHA1 Fingerprint: 26:f9:93:b4:ed:3d:28:27:b0:b9:4b:a7:e9:15:1d:a3:8d:92:e5:32 +# SHA256 Fingerprint: 65:7c:fe:2f:a7:3f:aa:38:46:25:71:f3:32:a2:36:3a:46:fc:e7:02:09:51:71:07:02:cd:fb:b6:ee:da:33:05 +-----BEGIN CERTIFICATE----- +MIIFRzCCAy+gAwIBAgIJEQA0tk7GNi02MA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV +BAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJR04g +Uk9PVCBDQSBHMjAeFw0xNzAyMDYwOTI3MzVaFw00MjAyMDYwOTI3MzVaMEExCzAJ +BgNVBAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJ +R04gUk9PVCBDQSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDF +dRmRfUR0dIf+DjuW3NgBFszuY5HnC2/OOwppGnzC46+CjobXXo9X69MhWf05N0Iw +vlDqtg+piNguLWkh59E3GE59kdUWX2tbAMI5Qw02hVK5U2UPHULlj88F0+7cDBrZ +uIt4ImfkabBoxTzkbFpG583H+u/E7Eu9aqSs/cwoUe+StCmrqzWaTOTECMYmzPhp +n+Sc8CnTXPnGFiWeI8MgwT0PPzhAsP6CRDiqWhqKa2NYOLQV07YRaXseVO6MGiKs +cpc/I1mbySKEwQdPzH/iV8oScLumZfNpdWO9lfsbl83kqK/20U6o2YpxJM02PbyW +xPFsqa7lzw1uKA2wDrXKUXt4FMMgL3/7FFXhEZn91QqhngLjYl/rNUssuHLoPj1P +rCy7Lobio3aP5ZMqz6WryFyNSwb/EkaseMsUBzXgqd+L6a8VTxaJW732jcZZroiF +DsGJ6x9nxUWO/203Nit4ZoORUSs9/1F3dmKh7Gc+PoGD4FapUB8fepmrY7+EF3fx +DTvf95xhszWYijqy7DwaNz9+j5LP2RIUZNoQAhVB/0/E6xyjyfqZ90bp4RjZsbgy +LcsUDFDYg2WD7rlcz8sFWkz6GZdr1l0T08JcVLwyc6B49fFtHsufpaafItzRUZ6C +eWRgKRM+o/1Pcmqr4tTluCRVLERLiohEnMqE0yo7AgMBAAGjQjBAMA8GA1UdEwEB +/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSCIS1mxteg4BXrzkwJ +d8RgnlRuAzANBgkqhkiG9w0BAQsFAAOCAgEAYN4auOfyYILVAzOBywaK8SJJ6ejq +kX/GM15oGQOGO0MBzwdw5AgeZYWR5hEit/UCI46uuR59H35s5r0l1ZUa8gWmr4UC +b6741jH/JclKyMeKqdmfS0mbEVeZkkMR3rYzpMzXjWR91M08KCy0mpbqTfXERMQl +qiCA2ClV9+BB/AYm/7k29UMUA2Z44RGx2iBfRgB4ACGlHgAoYXhvqAEBj500mv/0 +OJD7uNGzcgbJceaBxXntC6Z58hMLnPddDnskk7RI24Zf3lCGeOdA5jGokHZwYa+c +NywRtYK3qq4kNFtyDGkNzVmf9nGvnAvRCjj5BiKDUyUM/FHE5r7iOZULJK2v0ZXk +ltd0ZGtxTgI8qoXzIKNDOXZbbFD+mpwUHmUUihW9o4JFWklWatKcsWMy5WHgUyIO +pwpJ6st+H6jiYoD2EEVSmAYY3qXNL3+q1Ok+CHLsIwMCPKaq2LxndD0UF/tUSxfj +03k9bWtJySgOLnRQvwzZRjoQhsmnP+mg7H/rpXdYaXHmgwo38oZJar55CJD2AhZk +PuXaTH4MNMn5X7azKFGnpyuqSfqNZSlO42sTp5SjLVFteAxEy9/eCG/Oo2Sr05WE +1LlSVHJ7liXMvGnjSG4N0MedJ5qq+BOS3R7fY581qRY27Iy4g/Q9iY/NtBde17MX +QRBdJ3NghVdJIgc= +-----END CERTIFICATE----- + +# Issuer: CN=Trustwave Global Certification Authority O=Trustwave Holdings, Inc. +# Subject: CN=Trustwave Global Certification Authority O=Trustwave Holdings, Inc. +# Label: "Trustwave Global Certification Authority" +# Serial: 1846098327275375458322922162 +# MD5 Fingerprint: f8:1c:18:2d:2f:ba:5f:6d:a1:6c:bc:c7:ab:91:c7:0e +# SHA1 Fingerprint: 2f:8f:36:4f:e1:58:97:44:21:59:87:a5:2a:9a:d0:69:95:26:7f:b5 +# SHA256 Fingerprint: 97:55:20:15:f5:dd:fc:3c:87:88:c0:06:94:45:55:40:88:94:45:00:84:f1:00:86:70:86:bc:1a:2b:b5:8d:c8 +-----BEGIN CERTIFICATE----- +MIIF2jCCA8KgAwIBAgIMBfcOhtpJ80Y1LrqyMA0GCSqGSIb3DQEBCwUAMIGIMQsw +CQYDVQQGEwJVUzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28x +ITAfBgNVBAoMGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1 +c3R3YXZlIEdsb2JhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMx +OTM0MTJaFw00MjA4MjMxOTM0MTJaMIGIMQswCQYDVQQGEwJVUzERMA8GA1UECAwI +SWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xITAfBgNVBAoMGFRydXN0d2F2ZSBI +b2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1c3R3YXZlIEdsb2JhbCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB +ALldUShLPDeS0YLOvR29zd24q88KPuFd5dyqCblXAj7mY2Hf8g+CY66j96xz0Xzn +swuvCAAJWX/NKSqIk4cXGIDtiLK0thAfLdZfVaITXdHG6wZWiYj+rDKd/VzDBcdu +7oaJuogDnXIhhpCujwOl3J+IKMujkkkP7NAP4m1ET4BqstTnoApTAbqOl5F2brz8 +1Ws25kCI1nsvXwXoLG0R8+eyvpJETNKXpP7ScoFDB5zpET71ixpZfR9oWN0EACyW +80OzfpgZdNmcc9kYvkHHNHnZ9GLCQ7mzJ7Aiy/k9UscwR7PJPrhq4ufogXBeQotP +JqX+OsIgbrv4Fo7NDKm0G2x2EOFYeUY+VM6AqFcJNykbmROPDMjWLBz7BegIlT1l +RtzuzWniTY+HKE40Cz7PFNm73bZQmq131BnW2hqIyE4bJ3XYsgjxroMwuREOzYfw +hI0Vcnyh78zyiGG69Gm7DIwLdVcEuE4qFC49DxweMqZiNu5m4iK4BUBjECLzMx10 +coos9TkpoNPnG4CELcU9402x/RpvumUHO1jsQkUm+9jaJXLE9gCxInm943xZYkqc +BW89zubWR2OZxiRvchLIrH+QtAuRcOi35hYQcRfO3gZPSEF9NUqjifLJS3tBEW1n +twiYTOURGa5CgNz7kAXU+FDKvuStx8KU1xad5hePrzb7AgMBAAGjQjBAMA8GA1Ud +EwEB/wQFMAMBAf8wHQYDVR0OBBYEFJngGWcNYtt2s9o9uFvo/ULSMQ6HMA4GA1Ud +DwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAmHNw4rDT7TnsTGDZqRKGFx6W +0OhUKDtkLSGm+J1WE2pIPU/HPinbbViDVD2HfSMF1OQc3Og4ZYbFdada2zUFvXfe +uyk3QAUHw5RSn8pk3fEbK9xGChACMf1KaA0HZJDmHvUqoai7PF35owgLEQzxPy0Q +lG/+4jSHg9bP5Rs1bdID4bANqKCqRieCNqcVtgimQlRXtpla4gt5kNdXElE1GYhB +aCXUNxeEFfsBctyV3lImIJgm4nb1J2/6ADtKYdkNy1GTKv0WBpanI5ojSP5RvbbE +sLFUzt5sQa0WZ37b/TjNuThOssFgy50X31ieemKyJo90lZvkWx3SD92YHJtZuSPT +MaCm/zjdzyBP6VhWOmfD0faZmZ26NraAL4hHT4a/RDqA5Dccprrql5gR0IRiR2Qe +qu5AvzSxnI9O4fKSTx+O856X3vOmeWqJcU9LJxdI/uz0UA9PSX3MReO9ekDFQdxh +VicGaeVyQYHTtgGJoC86cnn+OjC/QezHYj6RS8fZMXZC+fc8Y+wmjHMMfRod6qh8 +h6jCJ3zhM0EPz8/8AKAigJ5Kp28AsEFFtyLKaEjFQqKu3R3y4G5OBVixwJAWKqQ9 +EEC+j2Jjg6mcgn0tAumDMHzLJ8n9HmYAsC7TIS+OMxZsmO0QqAfWzJPP29FpHOTK +yeC2nOnOcXHebD8WpHk= +-----END CERTIFICATE----- + +# Issuer: CN=Trustwave Global ECC P256 Certification Authority O=Trustwave Holdings, Inc. +# Subject: CN=Trustwave Global ECC P256 Certification Authority O=Trustwave Holdings, Inc. +# Label: "Trustwave Global ECC P256 Certification Authority" +# Serial: 4151900041497450638097112925 +# MD5 Fingerprint: 5b:44:e3:8d:5d:36:86:26:e8:0d:05:d2:59:a7:83:54 +# SHA1 Fingerprint: b4:90:82:dd:45:0c:be:8b:5b:b1:66:d3:e2:a4:08:26:cd:ed:42:cf +# SHA256 Fingerprint: 94:5b:bc:82:5e:a5:54:f4:89:d1:fd:51:a7:3d:df:2e:a6:24:ac:70:19:a0:52:05:22:5c:22:a7:8c:cf:a8:b4 +-----BEGIN CERTIFICATE----- +MIICYDCCAgegAwIBAgIMDWpfCD8oXD5Rld9dMAoGCCqGSM49BAMCMIGRMQswCQYD +VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAf +BgNVBAoTGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3 +YXZlIEdsb2JhbCBFQ0MgUDI1NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0x +NzA4MjMxOTM1MTBaFw00MjA4MjMxOTM1MTBaMIGRMQswCQYDVQQGEwJVUzERMA8G +A1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0 +d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBF +Q0MgUDI1NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTBZMBMGByqGSM49AgEGCCqG +SM49AwEHA0IABH77bOYj43MyCMpg5lOcunSNGLB4kFKA3TjASh3RqMyTpJcGOMoN +FWLGjgEqZZ2q3zSRLoHB5DOSMcT9CTqmP62jQzBBMA8GA1UdEwEB/wQFMAMBAf8w +DwYDVR0PAQH/BAUDAwcGADAdBgNVHQ4EFgQUo0EGrJBt0UrrdaVKEJmzsaGLSvcw +CgYIKoZIzj0EAwIDRwAwRAIgB+ZU2g6gWrKuEZ+Hxbb/ad4lvvigtwjzRM4q3wgh +DDcCIC0mA6AFvWvR9lz4ZcyGbbOcNEhjhAnFjXca4syc4XR7 +-----END CERTIFICATE----- + +# Issuer: CN=Trustwave Global ECC P384 Certification Authority O=Trustwave Holdings, Inc. +# Subject: CN=Trustwave Global ECC P384 Certification Authority O=Trustwave Holdings, Inc. +# Label: "Trustwave Global ECC P384 Certification Authority" +# Serial: 2704997926503831671788816187 +# MD5 Fingerprint: ea:cf:60:c4:3b:b9:15:29:40:a1:97:ed:78:27:93:d6 +# SHA1 Fingerprint: e7:f3:a3:c8:cf:6f:c3:04:2e:6d:0e:67:32:c5:9e:68:95:0d:5e:d2 +# SHA256 Fingerprint: 55:90:38:59:c8:c0:c3:eb:b8:75:9e:ce:4e:25:57:22:5f:f5:75:8b:bd:38:eb:d4:82:76:60:1e:1b:d5:80:97 +-----BEGIN CERTIFICATE----- +MIICnTCCAiSgAwIBAgIMCL2Fl2yZJ6SAaEc7MAoGCCqGSM49BAMDMIGRMQswCQYD +VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAf +BgNVBAoTGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3 +YXZlIEdsb2JhbCBFQ0MgUDM4NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0x +NzA4MjMxOTM2NDNaFw00MjA4MjMxOTM2NDNaMIGRMQswCQYDVQQGEwJVUzERMA8G +A1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0 +d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBF +Q0MgUDM4NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTB2MBAGByqGSM49AgEGBSuB +BAAiA2IABGvaDXU1CDFHBa5FmVXxERMuSvgQMSOjfoPTfygIOiYaOs+Xgh+AtycJ +j9GOMMQKmw6sWASr9zZ9lCOkmwqKi6vr/TklZvFe/oyujUF5nQlgziip04pt89ZF +1PKYhDhloKNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNVHQ8BAf8EBQMDBwYAMB0G +A1UdDgQWBBRVqYSJ0sEyvRjLbKYHTsjnnb6CkDAKBggqhkjOPQQDAwNnADBkAjA3 +AZKXRRJ+oPM+rRk6ct30UJMDEr5E0k9BpIycnR+j9sKS50gU/k6bpZFXrsY3crsC +MGclCrEMXu6pY5Jv5ZAL/mYiykf9ijH3g/56vxC+GCsej/YpHpRZ744hN8tRmKVu +Sw== +-----END CERTIFICATE----- + +# Issuer: CN=NAVER Global Root Certification Authority O=NAVER BUSINESS PLATFORM Corp. +# Subject: CN=NAVER Global Root Certification Authority O=NAVER BUSINESS PLATFORM Corp. +# Label: "NAVER Global Root Certification Authority" +# Serial: 9013692873798656336226253319739695165984492813 +# MD5 Fingerprint: c8:7e:41:f6:25:3b:f5:09:b3:17:e8:46:3d:bf:d0:9b +# SHA1 Fingerprint: 8f:6b:f2:a9:27:4a:da:14:a0:c4:f4:8e:61:27:f9:c0:1e:78:5d:d1 +# SHA256 Fingerprint: 88:f4:38:dc:f8:ff:d1:fa:8f:42:91:15:ff:e5:f8:2a:e1:e0:6e:0c:70:c3:75:fa:ad:71:7b:34:a4:9e:72:65 +-----BEGIN CERTIFICATE----- +MIIFojCCA4qgAwIBAgIUAZQwHqIL3fXFMyqxQ0Rx+NZQTQ0wDQYJKoZIhvcNAQEM +BQAwaTELMAkGA1UEBhMCS1IxJjAkBgNVBAoMHU5BVkVSIEJVU0lORVNTIFBMQVRG +T1JNIENvcnAuMTIwMAYDVQQDDClOQVZFUiBHbG9iYWwgUm9vdCBDZXJ0aWZpY2F0 +aW9uIEF1dGhvcml0eTAeFw0xNzA4MTgwODU4NDJaFw0zNzA4MTgyMzU5NTlaMGkx +CzAJBgNVBAYTAktSMSYwJAYDVQQKDB1OQVZFUiBCVVNJTkVTUyBQTEFURk9STSBD +b3JwLjEyMDAGA1UEAwwpTkFWRVIgR2xvYmFsIFJvb3QgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC21PGTXLVA +iQqrDZBbUGOukJR0F0Vy1ntlWilLp1agS7gvQnXp2XskWjFlqxcX0TM62RHcQDaH +38dq6SZeWYp34+hInDEW+j6RscrJo+KfziFTowI2MMtSAuXaMl3Dxeb57hHHi8lE +HoSTGEq0n+USZGnQJoViAbbJAh2+g1G7XNr4rRVqmfeSVPc0W+m/6imBEtRTkZaz +kVrd/pBzKPswRrXKCAfHcXLJZtM0l/aM9BhK4dA9WkW2aacp+yPOiNgSnABIqKYP +szuSjXEOdMWLyEz59JuOuDxp7W87UC9Y7cSw0BwbagzivESq2M0UXZR4Yb8Obtoq +vC8MC3GmsxY/nOb5zJ9TNeIDoKAYv7vxvvTWjIcNQvcGufFt7QSUqP620wbGQGHf +nZ3zVHbOUzoBppJB7ASjjw2i1QnK1sua8e9DXcCrpUHPXFNwcMmIpi3Ua2FzUCaG +YQ5fG8Ir4ozVu53BA0K6lNpfqbDKzE0K70dpAy8i+/Eozr9dUGWokG2zdLAIx6yo +0es+nPxdGoMuK8u180SdOqcXYZaicdNwlhVNt0xz7hlcxVs+Qf6sdWA7G2POAN3a +CJBitOUt7kinaxeZVL6HSuOpXgRM6xBtVNbv8ejyYhbLgGvtPe31HzClrkvJE+2K +AQHJuFFYwGY6sWZLxNUxAmLpdIQM201GLQIDAQABo0IwQDAdBgNVHQ4EFgQU0p+I +36HNLL3s9TsBAZMzJ7LrYEswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMB +Af8wDQYJKoZIhvcNAQEMBQADggIBADLKgLOdPVQG3dLSLvCkASELZ0jKbY7gyKoN +qo0hV4/GPnrK21HUUrPUloSlWGB/5QuOH/XcChWB5Tu2tyIvCZwTFrFsDDUIbatj +cu3cvuzHV+YwIHHW1xDBE1UBjCpD5EHxzzp6U5LOogMFDTjfArsQLtk70pt6wKGm ++LUx5vR1yblTmXVHIloUFcd4G7ad6Qz4G3bxhYTeodoS76TiEJd6eN4MUZeoIUCL +hr0N8F5OSza7OyAfikJW4Qsav3vQIkMsRIz75Sq0bBwcupTgE34h5prCy8VCZLQe +lHsIJchxzIdFV4XTnyliIoNRlwAYl3dqmJLJfGBs32x9SuRwTMKeuB330DTHD8z7 +p/8Dvq1wkNoL3chtl1+afwkyQf3NosxabUzyqkn+Zvjp2DXrDige7kgvOtB5CTh8 +piKCk5XQA76+AqAF3SAi428diDRgxuYKuQl1C/AH6GmWNcf7I4GOODm4RStDeKLR +LBT/DShycpWbXgnbiUSYqqFJu3FS8r/2/yehNq+4tneI3TqkbZs0kNwUXTC/t+sX +5Ie3cdCh13cV1ELX8vMxmV2b3RZtP+oGI/hGoiLtk/bdmuYqh7GYVPEi92tF4+KO +dh2ajcQGjTa3FPOdVGm3jjzVpG2Tgbet9r1ke8LJaDmgkpzNNIaRkPpkUZ3+/uul +9XXeifdy +-----END CERTIFICATE----- + +# Issuer: CN=AC RAIZ FNMT-RCM SERVIDORES SEGUROS O=FNMT-RCM OU=Ceres +# Subject: CN=AC RAIZ FNMT-RCM SERVIDORES SEGUROS O=FNMT-RCM OU=Ceres +# Label: "AC RAIZ FNMT-RCM SERVIDORES SEGUROS" +# Serial: 131542671362353147877283741781055151509 +# MD5 Fingerprint: 19:36:9c:52:03:2f:d2:d1:bb:23:cc:dd:1e:12:55:bb +# SHA1 Fingerprint: 62:ff:d9:9e:c0:65:0d:03:ce:75:93:d2:ed:3f:2d:32:c9:e3:e5:4a +# SHA256 Fingerprint: 55:41:53:b1:3d:2c:f9:dd:b7:53:bf:be:1a:4e:0a:e0:8d:0a:a4:18:70:58:fe:60:a2:b8:62:b2:e4:b8:7b:cb +-----BEGIN CERTIFICATE----- +MIICbjCCAfOgAwIBAgIQYvYybOXE42hcG2LdnC6dlTAKBggqhkjOPQQDAzB4MQsw +CQYDVQQGEwJFUzERMA8GA1UECgwIRk5NVC1SQ00xDjAMBgNVBAsMBUNlcmVzMRgw +FgYDVQRhDA9WQVRFUy1RMjgyNjAwNEoxLDAqBgNVBAMMI0FDIFJBSVogRk5NVC1S +Q00gU0VSVklET1JFUyBTRUdVUk9TMB4XDTE4MTIyMDA5MzczM1oXDTQzMTIyMDA5 +MzczM1oweDELMAkGA1UEBhMCRVMxETAPBgNVBAoMCEZOTVQtUkNNMQ4wDAYDVQQL +DAVDZXJlczEYMBYGA1UEYQwPVkFURVMtUTI4MjYwMDRKMSwwKgYDVQQDDCNBQyBS +QUlaIEZOTVQtUkNNIFNFUlZJRE9SRVMgU0VHVVJPUzB2MBAGByqGSM49AgEGBSuB +BAAiA2IABPa6V1PIyqvfNkpSIeSX0oNnnvBlUdBeh8dHsVnyV0ebAAKTRBdp20LH +sbI6GA60XYyzZl2hNPk2LEnb80b8s0RpRBNm/dfF/a82Tc4DTQdxz69qBdKiQ1oK +Um8BA06Oi6NCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD +VR0OBBYEFAG5L++/EYZg8k/QQW6rcx/n0m5JMAoGCCqGSM49BAMDA2kAMGYCMQCu +SuMrQMN0EfKVrRYj3k4MGuZdpSRea0R7/DjiT8ucRRcRTBQnJlU5dUoDzBOQn5IC +MQD6SmxgiHPz7riYYqnOK8LZiqZwMR2vsJRM60/G49HzYqc8/5MuB1xJAWdpEgJy +v+c= +-----END CERTIFICATE----- + +# Issuer: CN=GlobalSign Root R46 O=GlobalSign nv-sa +# Subject: CN=GlobalSign Root R46 O=GlobalSign nv-sa +# Label: "GlobalSign Root R46" +# Serial: 1552617688466950547958867513931858518042577 +# MD5 Fingerprint: c4:14:30:e4:fa:66:43:94:2a:6a:1b:24:5f:19:d0:ef +# SHA1 Fingerprint: 53:a2:b0:4b:ca:6b:d6:45:e6:39:8a:8e:c4:0d:d2:bf:77:c3:a2:90 +# SHA256 Fingerprint: 4f:a3:12:6d:8d:3a:11:d1:c4:85:5a:4f:80:7c:ba:d6:cf:91:9d:3a:5a:88:b0:3b:ea:2c:63:72:d9:3c:40:c9 +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgISEdK7udcjGJ5AXwqdLdDfJWfRMA0GCSqGSIb3DQEBDAUA +MEYxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYD +VQQDExNHbG9iYWxTaWduIFJvb3QgUjQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMy +MDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYt +c2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQCsrHQy6LNl5brtQyYdpokNRbopiLKkHWPd08EsCVeJ +OaFV6Wc0dwxu5FUdUiXSE2te4R2pt32JMl8Nnp8semNgQB+msLZ4j5lUlghYruQG +vGIFAha/r6gjA7aUD7xubMLL1aa7DOn2wQL7Id5m3RerdELv8HQvJfTqa1VbkNud +316HCkD7rRlr+/fKYIje2sGP1q7Vf9Q8g+7XFkyDRTNrJ9CG0Bwta/OrffGFqfUo +0q3v84RLHIf8E6M6cqJaESvWJ3En7YEtbWaBkoe0G1h6zD8K+kZPTXhc+CtI4wSE +y132tGqzZfxCnlEmIyDLPRT5ge1lFgBPGmSXZgjPjHvjK8Cd+RTyG/FWaha/LIWF +zXg4mutCagI0GIMXTpRW+LaCtfOW3T3zvn8gdz57GSNrLNRyc0NXfeD412lPFzYE ++cCQYDdF3uYM2HSNrpyibXRdQr4G9dlkbgIQrImwTDsHTUB+JMWKmIJ5jqSngiCN +I/onccnfxkF0oE32kRbcRoxfKWMxWXEM2G/CtjJ9++ZdU6Z+Ffy7dXxd7Pj2Fxzs +x2sZy/N78CsHpdlseVR2bJ0cpm4O6XkMqCNqo98bMDGfsVR7/mrLZqrcZdCinkqa +ByFrgY/bxFn63iLABJzjqls2k+g9vXqhnQt2sQvHnf3PmKgGwvgqo6GDoLclcqUC +4wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQUA1yrc4GHqMywptWU4jaWSf8FmSwwDQYJKoZIhvcNAQEMBQADggIBAHx4 +7PYCLLtbfpIrXTncvtgdokIzTfnvpCo7RGkerNlFo048p9gkUbJUHJNOxO97k4Vg +JuoJSOD1u8fpaNK7ajFxzHmuEajwmf3lH7wvqMxX63bEIaZHU1VNaL8FpO7XJqti +2kM3S+LGteWygxk6x9PbTZ4IevPuzz5i+6zoYMzRx6Fcg0XERczzF2sUyQQCPtIk +pnnpHs6i58FZFZ8d4kuaPp92CC1r2LpXFNqD6v6MVenQTqnMdzGxRBF6XLE+0xRF +FRhiJBPSy03OXIPBNvIQtQ6IbbjhVp+J3pZmOUdkLG5NrmJ7v2B0GbhWrJKsFjLt +rWhV/pi60zTe9Mlhww6G9kuEYO4Ne7UyWHmRVSyBQ7N0H3qqJZ4d16GLuc1CLgSk +ZoNNiTW2bKg2SnkheCLQQrzRQDGQob4Ez8pn7fXwgNNgyYMqIgXQBztSvwyeqiv5 +u+YfjyW6hY0XHgL+XVAEV8/+LbzvXMAaq7afJMbfc2hIkCwU9D9SGuTSyxTDYWnP +4vkYxboznxSjBF25cfe1lNj2M8FawTSLfJvdkzrnE6JwYZ+vj+vYxXX4M2bUdGc6 +N3ec592kD3ZDZopD8p/7DEJ4Y9HiD2971KE9dJeFt0g5QdYg/NA6s/rob8SKunE3 +vouXsXgxT7PntgMTzlSdriVZzH81Xwj3QEUxeCp6 +-----END CERTIFICATE----- + +# Issuer: CN=GlobalSign Root E46 O=GlobalSign nv-sa +# Subject: CN=GlobalSign Root E46 O=GlobalSign nv-sa +# Label: "GlobalSign Root E46" +# Serial: 1552617690338932563915843282459653771421763 +# MD5 Fingerprint: b5:b8:66:ed:de:08:83:e3:c9:e2:01:34:06:ac:51:6f +# SHA1 Fingerprint: 39:b4:6c:d5:fe:80:06:eb:e2:2f:4a:bb:08:33:a0:af:db:b9:dd:84 +# SHA256 Fingerprint: cb:b9:c4:4d:84:b8:04:3e:10:50:ea:31:a6:9f:51:49:55:d7:bf:d2:e2:c6:b4:93:01:01:9a:d6:1d:9f:50:58 +-----BEGIN CERTIFICATE----- +MIICCzCCAZGgAwIBAgISEdK7ujNu1LzmJGjFDYQdmOhDMAoGCCqGSM49BAMDMEYx +CzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQD +ExNHbG9iYWxTaWduIFJvb3QgRTQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAw +MDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2Ex +HDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAAScDrHPt+ieUnd1NPqlRqetMhkytAepJ8qUuwzSChDH2omwlwxwEwkBjtjq +R+q+soArzfwoDdusvKSGN+1wCAB16pMLey5SnCNoIwZD7JIvU4Tb+0cUB+hflGdd +yXqBPCCjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud +DgQWBBQxCpCPtsad0kRLgLWi5h+xEk8blTAKBggqhkjOPQQDAwNoADBlAjEA31SQ +7Zvvi5QCkxeCmb6zniz2C5GMn0oUsfZkvLtoURMMA/cVi4RguYv/Uo7njLwcAjA8 ++RHUjE7AwWHCFUyqqx0LMV87HOIAl0Qx5v5zli/altP+CAezNIm8BZ/3Hobui3A= +-----END CERTIFICATE----- + +# Issuer: CN=ANF Secure Server Root CA O=ANF Autoridad de Certificacion OU=ANF CA Raiz +# Subject: CN=ANF Secure Server Root CA O=ANF Autoridad de Certificacion OU=ANF CA Raiz +# Label: "ANF Secure Server Root CA" +# Serial: 996390341000653745 +# MD5 Fingerprint: 26:a6:44:5a:d9:af:4e:2f:b2:1d:b6:65:b0:4e:e8:96 +# SHA1 Fingerprint: 5b:6e:68:d0:cc:15:b6:a0:5f:1e:c1:5f:ae:02:fc:6b:2f:5d:6f:74 +# SHA256 Fingerprint: fb:8f:ec:75:91:69:b9:10:6b:1e:51:16:44:c6:18:c5:13:04:37:3f:6c:06:43:08:8d:8b:ef:fd:1b:99:75:99 +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +# Issuer: CN=Certum EC-384 CA O=Asseco Data Systems S.A. OU=Certum Certification Authority +# Subject: CN=Certum EC-384 CA O=Asseco Data Systems S.A. OU=Certum Certification Authority +# Label: "Certum EC-384 CA" +# Serial: 160250656287871593594747141429395092468 +# MD5 Fingerprint: b6:65:b3:96:60:97:12:a1:ec:4e:e1:3d:a3:c6:c9:f1 +# SHA1 Fingerprint: f3:3e:78:3c:ac:df:f4:a2:cc:ac:67:55:69:56:d7:e5:16:3c:e1:ed +# SHA256 Fingerprint: 6b:32:80:85:62:53:18:aa:50:d1:73:c9:8d:8b:da:09:d5:7e:27:41:3d:11:4c:f7:87:a0:f5:d0:6c:03:0c:f6 +-----BEGIN CERTIFICATE----- +MIICZTCCAeugAwIBAgIQeI8nXIESUiClBNAt3bpz9DAKBggqhkjOPQQDAzB0MQsw +CQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScw +JQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGTAXBgNVBAMT +EENlcnR1bSBFQy0zODQgQ0EwHhcNMTgwMzI2MDcyNDU0WhcNNDMwMzI2MDcyNDU0 +WjB0MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBT +LkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGTAX +BgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATE +KI6rGFtqvm5kN2PkzeyrOvfMobgOgknXhimfoZTy42B4mIF4Bk3y7JoOV2CDn7Tm +Fy8as10CW4kjPMIRBSqniBMY81CE1700LCeJVf/OTOffph8oxPBUw7l8t1Ot68Kj +QjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI0GZnQkdjrzife81r1HfS+8 +EF9LMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNoADBlAjADVS2m5hjEfO/J +UG7BJw+ch69u1RsIGL2SKcHvlJF40jocVYli5RsJHrpka/F2tNQCMQC0QoSZ/6vn +nvuRlydd3LBbMHHOXjgaatkl5+r3YZJW+OraNsKHZZYuciUvf9/DE8k= +-----END CERTIFICATE----- + +# Issuer: CN=Certum Trusted Root CA O=Asseco Data Systems S.A. OU=Certum Certification Authority +# Subject: CN=Certum Trusted Root CA O=Asseco Data Systems S.A. OU=Certum Certification Authority +# Label: "Certum Trusted Root CA" +# Serial: 40870380103424195783807378461123655149 +# MD5 Fingerprint: 51:e1:c2:e7:fe:4c:84:af:59:0e:2f:f4:54:6f:ea:29 +# SHA1 Fingerprint: c8:83:44:c0:18:ae:9f:cc:f1:87:b7:8f:22:d1:c5:d7:45:84:ba:e5 +# SHA256 Fingerprint: fe:76:96:57:38:55:77:3e:37:a9:5e:7a:d4:d9:cc:96:c3:01:57:c1:5d:31:76:5b:a9:b1:57:04:e1:ae:78:fd +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +# Issuer: CN=TunTrust Root CA O=Agence Nationale de Certification Electronique +# Subject: CN=TunTrust Root CA O=Agence Nationale de Certification Electronique +# Label: "TunTrust Root CA" +# Serial: 108534058042236574382096126452369648152337120275 +# MD5 Fingerprint: 85:13:b9:90:5b:36:5c:b6:5e:b8:5a:f8:e0:31:57:b4 +# SHA1 Fingerprint: cf:e9:70:84:0f:e0:73:0f:9d:f6:0c:7f:2c:4b:ee:20:46:34:9c:bb +# SHA256 Fingerprint: 2e:44:10:2a:b5:8c:b8:54:19:45:1c:8e:19:d9:ac:f3:66:2c:af:bc:61:4b:6a:53:96:0a:30:f7:d0:e2:eb:41 +-----BEGIN CERTIFICATE----- +MIIFszCCA5ugAwIBAgIUEwLV4kBMkkaGFmddtLu7sms+/BMwDQYJKoZIhvcNAQEL +BQAwYTELMAkGA1UEBhMCVE4xNzA1BgNVBAoMLkFnZW5jZSBOYXRpb25hbGUgZGUg +Q2VydGlmaWNhdGlvbiBFbGVjdHJvbmlxdWUxGTAXBgNVBAMMEFR1blRydXN0IFJv +b3QgQ0EwHhcNMTkwNDI2MDg1NzU2WhcNNDQwNDI2MDg1NzU2WjBhMQswCQYDVQQG +EwJUTjE3MDUGA1UECgwuQWdlbmNlIE5hdGlvbmFsZSBkZSBDZXJ0aWZpY2F0aW9u +IEVsZWN0cm9uaXF1ZTEZMBcGA1UEAwwQVHVuVHJ1c3QgUm9vdCBDQTCCAiIwDQYJ +KoZIhvcNAQEBBQADggIPADCCAgoCggIBAMPN0/y9BFPdDCA61YguBUtB9YOCfvdZ +n56eY+hz2vYGqU8ftPkLHzmMmiDQfgbU7DTZhrx1W4eI8NLZ1KMKsmwb60ksPqxd +2JQDoOw05TDENX37Jk0bbjBU2PWARZw5rZzJJQRNmpA+TkBuimvNKWfGzC3gdOgF +VwpIUPp6Q9p+7FuaDmJ2/uqdHYVy7BG7NegfJ7/Boce7SBbdVtfMTqDhuazb1YMZ +GoXRlJfXyqNlC/M4+QKu3fZnz8k/9YosRxqZbwUN/dAdgjH8KcwAWJeRTIAAHDOF +li/LQcKLEITDCSSJH7UP2dl3RxiSlGBcx5kDPP73lad9UKGAwqmDrViWVSHbhlnU +r8a83YFuB9tgYv7sEG7aaAH0gxupPqJbI9dkxt/con3YS7qC0lH4Zr8GRuR5KiY2 +eY8fTpkdso8MDhz/yV3A/ZAQprE38806JG60hZC/gLkMjNWb1sjxVj8agIl6qeIb +MlEsPvLfe/ZdeikZjuXIvTZxi11Mwh0/rViizz1wTaZQmCXcI/m4WEEIcb9PuISg +jwBUFfyRbVinljvrS5YnzWuioYasDXxU5mZMZl+QviGaAkYt5IPCgLnPSz7ofzwB +7I9ezX/SKEIBlYrilz0QIX32nRzFNKHsLA4KUiwSVXAkPcvCFDVDXSdOvsC9qnyW +5/yeYa1E0wCXAgMBAAGjYzBhMB0GA1UdDgQWBBQGmpsfU33x9aTI04Y+oXNZtPdE +ITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFAaamx9TffH1pMjThj6hc1m0 +90QhMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAqgVutt0Vyb+z +xiD2BkewhpMl0425yAA/l/VSJ4hxyXT968pk21vvHl26v9Hr7lxpuhbI87mP0zYu +QEkHDVneixCwSQXi/5E/S7fdAo74gShczNxtr18UnH1YeA32gAm56Q6XKRm4t+v4 +FstVEuTGfbvE7Pi1HE4+Z7/FXxttbUcoqgRYYdZ2vyJ/0Adqp2RT8JeNnYA/u8EH +22Wv5psymsNUk8QcCMNE+3tjEUPRahphanltkE8pjkcFwRJpadbGNjHh/PqAulxP +xOu3Mqz4dWEX1xAZufHSCe96Qp1bWgvUxpVOKs7/B9dPfhgGiPEZtdmYu65xxBzn +dFlY7wyJz4sfdZMaBBSSSFCp61cpABbjNhzI+L/wM9VBD8TMPN3pM0MBkRArHtG5 +Xc0yGYuPjCB31yLEQtyEFpslbei0VXF/sHyz03FJuc9SpAQ/3D2gu68zngowYI7b +nV2UqL1g52KAdoGDDIzMMEZJ4gzSqK/rYXHv5yJiqfdcZGyfFoxnNidF9Ql7v/YQ +CvGwjVRDjAS6oz/v4jXH+XTgbzRB0L9zZVcg+ZtnemZoJE6AZb0QmQZZ8mWvuMZH +u/2QeItBcy6vVR/cO5JyboTT0GFMDcx2V+IthSIVNg3rAZ3r2OvEhJn7wAzMMujj +d9qDRIueVSjAi1jTkD5OGwDxFa2DK5o= +-----END CERTIFICATE----- + +# Issuer: CN=HARICA TLS RSA Root CA 2021 O=Hellenic Academic and Research Institutions CA +# Subject: CN=HARICA TLS RSA Root CA 2021 O=Hellenic Academic and Research Institutions CA +# Label: "HARICA TLS RSA Root CA 2021" +# Serial: 76817823531813593706434026085292783742 +# MD5 Fingerprint: 65:47:9b:58:86:dd:2c:f0:fc:a2:84:1f:1e:96:c4:91 +# SHA1 Fingerprint: 02:2d:05:82:fa:88:ce:14:0c:06:79:de:7f:14:10:e9:45:d7:a5:6d +# SHA256 Fingerprint: d9:5d:0e:8e:da:79:52:5b:f9:be:b1:1b:14:d2:10:0d:32:94:98:5f:0c:62:d9:fa:bd:9c:d9:99:ec:cb:7b:1d +-----BEGIN CERTIFICATE----- +MIIFpDCCA4ygAwIBAgIQOcqTHO9D88aOk8f0ZIk4fjANBgkqhkiG9w0BAQsFADBs +MQswCQYDVQQGEwJHUjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl +c2VhcmNoIEluc3RpdHV0aW9ucyBDQTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBSU0Eg +Um9vdCBDQSAyMDIxMB4XDTIxMDIxOTEwNTUzOFoXDTQ1MDIxMzEwNTUzN1owbDEL +MAkGA1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNl +YXJjaCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgUlNBIFJv +b3QgQ0EgMjAyMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAIvC569l +mwVnlskNJLnQDmT8zuIkGCyEf3dRywQRNrhe7Wlxp57kJQmXZ8FHws+RFjZiPTgE +4VGC/6zStGndLuwRo0Xua2s7TL+MjaQenRG56Tj5eg4MmOIjHdFOY9TnuEFE+2uv +a9of08WRiFukiZLRgeaMOVig1mlDqa2YUlhu2wr7a89o+uOkXjpFc5gH6l8Cct4M +pbOfrqkdtx2z/IpZ525yZa31MJQjB/OCFks1mJxTuy/K5FrZx40d/JiZ+yykgmvw +Kh+OC19xXFyuQnspiYHLA6OZyoieC0AJQTPb5lh6/a6ZcMBaD9YThnEvdmn8kN3b +LW7R8pv1GmuebxWMevBLKKAiOIAkbDakO/IwkfN4E8/BPzWr8R0RI7VDIp4BkrcY +AuUR0YLbFQDMYTfBKnya4dC6s1BG7oKsnTH4+yPiAwBIcKMJJnkVU2DzOFytOOqB +AGMUuTNe3QvboEUHGjMJ+E20pwKmafTCWQWIZYVWrkvL4N48fS0ayOn7H6NhStYq +E613TBoYm5EPWNgGVMWX+Ko/IIqmhaZ39qb8HOLubpQzKoNQhArlT4b4UEV4AIHr +W2jjJo3Me1xR9BQsQL4aYB16cmEdH2MtiKrOokWQCPxrvrNQKlr9qEgYRtaQQJKQ +CoReaDH46+0N0x3GfZkYVVYnZS6NRcUk7M7jAgMBAAGjQjBAMA8GA1UdEwEB/wQF +MAMBAf8wHQYDVR0OBBYEFApII6ZgpJIKM+qTW8VX6iVNvRLuMA4GA1UdDwEB/wQE +AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAPpBIqm5iFSVmewzVjIuJndftTgfvnNAU +X15QvWiWkKQUEapobQk1OUAJ2vQJLDSle1mESSmXdMgHHkdt8s4cUCbjnj1AUz/3 +f5Z2EMVGpdAgS1D0NTsY9FVqQRtHBmg8uwkIYtlfVUKqrFOFrJVWNlar5AWMxaja +H6NpvVMPxP/cyuN+8kyIhkdGGvMA9YCRotxDQpSbIPDRzbLrLFPCU3hKTwSUQZqP +JzLB5UkZv/HywouoCjkxKLR9YjYsTewfM7Z+d21+UPCfDtcRj88YxeMn/ibvBZ3P +zzfF0HvaO7AWhAw6k9a+F9sPPg4ZeAnHqQJyIkv3N3a6dcSFA1pj1bF1BcK5vZSt +jBWZp5N99sXzqnTPBIWUmAD04vnKJGW/4GKvyMX6ssmeVkjaef2WdhW+o45WxLM0 +/L5H9MG0qPzVMIho7suuyWPEdr6sOBjhXlzPrjoiUevRi7PzKzMHVIf6tLITe7pT +BGIBnfHAT+7hOtSLIBD6Alfm78ELt5BGnBkpjNxvoEppaZS3JGWg/6w/zgH7IS79 +aPib8qXPMThcFarmlwDB31qlpzmq6YR/PFGoOtmUW4y/Twhx5duoXNTSpv4Ao8YW +xw/ogM4cKGR0GQjTQuPOAF1/sdwTsOEFy9EgqoZ0njnnkf3/W9b3raYvAwtt41dU +63ZTGI0RmLo= +-----END CERTIFICATE----- + +# Issuer: CN=HARICA TLS ECC Root CA 2021 O=Hellenic Academic and Research Institutions CA +# Subject: CN=HARICA TLS ECC Root CA 2021 O=Hellenic Academic and Research Institutions CA +# Label: "HARICA TLS ECC Root CA 2021" +# Serial: 137515985548005187474074462014555733966 +# MD5 Fingerprint: ae:f7:4c:e5:66:35:d1:b7:9b:8c:22:93:74:d3:4b:b0 +# SHA1 Fingerprint: bc:b0:c1:9d:e9:98:92:70:19:38:57:e9:8d:a7:b4:5d:6e:ee:01:48 +# SHA256 Fingerprint: 3f:99:cc:47:4a:cf:ce:4d:fe:d5:87:94:66:5e:47:8d:15:47:73:9f:2e:78:0f:1b:b4:ca:9b:13:30:97:d4:01 +-----BEGIN CERTIFICATE----- +MIICVDCCAdugAwIBAgIQZ3SdjXfYO2rbIvT/WeK/zjAKBggqhkjOPQQDAzBsMQsw +CQYDVQQGEwJHUjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2Vh +cmNoIEluc3RpdHV0aW9ucyBDQTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBFQ0MgUm9v +dCBDQSAyMDIxMB4XDTIxMDIxOTExMDExMFoXDTQ1MDIxMzExMDEwOVowbDELMAkG +A1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj +aCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgRUNDIFJvb3Qg +Q0EgMjAyMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABDgI/rGgltJ6rK9JOtDA4MM7 +KKrxcm1lAEeIhPyaJmuqS7psBAqIXhfyVYf8MLA04jRYVxqEU+kw2anylnTDUR9Y +STHMmE5gEYd103KUkE+bECUqqHgtvpBBWJAVcqeht6NCMEAwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUyRtTgRL+BNUW0aq8mm+3oJUZbsowDgYDVR0PAQH/BAQD +AgGGMAoGCCqGSM49BAMDA2cAMGQCMBHervjcToiwqfAircJRQO9gcS3ujwLEXQNw +SaSS6sUUiHCm0w2wqsosQJz76YJumgIwK0eaB8bRwoF8yguWGEEbo/QwCZ61IygN +nxS2PFOiTAZpffpskcYqSUXm7LcT4Tps +-----END CERTIFICATE----- + +# Issuer: CN=Autoridad de Certificacion Firmaprofesional CIF A62634068 +# Subject: CN=Autoridad de Certificacion Firmaprofesional CIF A62634068 +# Label: "Autoridad de Certificacion Firmaprofesional CIF A62634068" +# Serial: 1977337328857672817 +# MD5 Fingerprint: 4e:6e:9b:54:4c:ca:b7:fa:48:e4:90:b1:15:4b:1c:a3 +# SHA1 Fingerprint: 0b:be:c2:27:22:49:cb:39:aa:db:35:5c:53:e3:8c:ae:78:ff:b6:fe +# SHA256 Fingerprint: 57:de:05:83:ef:d2:b2:6e:03:61:da:99:da:9d:f4:64:8d:ef:7e:e8:44:1c:3b:72:8a:fa:9b:cd:e0:f9:b2:6a +-----BEGIN CERTIFICATE----- +MIIGFDCCA/ygAwIBAgIIG3Dp0v+ubHEwDQYJKoZIhvcNAQELBQAwUTELMAkGA1UE +BhMCRVMxQjBABgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1h +cHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODAeFw0xNDA5MjMxNTIyMDdaFw0zNjA1 +MDUxNTIyMDdaMFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUg +Q2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjgwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDDUtd9 +thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQM +cas9UX4PB99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefG +L9ItWY16Ck6WaVICqjaY7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15i +NA9wBj4gGFrO93IbJWyTdBSTo3OxDqqHECNZXyAFGUftaI6SEspd/NYrspI8IM/h +X68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyIplD9amML9ZMWGxmPsu2b +m8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctXMbScyJCy +Z/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirja +EbsXLZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/T +KI8xWVvTyQKmtFLKbpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF +6NkBiDkal4ZkQdU7hwxu+g/GvUgUvzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVh +OSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMB0GA1UdDgQWBBRlzeurNR4APn7VdMAc +tHNHDhpkLzASBgNVHRMBAf8ECDAGAQH/AgEBMIGmBgNVHSAEgZ4wgZswgZgGBFUd +IAAwgY8wLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuZmlybWFwcm9mZXNpb25hbC5j +b20vY3BzMFwGCCsGAQUFBwICMFAeTgBQAGEAcwBlAG8AIABkAGUAIABsAGEAIABC +AG8AbgBhAG4AbwB2AGEAIAA0ADcAIABCAGEAcgBjAGUAbABvAG4AYQAgADAAOAAw +ADEANzAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggIBAHSHKAIrdx9m +iWTtj3QuRhy7qPj4Cx2Dtjqn6EWKB7fgPiDL4QjbEwj4KKE1soCzC1HA01aajTNF +Sa9J8OA9B3pFE1r/yJfY0xgsfZb43aJlQ3CTkBW6kN/oGbDbLIpgD7dvlAceHabJ +hfa9NPhAeGIQcDq+fUs5gakQ1JZBu/hfHAsdCPKxsIl68veg4MSPi3i1O1ilI45P +Vf42O+AMt8oqMEEgtIDNrvx2ZnOorm7hfNoD6JQg5iKj0B+QXSBTFCZX2lSX3xZE +EAEeiGaPcjiT3SC3NL7X8e5jjkd5KAb881lFJWAiMxujX6i6KtoaPc1A6ozuBRWV +1aUsIC+nmCjuRfzxuIgALI9C2lHVnOUTaHFFQ4ueCyE8S1wF3BqfmI7avSKecs2t +CsvMo2ebKHTEm9caPARYpoKdrcd7b/+Alun4jWq9GJAd/0kakFI3ky88Al2CdgtR +5xbHV/g4+afNmyJU72OwFW1TZQNKXkqgsqeOSQBZONXH9IBk9W6VULgRfhVwOEqw +f9DEMnDAGf/JOC0ULGb0QkTmVXYbgBVX/8Cnp6o5qtjTcNAuuuuUavpfNIbnYrX9 +ivAwhZTJryQCL2/W3Wf+47BVTwSYT6RBVuKT0Gro1vP7ZeDOdcQxWQzugsgMYDNK +GbqEZycPvEJdvSRUDewdcAZfpLz6IHxV +-----END CERTIFICATE----- + +# Issuer: CN=vTrus ECC Root CA O=iTrusChina Co.,Ltd. +# Subject: CN=vTrus ECC Root CA O=iTrusChina Co.,Ltd. +# Label: "vTrus ECC Root CA" +# Serial: 630369271402956006249506845124680065938238527194 +# MD5 Fingerprint: de:4b:c1:f5:52:8c:9b:43:e1:3e:8f:55:54:17:8d:85 +# SHA1 Fingerprint: f6:9c:db:b0:fc:f6:02:13:b6:52:32:a6:a3:91:3f:16:70:da:c3:e1 +# SHA256 Fingerprint: 30:fb:ba:2c:32:23:8e:2a:98:54:7a:f9:79:31:e5:50:42:8b:9b:3f:1c:8e:eb:66:33:dc:fa:86:c5:b2:7d:d3 +-----BEGIN CERTIFICATE----- +MIICDzCCAZWgAwIBAgIUbmq8WapTvpg5Z6LSa6Q75m0c1towCgYIKoZIzj0EAwMw +RzELMAkGA1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xGjAY +BgNVBAMTEXZUcnVzIEVDQyBSb290IENBMB4XDTE4MDczMTA3MjY0NFoXDTQzMDcz +MTA3MjY0NFowRzELMAkGA1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28u +LEx0ZC4xGjAYBgNVBAMTEXZUcnVzIEVDQyBSb290IENBMHYwEAYHKoZIzj0CAQYF +K4EEACIDYgAEZVBKrox5lkqqHAjDo6LN/llWQXf9JpRCux3NCNtzslt188+cToL0 +v/hhJoVs1oVbcnDS/dtitN9Ti72xRFhiQgnH+n9bEOf+QP3A2MMrMudwpremIFUd +e4BdS49nTPEQo0IwQDAdBgNVHQ4EFgQUmDnNvtiyjPeyq+GtJK97fKHbH88wDwYD +VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwCgYIKoZIzj0EAwMDaAAwZQIw +V53dVvHH4+m4SVBrm2nDb+zDfSXkV5UTQJtS0zvzQBm8JsctBp61ezaf9SXUY2sA +AjEA6dPGnlaaKsyh2j/IZivTWJwghfqrkYpwcBE4YGQLYgmRWAD5Tfs0aNoJrSEG +GJTO +-----END CERTIFICATE----- + +# Issuer: CN=vTrus Root CA O=iTrusChina Co.,Ltd. +# Subject: CN=vTrus Root CA O=iTrusChina Co.,Ltd. +# Label: "vTrus Root CA" +# Serial: 387574501246983434957692974888460947164905180485 +# MD5 Fingerprint: b8:c9:37:df:fa:6b:31:84:64:c5:ea:11:6a:1b:75:fc +# SHA1 Fingerprint: 84:1a:69:fb:f5:cd:1a:25:34:13:3d:e3:f8:fc:b8:99:d0:c9:14:b7 +# SHA256 Fingerprint: 8a:71:de:65:59:33:6f:42:6c:26:e5:38:80:d0:0d:88:a1:8d:a4:c6:a9:1f:0d:cb:61:94:e2:06:c5:c9:63:87 +-----BEGIN CERTIFICATE----- +MIIFVjCCAz6gAwIBAgIUQ+NxE9izWRRdt86M/TX9b7wFjUUwDQYJKoZIhvcNAQEL +BQAwQzELMAkGA1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4x +FjAUBgNVBAMTDXZUcnVzIFJvb3QgQ0EwHhcNMTgwNzMxMDcyNDA1WhcNNDMwNzMx +MDcyNDA1WjBDMQswCQYDVQQGEwJDTjEcMBoGA1UEChMTaVRydXNDaGluYSBDby4s +THRkLjEWMBQGA1UEAxMNdlRydXMgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQAD +ggIPADCCAgoCggIBAL1VfGHTuB0EYgWgrmy3cLRB6ksDXhA/kFocizuwZotsSKYc +IrrVQJLuM7IjWcmOvFjai57QGfIvWcaMY1q6n6MLsLOaXLoRuBLpDLvPbmyAhykU +AyyNJJrIZIO1aqwTLDPxn9wsYTwaP3BVm60AUn/PBLn+NvqcwBauYv6WTEN+VRS+ +GrPSbcKvdmaVayqwlHeFXgQPYh1jdfdr58tbmnDsPmcF8P4HCIDPKNsFxhQnL4Z9 +8Cfe/+Z+M0jnCx5Y0ScrUw5XSmXX+6KAYPxMvDVTAWqXcoKv8R1w6Jz1717CbMdH +flqUhSZNO7rrTOiwCcJlwp2dCZtOtZcFrPUGoPc2BX70kLJrxLT5ZOrpGgrIDajt +J8nU57O5q4IikCc9Kuh8kO+8T/3iCiSn3mUkpF3qwHYw03dQ+A0Em5Q2AXPKBlim +0zvc+gRGE1WKyURHuFE5Gi7oNOJ5y1lKCn+8pu8fA2dqWSslYpPZUxlmPCdiKYZN +pGvu/9ROutW04o5IWgAZCfEF2c6Rsffr6TlP9m8EQ5pV9T4FFL2/s1m02I4zhKOQ +UqqzApVg+QxMaPnu1RcN+HFXtSXkKe5lXa/R7jwXC1pDxaWG6iSe4gUH3DRCEpHW +OXSuTEGC2/KmSNGzm/MzqvOmwMVO9fSddmPmAsYiS8GVP1BkLFTltvA8Kc9XAgMB +AAGjQjBAMB0GA1UdDgQWBBRUYnBj8XWEQ1iO0RYgscasGrz2iTAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAKbqSSaet +8PFww+SX8J+pJdVrnjT+5hpk9jprUrIQeBqfTNqK2uwcN1LgQkv7bHbKJAs5EhWd +nxEt/Hlk3ODg9d3gV8mlsnZwUKT+twpw1aA08XXXTUm6EdGz2OyC/+sOxL9kLX1j +bhd47F18iMjrjld22VkE+rxSH0Ws8HqA7Oxvdq6R2xCOBNyS36D25q5J08FsEhvM +Kar5CKXiNxTKsbhm7xqC5PD48acWabfbqWE8n/Uxy+QARsIvdLGx14HuqCaVvIiv +TDUHKgLKeBRtRytAVunLKmChZwOgzoy8sHJnxDHO2zTlJQNgJXtxmOTAGytfdELS +S8VZCAeHvsXDf+eW2eHcKJfWjwXj9ZtOyh1QRwVTsMo554WgicEFOwE30z9J4nfr +I8iIZjs9OXYhRvHsXyO466JmdXTBQPfYaJqT4i2pLr0cox7IdMakLXogqzu4sEb9 +b91fUlV1YvCXoHzXOP0l382gmxDPi7g4Xl7FtKYCNqEeXxzP4padKar9mK5S4fNB +UvupLnKWnyfjqnN9+BojZns7q2WwMgFLFT49ok8MKzWixtlnEjUwzXYuFrOZnk1P +Ti07NEPhmg4NpGaXutIcSkwsKouLgU9xGqndXHt7CMUADTdA43x7VF8vhV929ven +sBxXVsFy6K2ir40zSbofitzmdHxghm+Hl3s= +-----END CERTIFICATE----- + +# Issuer: CN=ISRG Root X2 O=Internet Security Research Group +# Subject: CN=ISRG Root X2 O=Internet Security Research Group +# Label: "ISRG Root X2" +# Serial: 87493402998870891108772069816698636114 +# MD5 Fingerprint: d3:9e:c4:1e:23:3c:a6:df:cf:a3:7e:6d:e0:14:e6:e5 +# SHA1 Fingerprint: bd:b1:b9:3c:d5:97:8d:45:c6:26:14:55:f8:db:95:c7:5a:d1:53:af +# SHA256 Fingerprint: 69:72:9b:8e:15:a8:6e:fc:17:7a:57:af:b7:17:1d:fc:64:ad:d2:8c:2f:ca:8c:f1:50:7e:34:45:3c:cb:14:70 +-----BEGIN CERTIFICATE----- +MIICGzCCAaGgAwIBAgIQQdKd0XLq7qeAwSxs6S+HUjAKBggqhkjOPQQDAzBPMQsw +CQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2gg +R3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMjAeFw0yMDA5MDQwMDAwMDBaFw00 +MDA5MTcxNjAwMDBaME8xCzAJBgNVBAYTAlVTMSkwJwYDVQQKEyBJbnRlcm5ldCBT +ZWN1cml0eSBSZXNlYXJjaCBHcm91cDEVMBMGA1UEAxMMSVNSRyBSb290IFgyMHYw +EAYHKoZIzj0CAQYFK4EEACIDYgAEzZvVn4CDCuwJSvMWSj5cz3es3mcFDR0HttwW ++1qLFNvicWDEukWVEYmO6gbf9yoWHKS5xcUy4APgHoIYOIvXRdgKam7mAHf7AlF9 +ItgKbppbd9/w+kHsOdx1ymgHDB/qo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0T +AQH/BAUwAwEB/zAdBgNVHQ4EFgQUfEKWrt5LSDv6kviejM9ti6lyN5UwCgYIKoZI +zj0EAwMDaAAwZQIwe3lORlCEwkSHRhtFcP9Ymd70/aTSVaYgLXTWNLxBo1BfASdW +tL4ndQavEi51mI38AjEAi/V3bNTIZargCyzuFJ0nN6T5U6VR5CmD1/iQMVtCnwr1 +/q4AaOeMSQ+2b1tbFfLn +-----END CERTIFICATE----- + +# Issuer: CN=HiPKI Root CA - G1 O=Chunghwa Telecom Co., Ltd. +# Subject: CN=HiPKI Root CA - G1 O=Chunghwa Telecom Co., Ltd. +# Label: "HiPKI Root CA - G1" +# Serial: 60966262342023497858655262305426234976 +# MD5 Fingerprint: 69:45:df:16:65:4b:e8:68:9a:8f:76:5f:ff:80:9e:d3 +# SHA1 Fingerprint: 6a:92:e4:a8:ee:1b:ec:96:45:37:e3:29:57:49:cd:96:e3:e5:d2:60 +# SHA256 Fingerprint: f0:15:ce:3c:c2:39:bf:ef:06:4b:e9:f1:d2:c4:17:e1:a0:26:4a:0a:94:be:1f:0c:8d:12:18:64:eb:69:49:cc +-----BEGIN CERTIFICATE----- +MIIFajCCA1KgAwIBAgIQLd2szmKXlKFD6LDNdmpeYDANBgkqhkiG9w0BAQsFADBP +MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0 +ZC4xGzAZBgNVBAMMEkhpUEtJIFJvb3QgQ0EgLSBHMTAeFw0xOTAyMjIwOTQ2MDRa +Fw0zNzEyMzExNTU5NTlaME8xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3 +YSBUZWxlY29tIENvLiwgTHRkLjEbMBkGA1UEAwwSSGlQS0kgUm9vdCBDQSAtIEcx +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA9B5/UnMyDHPkvRN0o9Qw +qNCuS9i233VHZvR85zkEHmpwINJaR3JnVfSl6J3VHiGh8Ge6zCFovkRTv4354twv +Vcg3Px+kwJyz5HdcoEb+d/oaoDjq7Zpy3iu9lFc6uux55199QmQ5eiY29yTw1S+6 +lZgRZq2XNdZ1AYDgr/SEYYwNHl98h5ZeQa/rh+r4XfEuiAU+TCK72h8q3VJGZDnz +Qs7ZngyzsHeXZJzA9KMuH5UHsBffMNsAGJZMoYFL3QRtU6M9/Aes1MU3guvklQgZ +KILSQjqj2FPseYlgSGDIcpJQ3AOPgz+yQlda22rpEZfdhSi8MEyr48KxRURHH+CK +FgeW0iEPU8DtqX7UTuybCeyvQqww1r/REEXgphaypcXTT3OUM3ECoWqj1jOXTyFj +HluP2cFeRXF3D4FdXyGarYPM+l7WjSNfGz1BryB1ZlpK9p/7qxj3ccC2HTHsOyDr +y+K49a6SsvfhhEvyovKTmiKe0xRvNlS9H15ZFblzqMF8b3ti6RZsR1pl8w4Rm0bZ +/W3c1pzAtH2lsN0/Vm+h+fbkEkj9Bn8SV7apI09bA8PgcSojt/ewsTu8mL3WmKgM +a/aOEmem8rJY5AIJEzypuxC00jBF8ez3ABHfZfjcK0NVvxaXxA/VLGGEqnKG/uY6 +fsI/fe78LxQ+5oXdUG+3Se0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQU8ncX+l6o/vY9cdVouslGDDjYr7AwDgYDVR0PAQH/BAQDAgGGMA0GCSqG +SIb3DQEBCwUAA4ICAQBQUfB13HAE4/+qddRxosuej6ip0691x1TPOhwEmSKsxBHi +7zNKpiMdDg1H2DfHb680f0+BazVP6XKlMeJ45/dOlBhbQH3PayFUhuaVevvGyuqc +SE5XCV0vrPSltJczWNWseanMX/mF+lLFjfiRFOs6DRfQUsJ748JzjkZ4Bjgs6Fza +ZsT0pPBWGTMpWmWSBUdGSquEwx4noR8RkpkndZMPvDY7l1ePJlsMu5wP1G4wB9Tc +XzZoZjmDlicmisjEOf6aIW/Vcobpf2Lll07QJNBAsNB1CI69aO4I1258EHBGG3zg +iLKecoaZAeO/n0kZtCW+VmWuF2PlHt/o/0elv+EmBYTksMCv5wiZqAxeJoBF1Pho +L5aPruJKHJwWDBNvOIf2u8g0X5IDUXlwpt/L9ZlNec1OvFefQ05rLisY+GpzjLrF +Ne85akEez3GoorKGB1s6yeHvP2UEgEcyRHCVTjFnanRbEEV16rCf0OY1/k6fi8wr +kkVbbiVghUbN0aqwdmaTd5a+g744tiROJgvM7XpWGuDpWsZkrUx6AEhEL7lAuxM+ +vhV4nYWBSipX3tUZQ9rbyltHhoMLP7YNdnhzeSJesYAfz77RP1YQmCuVh6EfnWQU +YDksswBVLuT1sw5XxJFBAJw/6KXf6vb/yPCtbVKoF6ubYfwSUTXkJf2vqmqGOQ== +-----END CERTIFICATE----- + +# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R4 +# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R4 +# Label: "GlobalSign ECC Root CA - R4" +# Serial: 159662223612894884239637590694 +# MD5 Fingerprint: 26:29:f8:6d:e1:88:bf:a2:65:7f:aa:c4:cd:0f:7f:fc +# SHA1 Fingerprint: 6b:a0:b0:98:e1:71:ef:5a:ad:fe:48:15:80:77:10:f4:bd:6f:0b:28 +# SHA256 Fingerprint: b0:85:d7:0b:96:4f:19:1a:73:e4:af:0d:54:ae:7a:0e:07:aa:fd:af:9b:71:dd:08:62:13:8a:b7:32:5a:24:a2 +-----BEGIN CERTIFICATE----- +MIIB3DCCAYOgAwIBAgINAgPlfvU/k/2lCSGypjAKBggqhkjOPQQDAjBQMSQwIgYD +VQQLExtHbG9iYWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2Jh +bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTIxMTEzMDAwMDAwWhcNMzgw +MTE5MDMxNDA3WjBQMSQwIgYDVQQLExtHbG9iYWxTaWduIEVDQyBSb290IENBIC0g +UjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wWTAT +BgcqhkjOPQIBBggqhkjOPQMBBwNCAAS4xnnTj2wlDp8uORkcA6SumuU5BwkWymOx +uYb4ilfBV85C+nOh92VC/x7BALJucw7/xyHlGKSq2XE/qNS5zowdo0IwQDAOBgNV +HQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVLB7rUW44kB/ ++wpu+74zyTyjhNUwCgYIKoZIzj0EAwIDRwAwRAIgIk90crlgr/HmnKAWBVBfw147 +bmF0774BxL4YSFlhgjICICadVGNA3jdgUM/I2O2dgq43mLyjj0xMqTQrbO/7lZsm +-----END CERTIFICATE----- + +# Issuer: CN=GTS Root R1 O=Google Trust Services LLC +# Subject: CN=GTS Root R1 O=Google Trust Services LLC +# Label: "GTS Root R1" +# Serial: 159662320309726417404178440727 +# MD5 Fingerprint: 05:fe:d0:bf:71:a8:a3:76:63:da:01:e0:d8:52:dc:40 +# SHA1 Fingerprint: e5:8c:1c:c4:91:3b:38:63:4b:e9:10:6e:e3:ad:8e:6b:9d:d9:81:4a +# SHA256 Fingerprint: d9:47:43:2a:bd:e7:b7:fa:90:fc:2e:6b:59:10:1b:12:80:e0:e1:c7:e4:e4:0f:a3:c6:88:7f:ff:57:a7:f4:cf +-----BEGIN CERTIFICATE----- +MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQsw +CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU +MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw +MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp +Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaMf/vo +27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7w +Cl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjw +TcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0Pfybl +qAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaH +szVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4Zor8 +Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUspzBmk +MiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92 +wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70p +aDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrN +VjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQID +AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E +FgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBAJ+qQibb +C5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe +QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuy +h6f88/qBVRRiClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM4 +7HLwEXWdyzRSjeZ2axfG34arJ45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8J +ZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYciNuaCp+0KueIHoI17eko8cdLiA6Ef +MgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5meLMFrUKTX5hgUvYU/ +Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJFfbdT +6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ +0E6yove+7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm +2tIMPNuzjsmhDYAPexZ3FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bb +bP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3gm3c +-----END CERTIFICATE----- + +# Issuer: CN=GTS Root R2 O=Google Trust Services LLC +# Subject: CN=GTS Root R2 O=Google Trust Services LLC +# Label: "GTS Root R2" +# Serial: 159662449406622349769042896298 +# MD5 Fingerprint: 1e:39:c0:53:e6:1e:29:82:0b:ca:52:55:36:5d:57:dc +# SHA1 Fingerprint: 9a:44:49:76:32:db:de:fa:d0:bc:fb:5a:7b:17:bd:9e:56:09:24:94 +# SHA256 Fingerprint: 8d:25:cd:97:22:9d:bf:70:35:6b:da:4e:b3:cc:73:40:31:e2:4c:f0:0f:af:cf:d3:2d:c7:6e:b5:84:1c:7e:a8 +-----BEGIN CERTIFICATE----- +MIIFVzCCAz+gAwIBAgINAgPlrsWNBCUaqxElqjANBgkqhkiG9w0BAQwFADBHMQsw +CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU +MBIGA1UEAxMLR1RTIFJvb3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw +MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp +Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3LvCvpt +nfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3KgGjSY +6Dlo7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9BuXvAu +MC6C/Pq8tBcKSOWIm8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOdre7k +RXuJVfeKH2JShBKzwkCX44ofR5GmdFrS+LFjKBC4swm4VndAoiaYecb+3yXuPuWg +f9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7MkogwTZq9TwtImoS1mKPV ++3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJGr61K8Yzo +dDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqjx5RW +Ir9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsRnTKa +G73VululycslaVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0kzCq +gc7dGtxRcw1PcOnlthYhGXmy5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9OktwID +AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E +FgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQADggIBAB/Kzt3H +vqGf2SdMC9wXmBFqiN495nFWcrKeGk6c1SuYJF2ba3uwM4IJvd8lRuqYnrYb/oM8 +0mJhwQTtzuDFycgTE1XnqGOtjHsB/ncw4c5omwX4Eu55MaBBRTUoCnGkJE+M3DyC +B19m3H0Q/gxhswWV7uGugQ+o+MePTagjAiZrHYNSVc61LwDKgEDg4XSsYPWHgJ2u +NmSRXbBoGOqKYcl3qJfEycel/FVL8/B/uWU9J2jQzGv6U53hkRrJXRqWbTKH7QMg +yALOWr7Z6v2yTcQvG99fevX4i8buMTolUVVnjWQye+mew4K6Ki3pHrTgSAai/Gev +HyICc/sgCq+dVEuhzf9gR7A/Xe8bVr2XIZYtCtFenTgCR2y59PYjJbigapordwj6 +xLEokCZYCDzifqrXPW+6MYgKBesntaFJ7qBFVHvmJ2WZICGoo7z7GJa7Um8M7YNR +TOlZ4iBgxcJlkoKM8xAfDoqXvneCbT+PHV28SSe9zE8P4c52hgQjxcCMElv924Sg +JPFI/2R80L5cFtHvma3AH/vLrrw4IgYmZNralw4/KBVEqE8AyvCazM90arQ+POuV +7LXTWtiBmelDGDfrs7vRWGJB82bSj6p4lVQgw1oudCvV0b4YacCs1aTPObpRhANl +6WLAYv7YTVWW4tAR+kg0Eeye7QUd5MjWHYbL +-----END CERTIFICATE----- + +# Issuer: CN=GTS Root R3 O=Google Trust Services LLC +# Subject: CN=GTS Root R3 O=Google Trust Services LLC +# Label: "GTS Root R3" +# Serial: 159662495401136852707857743206 +# MD5 Fingerprint: 3e:e7:9d:58:02:94:46:51:94:e5:e0:22:4a:8b:e7:73 +# SHA1 Fingerprint: ed:e5:71:80:2b:c8:92:b9:5b:83:3c:d2:32:68:3f:09:cd:a0:1e:46 +# SHA256 Fingerprint: 34:d8:a7:3e:e2:08:d9:bc:db:0d:95:65:20:93:4b:4e:40:e6:94:82:59:6e:8b:6f:73:c8:42:6b:01:0a:6f:48 +-----BEGIN CERTIFICATE----- +MIICCTCCAY6gAwIBAgINAgPluILrIPglJ209ZjAKBggqhkjOPQQDAzBHMQswCQYD +VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG +A1UEAxMLR1RTIFJvb3QgUjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw +WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz +IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjOPQIBBgUrgQQAIgNi +AAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout736G +jOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2ADDL2 +4CejQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW +BBTB8Sa6oC2uhYHP0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEA9uEglRR7 +VKOQFhG/hMjqb2sXnh5GmCCbn9MN2azTL818+FsuVbu/3ZL3pAzcMeGiAjEA/Jdm +ZuVDFhOD3cffL74UOO0BzrEXGhF16b0DjyZ+hOXJYKaV11RZt+cRLInUue4X +-----END CERTIFICATE----- + +# Issuer: CN=GTS Root R4 O=Google Trust Services LLC +# Subject: CN=GTS Root R4 O=Google Trust Services LLC +# Label: "GTS Root R4" +# Serial: 159662532700760215368942768210 +# MD5 Fingerprint: 43:96:83:77:19:4d:76:b3:9d:65:52:e4:1d:22:a5:e8 +# SHA1 Fingerprint: 77:d3:03:67:b5:e0:0c:15:f6:0c:38:61:df:7c:e1:3b:92:46:4d:47 +# SHA256 Fingerprint: 34:9d:fa:40:58:c5:e2:63:12:3b:39:8a:e7:95:57:3c:4e:13:13:c8:3f:e6:8f:93:55:6c:d5:e8:03:1b:3c:7d +-----BEGIN CERTIFICATE----- +MIICCTCCAY6gAwIBAgINAgPlwGjvYxqccpBQUjAKBggqhkjOPQQDAzBHMQswCQYD +VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG +A1UEAxMLR1RTIFJvb3QgUjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw +WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz +IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjOPQIBBgUrgQQAIgNi +AATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzuhXyi +QHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvR +HYqjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW +BBSATNbrdP9JNqPV2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNpADBmAjEA6ED/g94D +9J+uHXqnLrmvT/aDHQ4thQEd0dlq7A/Cr8deVl5c1RxYIigL9zC2L7F8AjEA8GE8 +p/SgguMh1YQdc4acLa/KNJvxn7kjNuK8YAOdgLOaVsjh4rsUecrNIdSUtUlD +-----END CERTIFICATE----- + +# Issuer: CN=Telia Root CA v2 O=Telia Finland Oyj +# Subject: CN=Telia Root CA v2 O=Telia Finland Oyj +# Label: "Telia Root CA v2" +# Serial: 7288924052977061235122729490515358 +# MD5 Fingerprint: 0e:8f:ac:aa:82:df:85:b1:f4:dc:10:1c:fc:99:d9:48 +# SHA1 Fingerprint: b9:99:cd:d1:73:50:8a:c4:47:05:08:9c:8c:88:fb:be:a0:2b:40:cd +# SHA256 Fingerprint: 24:2b:69:74:2f:cb:1e:5b:2a:bf:98:89:8b:94:57:21:87:54:4e:5b:4d:99:11:78:65:73:62:1f:6a:74:b8:2c +-----BEGIN CERTIFICATE----- +MIIFdDCCA1ygAwIBAgIPAWdfJ9b+euPkrL4JWwWeMA0GCSqGSIb3DQEBCwUAMEQx +CzAJBgNVBAYTAkZJMRowGAYDVQQKDBFUZWxpYSBGaW5sYW5kIE95ajEZMBcGA1UE +AwwQVGVsaWEgUm9vdCBDQSB2MjAeFw0xODExMjkxMTU1NTRaFw00MzExMjkxMTU1 +NTRaMEQxCzAJBgNVBAYTAkZJMRowGAYDVQQKDBFUZWxpYSBGaW5sYW5kIE95ajEZ +MBcGA1UEAwwQVGVsaWEgUm9vdCBDQSB2MjCCAiIwDQYJKoZIhvcNAQEBBQADggIP +ADCCAgoCggIBALLQPwe84nvQa5n44ndp586dpAO8gm2h/oFlH0wnrI4AuhZ76zBq +AMCzdGh+sq/H1WKzej9Qyow2RCRj0jbpDIX2Q3bVTKFgcmfiKDOlyzG4OiIjNLh9 +vVYiQJ3q9HsDrWj8soFPmNB06o3lfc1jw6P23pLCWBnglrvFxKk9pXSW/q/5iaq9 +lRdU2HhE8Qx3FZLgmEKnpNaqIJLNwaCzlrI6hEKNfdWV5Nbb6WLEWLN5xYzTNTOD +n3WhUidhOPFZPY5Q4L15POdslv5e2QJltI5c0BE0312/UqeBAMN/mUWZFdUXyApT +7GPzmX3MaRKGwhfwAZ6/hLzRUssbkmbOpFPlob/E2wnW5olWK8jjfN7j/4nlNW4o +6GwLI1GpJQXrSPjdscr6bAhR77cYbETKJuFzxokGgeWKrLDiKca5JLNrRBH0pUPC +TEPlcDaMtjNXepUugqD0XBCzYYP2AgWGLnwtbNwDRm41k9V6lS/eINhbfpSQBGq6 +WT0EBXWdN6IOLj3rwaRSg/7Qa9RmjtzG6RJOHSpXqhC8fF6CfaamyfItufUXJ63R +DolUK5X6wK0dmBR4M0KGCqlztft0DbcbMBnEWg4cJ7faGND/isgFuvGqHKI3t+ZI +pEYslOqodmJHixBTB0hXbOKSTbauBcvcwUpej6w9GU7C7WB1K9vBykLVAgMBAAGj +YzBhMB8GA1UdIwQYMBaAFHKs5DN5qkWH9v2sHZ7Wxy+G2CQ5MB0GA1UdDgQWBBRy +rOQzeapFh/b9rB2e1scvhtgkOTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw +AwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAoDtZpwmUPjaE0n4vOaWWl/oRrfxn83EJ +8rKJhGdEr7nv7ZbsnGTbMjBvZ5qsfl+yqwE2foH65IRe0qw24GtixX1LDoJt0nZi +0f6X+J8wfBj5tFJ3gh1229MdqfDBmgC9bXXYfef6xzijnHDoRnkDry5023X4blMM +A8iZGok1GTzTyVR8qPAs5m4HeW9q4ebqkYJpCh3DflminmtGFZhb069GHWLIzoBS +SRE/yQQSwxN8PzuKlts8oB4KtItUsiRnDe+Cy748fdHif64W1lZYudogsYMVoe+K +TTJvQS8TUoKU1xrBeKJR3Stwbbca+few4GeXVtt8YVMJAygCQMez2P2ccGrGKMOF +6eLtGpOg3kuYooQ+BXcBlj37tCAPnHICehIv1aO6UXivKitEZU61/Qrowc15h2Er +3oBXRb9n8ZuRXqWk7FlIEA04x7D6w0RtBPV4UBySllva9bguulvP5fBqnUsvWHMt +Ty3EHD70sz+rFQ47GUGKpMFXEmZxTPpT41frYpUJnlTd0cI8Vzy9OK2YZLe4A5pT +VmBds9hCG1xLEooc6+t9xnppxyd/pPiL8uSUZodL6ZQHCRJ5irLrdATczvREWeAW +ysUsWNc8e89ihmpQfTU2Zqf7N+cox9jQraVplI/owd8k+BsHMYeB2F326CjYSlKA +rBPuUBQemMc= +-----END CERTIFICATE----- + +# Issuer: CN=D-TRUST BR Root CA 1 2020 O=D-Trust GmbH +# Subject: CN=D-TRUST BR Root CA 1 2020 O=D-Trust GmbH +# Label: "D-TRUST BR Root CA 1 2020" +# Serial: 165870826978392376648679885835942448534 +# MD5 Fingerprint: b5:aa:4b:d5:ed:f7:e3:55:2e:8f:72:0a:f3:75:b8:ed +# SHA1 Fingerprint: 1f:5b:98:f0:e3:b5:f7:74:3c:ed:e6:b0:36:7d:32:cd:f4:09:41:67 +# SHA256 Fingerprint: e5:9a:aa:81:60:09:c2:2b:ff:5b:25:ba:d3:7d:f3:06:f0:49:79:7c:1f:81:d8:5a:b0:89:e6:57:bd:8f:00:44 +-----BEGIN CERTIFICATE----- +MIIC2zCCAmCgAwIBAgIQfMmPK4TX3+oPyWWa00tNljAKBggqhkjOPQQDAzBIMQsw +CQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRS +VVNUIEJSIFJvb3QgQ0EgMSAyMDIwMB4XDTIwMDIxMTA5NDUwMFoXDTM1MDIxMTA5 +NDQ1OVowSDELMAkGA1UEBhMCREUxFTATBgNVBAoTDEQtVHJ1c3QgR21iSDEiMCAG +A1UEAxMZRC1UUlVTVCBCUiBSb290IENBIDEgMjAyMDB2MBAGByqGSM49AgEGBSuB +BAAiA2IABMbLxyjR+4T1mu9CFCDhQ2tuda38KwOE1HaTJddZO0Flax7mNCq7dPYS +zuht56vkPE4/RAiLzRZxy7+SmfSk1zxQVFKQhYN4lGdnoxwJGT11NIXe7WB9xwy0 +QVK5buXuQqOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFHOREKv/ +VbNafAkl1bK6CKBrqx9tMA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6g +PKA6hjhodHRwOi8vY3JsLmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X2JyX3Jvb3Rf +Y2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVjdG9yeS5kLXRydXN0Lm5l +dC9DTj1ELVRSVVNUJTIwQlIlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxPPUQtVHJ1 +c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjO +PQQDAwNpADBmAjEAlJAtE/rhY/hhY+ithXhUkZy4kzg+GkHaQBZTQgjKL47xPoFW +wKrY7RjEsK70PvomAjEA8yjixtsrmfu3Ubgko6SUeho/5jbiA1czijDLgsfWFBHV +dWNbFJWcHwHP2NVypw87 +-----END CERTIFICATE----- + +# Issuer: CN=D-TRUST EV Root CA 1 2020 O=D-Trust GmbH +# Subject: CN=D-TRUST EV Root CA 1 2020 O=D-Trust GmbH +# Label: "D-TRUST EV Root CA 1 2020" +# Serial: 126288379621884218666039612629459926992 +# MD5 Fingerprint: 8c:2d:9d:70:9f:48:99:11:06:11:fb:e9:cb:30:c0:6e +# SHA1 Fingerprint: 61:db:8c:21:59:69:03:90:d8:7c:9c:12:86:54:cf:9d:3d:f4:dd:07 +# SHA256 Fingerprint: 08:17:0d:1a:a3:64:53:90:1a:2f:95:92:45:e3:47:db:0c:8d:37:ab:aa:bc:56:b8:1a:a1:00:dc:95:89:70:db +-----BEGIN CERTIFICATE----- +MIIC2zCCAmCgAwIBAgIQXwJB13qHfEwDo6yWjfv/0DAKBggqhkjOPQQDAzBIMQsw +CQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRS +VVNUIEVWIFJvb3QgQ0EgMSAyMDIwMB4XDTIwMDIxMTEwMDAwMFoXDTM1MDIxMTA5 +NTk1OVowSDELMAkGA1UEBhMCREUxFTATBgNVBAoTDEQtVHJ1c3QgR21iSDEiMCAG +A1UEAxMZRC1UUlVTVCBFViBSb290IENBIDEgMjAyMDB2MBAGByqGSM49AgEGBSuB +BAAiA2IABPEL3YZDIBnfl4XoIkqbz52Yv7QFJsnL46bSj8WeeHsxiamJrSc8ZRCC +/N/DnU7wMyPE0jL1HLDfMxddxfCxivnvubcUyilKwg+pf3VlSSowZ/Rk99Yad9rD +wpdhQntJraOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFH8QARY3 +OqQo5FD4pPfsazK2/umLMA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6g +PKA6hjhodHRwOi8vY3JsLmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X2V2X3Jvb3Rf +Y2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVjdG9yeS5kLXRydXN0Lm5l +dC9DTj1ELVRSVVNUJTIwRVYlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxPPUQtVHJ1 +c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjO +PQQDAwNpADBmAjEAyjzGKnXCXnViOTYAYFqLwZOZzNnbQTs7h5kXO9XMT8oi96CA +y/m0sRtW9XLS/BnRAjEAkfcwkz8QRitxpNA7RJvAKQIFskF3UfN5Wp6OFKBOQtJb +gfM0agPnIjhQW+0ZT0MW +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert TLS ECC P384 Root G5 O=DigiCert, Inc. +# Subject: CN=DigiCert TLS ECC P384 Root G5 O=DigiCert, Inc. +# Label: "DigiCert TLS ECC P384 Root G5" +# Serial: 13129116028163249804115411775095713523 +# MD5 Fingerprint: d3:71:04:6a:43:1c:db:a6:59:e1:a8:a3:aa:c5:71:ed +# SHA1 Fingerprint: 17:f3:de:5e:9f:0f:19:e9:8e:f6:1f:32:26:6e:20:c4:07:ae:30:ee +# SHA256 Fingerprint: 01:8e:13:f0:77:25:32:cf:80:9b:d1:b1:72:81:86:72:83:fc:48:c6:e1:3b:e9:c6:98:12:85:4a:49:0c:1b:05 +-----BEGIN CERTIFICATE----- +MIICGTCCAZ+gAwIBAgIQCeCTZaz32ci5PhwLBCou8zAKBggqhkjOPQQDAzBOMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJjAkBgNVBAMTHURp +Z2lDZXJ0IFRMUyBFQ0MgUDM4NCBSb290IEc1MB4XDTIxMDExNTAwMDAwMFoXDTQ2 +MDExNDIzNTk1OVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ +bmMuMSYwJAYDVQQDEx1EaWdpQ2VydCBUTFMgRUNDIFAzODQgUm9vdCBHNTB2MBAG +ByqGSM49AgEGBSuBBAAiA2IABMFEoc8Rl1Ca3iOCNQfN0MsYndLxf3c1TzvdlHJS +7cI7+Oz6e2tYIOyZrsn8aLN1udsJ7MgT9U7GCh1mMEy7H0cKPGEQQil8pQgO4CLp +0zVozptjn4S1mU1YoI71VOeVyaNCMEAwHQYDVR0OBBYEFMFRRVBZqz7nLFr6ICIS +B4CIfBFqMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49 +BAMDA2gAMGUCMQCJao1H5+z8blUD2WdsJk6Dxv3J+ysTvLd6jLRl0mlpYxNjOyZQ +LgGheQaRnUi/wr4CMEfDFXuxoJGZSZOoPHzoRgaLLPIxAJSdYsiJvRmEFOml+wG4 +DXZDjC5Ty3zfDBeWUA== +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert TLS RSA4096 Root G5 O=DigiCert, Inc. +# Subject: CN=DigiCert TLS RSA4096 Root G5 O=DigiCert, Inc. +# Label: "DigiCert TLS RSA4096 Root G5" +# Serial: 11930366277458970227240571539258396554 +# MD5 Fingerprint: ac:fe:f7:34:96:a9:f2:b3:b4:12:4b:e4:27:41:6f:e1 +# SHA1 Fingerprint: a7:88:49:dc:5d:7c:75:8c:8c:de:39:98:56:b3:aa:d0:b2:a5:71:35 +# SHA256 Fingerprint: 37:1a:00:dc:05:33:b3:72:1a:7e:eb:40:e8:41:9e:70:79:9d:2b:0a:0f:2c:1d:80:69:31:65:f7:ce:c4:ad:75 +-----BEGIN CERTIFICATE----- +MIIFZjCCA06gAwIBAgIQCPm0eKj6ftpqMzeJ3nzPijANBgkqhkiG9w0BAQwFADBN +MQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMT +HERpZ2lDZXJ0IFRMUyBSU0E0MDk2IFJvb3QgRzUwHhcNMjEwMTE1MDAwMDAwWhcN +NDYwMTE0MjM1OTU5WjBNMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQs +IEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0MDk2IFJvb3QgRzUwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz0PTJeRGd/fxmgefM1eS87IE+ +ajWOLrfn3q/5B03PMJ3qCQuZvWxX2hhKuHisOjmopkisLnLlvevxGs3npAOpPxG0 +2C+JFvuUAT27L/gTBaF4HI4o4EXgg/RZG5Wzrn4DReW+wkL+7vI8toUTmDKdFqgp +wgscONyfMXdcvyej/Cestyu9dJsXLfKB2l2w4SMXPohKEiPQ6s+d3gMXsUJKoBZM +pG2T6T867jp8nVid9E6P/DsjyG244gXazOvswzH016cpVIDPRFtMbzCe88zdH5RD +nU1/cHAN1DrRN/BsnZvAFJNY781BOHW8EwOVfH/jXOnVDdXifBBiqmvwPXbzP6Po +sMH976pXTayGpxi0KcEsDr9kvimM2AItzVwv8n/vFfQMFawKsPHTDU9qTXeXAaDx +Zre3zu/O7Oyldcqs4+Fj97ihBMi8ez9dLRYiVu1ISf6nL3kwJZu6ay0/nTvEF+cd +Lvvyz6b84xQslpghjLSR6Rlgg/IwKwZzUNWYOwbpx4oMYIwo+FKbbuH2TbsGJJvX +KyY//SovcfXWJL5/MZ4PbeiPT02jP/816t9JXkGPhvnxd3lLG7SjXi/7RgLQZhNe +XoVPzthwiHvOAbWWl9fNff2C+MIkwcoBOU+NosEUQB+cZtUMCUbW8tDRSHZWOkPL +tgoRObqME2wGtZ7P6wIDAQABo0IwQDAdBgNVHQ4EFgQUUTMc7TZArxfTJc1paPKv +TiM+s0EwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcN +AQEMBQADggIBAGCmr1tfV9qJ20tQqcQjNSH/0GEwhJG3PxDPJY7Jv0Y02cEhJhxw +GXIeo8mH/qlDZJY6yFMECrZBu8RHANmfGBg7sg7zNOok992vIGCukihfNudd5N7H +PNtQOa27PShNlnx2xlv0wdsUpasZYgcYQF+Xkdycx6u1UQ3maVNVzDl92sURVXLF +O4uJ+DQtpBflF+aZfTCIITfNMBc9uPK8qHWgQ9w+iUuQrm0D4ByjoJYJu32jtyoQ +REtGBzRj7TG5BO6jm5qu5jF49OokYTurWGT/u4cnYiWB39yhL/btp/96j1EuMPik +AdKFOV8BmZZvWltwGUb+hmA+rYAQCd05JS9Yf7vSdPD3Rh9GOUrYU9DzLjtxpdRv +/PNn5AeP3SYZ4Y1b+qOTEZvpyDrDVWiakuFSdjjo4bq9+0/V77PnSIMx8IIh47a+ +p6tv75/fTM8BuGJqIz3nCU2AG3swpMPdB380vqQmsvZB6Akd4yCYqjdP//fx4ilw +MUc/dNAUFvohigLVigmUdy7yWSiLfFCSCmZ4OIN1xLVaqBHG5cGdZlXPU8Sv13WF +qUITVuwhd4GTWgzqltlJyqEI8pc7bZsEGCREjnwB8twl2F6GmrE52/WRMmrRpnCK +ovfepEWFJqgejF0pW8hL2JpqA15w8oVPbEtoL8pU9ozaMv7Da4M/OMZ+ +-----END CERTIFICATE----- + +# Issuer: CN=Certainly Root R1 O=Certainly +# Subject: CN=Certainly Root R1 O=Certainly +# Label: "Certainly Root R1" +# Serial: 188833316161142517227353805653483829216 +# MD5 Fingerprint: 07:70:d4:3e:82:87:a0:fa:33:36:13:f4:fa:33:e7:12 +# SHA1 Fingerprint: a0:50:ee:0f:28:71:f4:27:b2:12:6d:6f:50:96:25:ba:cc:86:42:af +# SHA256 Fingerprint: 77:b8:2c:d8:64:4c:43:05:f7:ac:c5:cb:15:6b:45:67:50:04:03:3d:51:c6:0c:62:02:a8:e0:c3:34:67:d3:a0 +-----BEGIN CERTIFICATE----- +MIIFRzCCAy+gAwIBAgIRAI4P+UuQcWhlM1T01EQ5t+AwDQYJKoZIhvcNAQELBQAw +PTELMAkGA1UEBhMCVVMxEjAQBgNVBAoTCUNlcnRhaW5seTEaMBgGA1UEAxMRQ2Vy +dGFpbmx5IFJvb3QgUjEwHhcNMjEwNDAxMDAwMDAwWhcNNDYwNDAxMDAwMDAwWjA9 +MQswCQYDVQQGEwJVUzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0 +YWlubHkgUm9vdCBSMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANA2 +1B/q3avk0bbm+yLA3RMNansiExyXPGhjZjKcA7WNpIGD2ngwEc/csiu+kr+O5MQT +vqRoTNoCaBZ0vrLdBORrKt03H2As2/X3oXyVtwxwhi7xOu9S98zTm/mLvg7fMbed +aFySpvXl8wo0tf97ouSHocavFwDvA5HtqRxOcT3Si2yJ9HiG5mpJoM610rCrm/b0 +1C7jcvk2xusVtyWMOvwlDbMicyF0yEqWYZL1LwsYpfSt4u5BvQF5+paMjRcCMLT5 +r3gajLQ2EBAHBXDQ9DGQilHFhiZ5shGIXsXwClTNSaa/ApzSRKft43jvRl5tcdF5 +cBxGX1HpyTfcX35pe0HfNEXgO4T0oYoKNp43zGJS4YkNKPl6I7ENPT2a/Z2B7yyQ +wHtETrtJ4A5KVpK8y7XdeReJkd5hiXSSqOMyhb5OhaRLWcsrxXiOcVTQAjeZjOVJ +6uBUcqQRBi8LjMFbvrWhsFNunLhgkR9Za/kt9JQKl7XsxXYDVBtlUrpMklZRNaBA +2CnbrlJ2Oy0wQJuK0EJWtLeIAaSHO1OWzaMWj/Nmqhexx2DgwUMFDO6bW2BvBlyH +Wyf5QBGenDPBt+U1VwV/J84XIIwc/PH72jEpSe31C4SnT8H2TsIonPru4K8H+zMR +eiFPCyEQtkA6qyI6BJyLm4SGcprSp6XEtHWRqSsjAgMBAAGjQjBAMA4GA1UdDwEB +/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTgqj8ljZ9EXME66C6u +d0yEPmcM9DANBgkqhkiG9w0BAQsFAAOCAgEAuVevuBLaV4OPaAszHQNTVfSVcOQr +PbA56/qJYv331hgELyE03fFo8NWWWt7CgKPBjcZq91l3rhVkz1t5BXdm6ozTaw3d +8VkswTOlMIAVRQdFGjEitpIAq5lNOo93r6kiyi9jyhXWx8bwPWz8HA2YEGGeEaIi +1wrykXprOQ4vMMM2SZ/g6Q8CRFA3lFV96p/2O7qUpUzpvD5RtOjKkjZUbVwlKNrd +rRT90+7iIgXr0PK3aBLXWopBGsaSpVo7Y0VPv+E6dyIvXL9G+VoDhRNCX8reU9di +taY1BMJH/5n9hN9czulegChB8n3nHpDYT3Y+gjwN/KUD+nsa2UUeYNrEjvn8K8l7 +lcUq/6qJ34IxD3L/DCfXCh5WAFAeDJDBlrXYFIW7pw0WwfgHJBu6haEaBQmAupVj +yTrsJZ9/nbqkRxWbRHDxakvWOF5D8xh+UG7pWijmZeZ3Gzr9Hb4DJqPb1OG7fpYn +Kx3upPvaJVQTA945xsMfTZDsjxtK0hzthZU4UHlG1sGQUDGpXJpuHfUzVounmdLy +yCwzk5Iwx06MZTMQZBf9JBeW0Y3COmor6xOLRPIh80oat3df1+2IpHLlOR+Vnb5n +wXARPbv0+Em34yaXOp/SX3z7wJl8OSngex2/DaeP0ik0biQVy96QXr8axGbqwua6 +OV+KmalBWQewLK8= +-----END CERTIFICATE----- + +# Issuer: CN=Certainly Root E1 O=Certainly +# Subject: CN=Certainly Root E1 O=Certainly +# Label: "Certainly Root E1" +# Serial: 8168531406727139161245376702891150584 +# MD5 Fingerprint: 0a:9e:ca:cd:3e:52:50:c6:36:f3:4b:a3:ed:a7:53:e9 +# SHA1 Fingerprint: f9:e1:6d:dc:01:89:cf:d5:82:45:63:3e:c5:37:7d:c2:eb:93:6f:2b +# SHA256 Fingerprint: b4:58:5f:22:e4:ac:75:6a:4e:86:12:a1:36:1c:5d:9d:03:1a:93:fd:84:fe:bb:77:8f:a3:06:8b:0f:c4:2d:c2 +-----BEGIN CERTIFICATE----- +MIIB9zCCAX2gAwIBAgIQBiUzsUcDMydc+Y2aub/M+DAKBggqhkjOPQQDAzA9MQsw +CQYDVQQGEwJVUzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0YWlu +bHkgUm9vdCBFMTAeFw0yMTA0MDEwMDAwMDBaFw00NjA0MDEwMDAwMDBaMD0xCzAJ +BgNVBAYTAlVTMRIwEAYDVQQKEwlDZXJ0YWlubHkxGjAYBgNVBAMTEUNlcnRhaW5s +eSBSb290IEUxMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE3m/4fxzf7flHh4axpMCK ++IKXgOqPyEpeKn2IaKcBYhSRJHpcnqMXfYqGITQYUBsQ3tA3SybHGWCA6TS9YBk2 +QNYphwk8kXr2vBMj3VlOBF7PyAIcGFPBMdjaIOlEjeR2o0IwQDAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU8ygYy2R17ikq6+2uI1g4 +hevIIgcwCgYIKoZIzj0EAwMDaAAwZQIxALGOWiDDshliTd6wT99u0nCK8Z9+aozm +ut6Dacpps6kFtZaSF4fC0urQe87YQVt8rgIwRt7qy12a7DLCZRawTDBcMPPaTnOG +BtjOiQRINzf43TNRnXCve1XYAS59BWQOhriR +-----END CERTIFICATE----- + +# Issuer: CN=Security Communication ECC RootCA1 O=SECOM Trust Systems CO.,LTD. +# Subject: CN=Security Communication ECC RootCA1 O=SECOM Trust Systems CO.,LTD. +# Label: "Security Communication ECC RootCA1" +# Serial: 15446673492073852651 +# MD5 Fingerprint: 7e:43:b0:92:68:ec:05:43:4c:98:ab:5d:35:2e:7e:86 +# SHA1 Fingerprint: b8:0e:26:a9:bf:d2:b2:3b:c0:ef:46:c9:ba:c7:bb:f6:1d:0d:41:41 +# SHA256 Fingerprint: e7:4f:bd:a5:5b:d5:64:c4:73:a3:6b:44:1a:a7:99:c8:a6:8e:07:74:40:e8:28:8b:9f:a1:e5:0e:4b:ba:ca:11 +-----BEGIN CERTIFICATE----- +MIICODCCAb6gAwIBAgIJANZdm7N4gS7rMAoGCCqGSM49BAMDMGExCzAJBgNVBAYT +AkpQMSUwIwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMSswKQYD +VQQDEyJTZWN1cml0eSBDb21tdW5pY2F0aW9uIEVDQyBSb290Q0ExMB4XDTE2MDYx +NjA1MTUyOFoXDTM4MDExODA1MTUyOFowYTELMAkGA1UEBhMCSlAxJTAjBgNVBAoT +HFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKzApBgNVBAMTIlNlY3VyaXR5 +IENvbW11bmljYXRpb24gRUNDIFJvb3RDQTEwdjAQBgcqhkjOPQIBBgUrgQQAIgNi +AASkpW9gAwPDvTH00xecK4R1rOX9PVdu12O/5gSJko6BnOPpR27KkBLIE+Cnnfdl +dB9sELLo5OnvbYUymUSxXv3MdhDYW72ixvnWQuRXdtyQwjWpS4g8EkdtXP9JTxpK +ULGjQjBAMB0GA1UdDgQWBBSGHOf+LaVKiwj+KBH6vqNm+GBZLzAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjAVXUI9/Lbu +9zuxNuie9sRGKEkz0FhDKmMpzE2xtHqiuQ04pV1IKv3LsnNdo4gIxwwCMQDAqy0O +be0YottT6SXbVQjgUMzfRGEWgqtJsLKB7HOHeLRMsmIbEvoWTSVLY70eN9k= +-----END CERTIFICATE----- + +# Issuer: CN=BJCA Global Root CA1 O=BEIJING CERTIFICATE AUTHORITY +# Subject: CN=BJCA Global Root CA1 O=BEIJING CERTIFICATE AUTHORITY +# Label: "BJCA Global Root CA1" +# Serial: 113562791157148395269083148143378328608 +# MD5 Fingerprint: 42:32:99:76:43:33:36:24:35:07:82:9b:28:f9:d0:90 +# SHA1 Fingerprint: d5:ec:8d:7b:4c:ba:79:f4:e7:e8:cb:9d:6b:ae:77:83:10:03:21:6a +# SHA256 Fingerprint: f3:89:6f:88:fe:7c:0a:88:27:66:a7:fa:6a:d2:74:9f:b5:7a:7f:3e:98:fb:76:9c:1f:a7:b0:9c:2c:44:d5:ae +-----BEGIN CERTIFICATE----- +MIIFdDCCA1ygAwIBAgIQVW9l47TZkGobCdFsPsBsIDANBgkqhkiG9w0BAQsFADBU +MQswCQYDVQQGEwJDTjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRI +T1JJVFkxHTAbBgNVBAMMFEJKQ0EgR2xvYmFsIFJvb3QgQ0ExMB4XDTE5MTIxOTAz +MTYxN1oXDTQ0MTIxMjAzMTYxN1owVDELMAkGA1UEBhMCQ04xJjAkBgNVBAoMHUJF +SUpJTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQDDBRCSkNBIEdsb2Jh +bCBSb290IENBMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAPFmCL3Z +xRVhy4QEQaVpN3cdwbB7+sN3SJATcmTRuHyQNZ0YeYjjlwE8R4HyDqKYDZ4/N+AZ +spDyRhySsTphzvq3Rp4Dhtczbu33RYx2N95ulpH3134rhxfVizXuhJFyV9xgw8O5 +58dnJCNPYwpj9mZ9S1WnP3hkSWkSl+BMDdMJoDIwOvqfwPKcxRIqLhy1BDPapDgR +at7GGPZHOiJBhyL8xIkoVNiMpTAK+BcWyqw3/XmnkRd4OJmtWO2y3syJfQOcs4ll +5+M7sSKGjwZteAf9kRJ/sGsciQ35uMt0WwfCyPQ10WRjeulumijWML3mG90Vr4Tq +nMfK9Q7q8l0ph49pczm+LiRvRSGsxdRpJQaDrXpIhRMsDQa4bHlW/KNnMoH1V6XK +V0Jp6VwkYe/iMBhORJhVb3rCk9gZtt58R4oRTklH2yiUAguUSiz5EtBP6DF+bHq/ +pj+bOT0CFqMYs2esWz8sgytnOYFcuX6U1WTdno9uruh8W7TXakdI136z1C2OVnZO +z2nxbkRs1CTqjSShGL+9V/6pmTW12xB3uD1IutbB5/EjPtffhZ0nPNRAvQoMvfXn +jSXWgXSHRtQpdaJCbPdzied9v3pKH9MiyRVVz99vfFXQpIsHETdfg6YmV6YBW37+ +WGgHqel62bno/1Afq8K0wM7o6v0PvY1NuLxxAgMBAAGjQjBAMB0GA1UdDgQWBBTF +7+3M2I0hxkjk49cULqcWk+WYATAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE +AwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAUoKsITQfI/Ki2Pm4rzc2IInRNwPWaZ+4 +YRC6ojGYWUfo0Q0lHhVBDOAqVdVXUsv45Mdpox1NcQJeXyFFYEhcCY5JEMEE3Kli +awLwQ8hOnThJdMkycFRtwUf8jrQ2ntScvd0g1lPJGKm1Vrl2i5VnZu69mP6u775u ++2D2/VnGKhs/I0qUJDAnyIm860Qkmss9vk/Ves6OF8tiwdneHg56/0OGNFK8YT88 +X7vZdrRTvJez/opMEi4r89fO4aL/3Xtw+zuhTaRjAv04l5U/BXCga99igUOLtFkN +SoxUnMW7gZ/NfaXvCyUeOiDbHPwfmGcCCtRzRBPbUYQaVQNW4AB+dAb/OMRyHdOo +P2gxXdMJxy6MW2Pg6Nwe0uxhHvLe5e/2mXZgLR6UcnHGCyoyx5JO1UbXHfmpGQrI ++pXObSOYqgs4rZpWDW+N8TEAiMEXnM0ZNjX+VVOg4DwzX5Ze4jLp3zO7Bkqp2IRz +znfSxqxx4VyjHQy7Ct9f4qNx2No3WqB4K/TUfet27fJhcKVlmtOJNBir+3I+17Q9 +eVzYH6Eze9mCUAyTF6ps3MKCuwJXNq+YJyo5UOGwifUll35HaBC07HPKs5fRJNz2 +YqAo07WjuGS3iGJCz51TzZm+ZGiPTx4SSPfSKcOYKMryMguTjClPPGAyzQWWYezy +r/6zcCwupvI= +-----END CERTIFICATE----- + +# Issuer: CN=BJCA Global Root CA2 O=BEIJING CERTIFICATE AUTHORITY +# Subject: CN=BJCA Global Root CA2 O=BEIJING CERTIFICATE AUTHORITY +# Label: "BJCA Global Root CA2" +# Serial: 58605626836079930195615843123109055211 +# MD5 Fingerprint: 5e:0a:f6:47:5f:a6:14:e8:11:01:95:3f:4d:01:eb:3c +# SHA1 Fingerprint: f4:27:86:eb:6e:b8:6d:88:31:67:02:fb:ba:66:a4:53:00:aa:7a:a6 +# SHA256 Fingerprint: 57:4d:f6:93:1e:27:80:39:66:7b:72:0a:fd:c1:60:0f:c2:7e:b6:6d:d3:09:29:79:fb:73:85:64:87:21:28:82 +-----BEGIN CERTIFICATE----- +MIICJTCCAaugAwIBAgIQLBcIfWQqwP6FGFkGz7RK6zAKBggqhkjOPQQDAzBUMQsw +CQYDVQQGEwJDTjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRIT1JJ +VFkxHTAbBgNVBAMMFEJKQ0EgR2xvYmFsIFJvb3QgQ0EyMB4XDTE5MTIxOTAzMTgy +MVoXDTQ0MTIxMjAzMTgyMVowVDELMAkGA1UEBhMCQ04xJjAkBgNVBAoMHUJFSUpJ +TkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQDDBRCSkNBIEdsb2JhbCBS +b290IENBMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABJ3LgJGNU2e1uVCxA/jlSR9B +IgmwUVJY1is0j8USRhTFiy8shP8sbqjV8QnjAyEUxEM9fMEsxEtqSs3ph+B99iK+ ++kpRuDCK/eHeGBIK9ke35xe/J4rUQUyWPGCWwf0VHKNCMEAwHQYDVR0OBBYEFNJK +sVF/BvDRgh9Obl+rg/xI1LCRMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD +AgEGMAoGCCqGSM49BAMDA2gAMGUCMBq8W9f+qdJUDkpd0m2xQNz0Q9XSSpkZElaA +94M04TVOSG0ED1cxMDAtsaqdAzjbBgIxAMvMh1PLet8gUXOQwKhbYdDFUDn9hf7B +43j4ptZLvZuHjw/l1lOWqzzIQNph91Oj9w== +-----END CERTIFICATE----- + +# Issuer: CN=Sectigo Public Server Authentication Root E46 O=Sectigo Limited +# Subject: CN=Sectigo Public Server Authentication Root E46 O=Sectigo Limited +# Label: "Sectigo Public Server Authentication Root E46" +# Serial: 88989738453351742415770396670917916916 +# MD5 Fingerprint: 28:23:f8:b2:98:5c:37:16:3b:3e:46:13:4e:b0:b3:01 +# SHA1 Fingerprint: ec:8a:39:6c:40:f0:2e:bc:42:75:d4:9f:ab:1c:1a:5b:67:be:d2:9a +# SHA256 Fingerprint: c9:0f:26:f0:fb:1b:40:18:b2:22:27:51:9b:5c:a2:b5:3e:2c:a5:b3:be:5c:f1:8e:fe:1b:ef:47:38:0c:53:83 +-----BEGIN CERTIFICATE----- +MIICOjCCAcGgAwIBAgIQQvLM2htpN0RfFf51KBC49DAKBggqhkjOPQQDAzBfMQsw +CQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1T +ZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwHhcN +MjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEYMBYG +A1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1YmxpYyBT +ZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAAR2+pmpbiDt+dd34wc7qNs9Xzjoq1WmVk/WSOrsfy2qw7LFeeyZYX8QeccC +WvkEN/U0NSt3zn8gj1KjAIns1aeibVvjS5KToID1AZTc8GgHHs3u/iVStSBDHBv+ +6xnOQ6OjQjBAMB0GA1UdDgQWBBTRItpMWfFLXyY4qp3W7usNw/upYTAOBgNVHQ8B +Af8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNnADBkAjAn7qRa +qCG76UeXlImldCBteU/IvZNeWBj7LRoAasm4PdCkT0RHlAFWovgzJQxC36oCMB3q +4S6ILuH5px0CMk7yn2xVdOOurvulGu7t0vzCAxHrRVxgED1cf5kDW21USAGKcw== +-----END CERTIFICATE----- + +# Issuer: CN=Sectigo Public Server Authentication Root R46 O=Sectigo Limited +# Subject: CN=Sectigo Public Server Authentication Root R46 O=Sectigo Limited +# Label: "Sectigo Public Server Authentication Root R46" +# Serial: 156256931880233212765902055439220583700 +# MD5 Fingerprint: 32:10:09:52:00:d5:7e:6c:43:df:15:c0:b1:16:93:e5 +# SHA1 Fingerprint: ad:98:f9:f3:e4:7d:75:3b:65:d4:82:b3:a4:52:17:bb:6e:f5:e4:38 +# SHA256 Fingerprint: 7b:b6:47:a6:2a:ee:ac:88:bf:25:7a:a5:22:d0:1f:fe:a3:95:e0:ab:45:c7:3f:93:f6:56:54:ec:38:f2:5a:06 +-----BEGIN CERTIFICATE----- +MIIFijCCA3KgAwIBAgIQdY39i658BwD6qSWn4cetFDANBgkqhkiG9w0BAQwFADBf +MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQD +Ey1TZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYw +HhcNMjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEY +MBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1Ymxp +YyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQCTvtU2UnXYASOgHEdCSe5jtrch/cSV1UgrJnwUUxDa +ef0rty2k1Cz66jLdScK5vQ9IPXtamFSvnl0xdE8H/FAh3aTPaE8bEmNtJZlMKpnz +SDBh+oF8HqcIStw+KxwfGExxqjWMrfhu6DtK2eWUAtaJhBOqbchPM8xQljeSM9xf +iOefVNlI8JhD1mb9nxc4Q8UBUQvX4yMPFF1bFOdLvt30yNoDN9HWOaEhUTCDsG3X +ME6WW5HwcCSrv0WBZEMNvSE6Lzzpng3LILVCJ8zab5vuZDCQOc2TZYEhMbUjUDM3 +IuM47fgxMMxF/mL50V0yeUKH32rMVhlATc6qu/m1dkmU8Sf4kaWD5QazYw6A3OAS +VYCmO2a0OYctyPDQ0RTp5A1NDvZdV3LFOxxHVp3i1fuBYYzMTYCQNFu31xR13NgE +SJ/AwSiItOkcyqex8Va3e0lMWeUgFaiEAin6OJRpmkkGj80feRQXEgyDet4fsZfu ++Zd4KKTIRJLpfSYFplhym3kT2BFfrsU4YjRosoYwjviQYZ4ybPUHNs2iTG7sijbt +8uaZFURww3y8nDnAtOFr94MlI1fZEoDlSfB1D++N6xybVCi0ITz8fAr/73trdf+L +HaAZBav6+CuBQug4urv7qv094PPK306Xlynt8xhW6aWWrL3DkJiy4Pmi1KZHQ3xt +zwIDAQABo0IwQDAdBgNVHQ4EFgQUVnNYZJX5khqwEioEYnmhQBWIIUkwDgYDVR0P +AQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAC9c +mTz8Bl6MlC5w6tIyMY208FHVvArzZJ8HXtXBc2hkeqK5Duj5XYUtqDdFqij0lgVQ +YKlJfp/imTYpE0RHap1VIDzYm/EDMrraQKFz6oOht0SmDpkBm+S8f74TlH7Kph52 +gDY9hAaLMyZlbcp+nv4fjFg4exqDsQ+8FxG75gbMY/qB8oFM2gsQa6H61SilzwZA +Fv97fRheORKkU55+MkIQpiGRqRxOF3yEvJ+M0ejf5lG5Nkc/kLnHvALcWxxPDkjB +JYOcCj+esQMzEhonrPcibCTRAUH4WAP+JWgiH5paPHxsnnVI84HxZmduTILA7rpX +DhjvLpr3Etiga+kFpaHpaPi8TD8SHkXoUsCjvxInebnMMTzD9joiFgOgyY9mpFui +TdaBJQbpdqQACj7LzTWb4OE4y2BThihCQRxEV+ioratF4yUQvNs+ZUH7G6aXD+u5 +dHn5HrwdVw1Hr8Mvn4dGp+smWg9WY7ViYG4A++MnESLn/pmPNPW56MORcr3Ywx65 +LvKRRFHQV80MNNVIIb/bE/FmJUNS0nAiNs2fxBx1IK1jcmMGDw4nztJqDby1ORrp +0XZ60Vzk50lJLVU3aPAaOpg+VBeHVOmmJ1CJeyAvP/+/oYtKR5j/K3tJPsMpRmAY +QqszKbrAKbkTidOIijlBO8n9pu0f9GBj39ItVQGL +-----END CERTIFICATE----- + +# Issuer: CN=SSL.com TLS RSA Root CA 2022 O=SSL Corporation +# Subject: CN=SSL.com TLS RSA Root CA 2022 O=SSL Corporation +# Label: "SSL.com TLS RSA Root CA 2022" +# Serial: 148535279242832292258835760425842727825 +# MD5 Fingerprint: d8:4e:c6:59:30:d8:fe:a0:d6:7a:5a:2c:2c:69:78:da +# SHA1 Fingerprint: ec:2c:83:40:72:af:26:95:10:ff:0e:f2:03:ee:31:70:f6:78:9d:ca +# SHA256 Fingerprint: 8f:af:7d:2e:2c:b4:70:9b:b8:e0:b3:36:66:bf:75:a5:dd:45:b5:de:48:0f:8e:a8:d4:bf:e6:be:bc:17:f2:ed +-----BEGIN CERTIFICATE----- +MIIFiTCCA3GgAwIBAgIQb77arXO9CEDii02+1PdbkTANBgkqhkiG9w0BAQsFADBO +MQswCQYDVQQGEwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQD +DBxTU0wuY29tIFRMUyBSU0EgUm9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzQyMloX +DTQ2MDgxOTE2MzQyMVowTjELMAkGA1UEBhMCVVMxGDAWBgNVBAoMD1NTTCBDb3Jw +b3JhdGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgUlNBIFJvb3QgQ0EgMjAyMjCC +AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANCkCXJPQIgSYT41I57u9nTP +L3tYPc48DRAokC+X94xI2KDYJbFMsBFMF3NQ0CJKY7uB0ylu1bUJPiYYf7ISf5OY +t6/wNr/y7hienDtSxUcZXXTzZGbVXcdotL8bHAajvI9AI7YexoS9UcQbOcGV0ins +S657Lb85/bRi3pZ7QcacoOAGcvvwB5cJOYF0r/c0WRFXCsJbwST0MXMwgsadugL3 +PnxEX4MN8/HdIGkWCVDi1FW24IBydm5MR7d1VVm0U3TZlMZBrViKMWYPHqIbKUBO +L9975hYsLfy/7PO0+r4Y9ptJ1O4Fbtk085zx7AGL0SDGD6C1vBdOSHtRwvzpXGk3 +R2azaPgVKPC506QVzFpPulJwoxJF3ca6TvvC0PeoUidtbnm1jPx7jMEWTO6Af77w +dr5BUxIzrlo4QqvXDz5BjXYHMtWrifZOZ9mxQnUjbvPNQrL8VfVThxc7wDNY8VLS ++YCk8OjwO4s4zKTGkH8PnP2L0aPP2oOnaclQNtVcBdIKQXTbYxE3waWglksejBYS +d66UNHsef8JmAOSqg+qKkK3ONkRN0VHpvB/zagX9wHQfJRlAUW7qglFA35u5CCoG +AtUjHBPW6dvbxrB6y3snm/vg1UYk7RBLY0ulBY+6uB0rpvqR4pJSvezrZ5dtmi2f +gTIFZzL7SAg/2SW4BCUvAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0j +BBgwFoAU+y437uOEeicuzRk1sTN8/9REQrkwHQYDVR0OBBYEFPsuN+7jhHonLs0Z +NbEzfP/UREK5MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAjYlt +hEUY8U+zoO9opMAdrDC8Z2awms22qyIZZtM7QbUQnRC6cm4pJCAcAZli05bg4vsM +QtfhWsSWTVTNj8pDU/0quOr4ZcoBwq1gaAafORpR2eCNJvkLTqVTJXojpBzOCBvf +R4iyrT7gJ4eLSYwfqUdYe5byiB0YrrPRpgqU+tvT5TgKa3kSM/tKWTcWQA673vWJ +DPFs0/dRa1419dvAJuoSc06pkZCmF8NsLzjUo3KUQyxi4U5cMj29TH0ZR6LDSeeW +P4+a0zvkEdiLA9z2tmBVGKaBUfPhqBVq6+AL8BQx1rmMRTqoENjwuSfr98t67wVy +lrXEj5ZzxOhWc5y8aVFjvO9nHEMaX3cZHxj4HCUp+UmZKbaSPaKDN7EgkaibMOlq +bLQjk2UEqxHzDh1TJElTHaE/nUiSEeJ9DU/1172iWD54nR4fK/4huxoTtrEoZP2w +AgDHbICivRZQIA9ygV/MlP+7mea6kMvq+cYMwq7FGc4zoWtcu358NFcXrfA/rs3q +r5nsLFR+jM4uElZI7xc7P0peYNLcdDa8pUNjyw9bowJWCZ4kLOGGgYz+qxcs+sji +Mho6/4UIyYOf8kpIEFR3N+2ivEC+5BB09+Rbu7nzifmPQdjH5FCQNYA+HLhNkNPU +98OwoX6EyneSMSy4kLGCenROmxMmtNVQZlR4rmA= +-----END CERTIFICATE----- + +# Issuer: CN=SSL.com TLS ECC Root CA 2022 O=SSL Corporation +# Subject: CN=SSL.com TLS ECC Root CA 2022 O=SSL Corporation +# Label: "SSL.com TLS ECC Root CA 2022" +# Serial: 26605119622390491762507526719404364228 +# MD5 Fingerprint: 99:d7:5c:f1:51:36:cc:e9:ce:d9:19:2e:77:71:56:c5 +# SHA1 Fingerprint: 9f:5f:d9:1a:54:6d:f5:0c:71:f0:ee:7a:bd:17:49:98:84:73:e2:39 +# SHA256 Fingerprint: c3:2f:fd:9f:46:f9:36:d1:6c:36:73:99:09:59:43:4b:9a:d6:0a:af:bb:9e:7c:f3:36:54:f1:44:cc:1b:a1:43 +-----BEGIN CERTIFICATE----- +MIICOjCCAcCgAwIBAgIQFAP1q/s3ixdAW+JDsqXRxDAKBggqhkjOPQQDAzBOMQsw +CQYDVQQGEwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQDDBxT +U0wuY29tIFRMUyBFQ0MgUm9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzM0OFoXDTQ2 +MDgxOTE2MzM0N1owTjELMAkGA1UEBhMCVVMxGDAWBgNVBAoMD1NTTCBDb3Jwb3Jh +dGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgRUNDIFJvb3QgQ0EgMjAyMjB2MBAG +ByqGSM49AgEGBSuBBAAiA2IABEUpNXP6wrgjzhR9qLFNoFs27iosU8NgCTWyJGYm +acCzldZdkkAZDsalE3D07xJRKF3nzL35PIXBz5SQySvOkkJYWWf9lCcQZIxPBLFN +SeR7T5v15wj4A4j3p8OSSxlUgaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSME +GDAWgBSJjy+j6CugFFR781a4Jl9nOAuc0DAdBgNVHQ4EFgQUiY8vo+groBRUe/NW +uCZfZzgLnNAwDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2gAMGUCMFXjIlbp +15IkWE8elDIPDAI2wv2sdDJO4fscgIijzPvX6yv/N33w7deedWo1dlJF4AIxAMeN +b0Igj762TVntd00pxCAgRWSGOlDGxK0tk/UYfXLtqc/ErFc2KAhl3zx5Zn6g6g== +-----END CERTIFICATE----- + +# Issuer: CN=Atos TrustedRoot Root CA ECC TLS 2021 O=Atos +# Subject: CN=Atos TrustedRoot Root CA ECC TLS 2021 O=Atos +# Label: "Atos TrustedRoot Root CA ECC TLS 2021" +# Serial: 81873346711060652204712539181482831616 +# MD5 Fingerprint: 16:9f:ad:f1:70:ad:79:d6:ed:29:b4:d1:c5:79:70:a8 +# SHA1 Fingerprint: 9e:bc:75:10:42:b3:02:f3:81:f4:f7:30:62:d4:8f:c3:a7:51:b2:dd +# SHA256 Fingerprint: b2:fa:e5:3e:14:cc:d7:ab:92:12:06:47:01:ae:27:9c:1d:89:88:fa:cb:77:5f:a8:a0:08:91:4e:66:39:88:a8 +-----BEGIN CERTIFICATE----- +MIICFTCCAZugAwIBAgIQPZg7pmY9kGP3fiZXOATvADAKBggqhkjOPQQDAzBMMS4w +LAYDVQQDDCVBdG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgRUNDIFRMUyAyMDIxMQ0w +CwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0yMTA0MjIwOTI2MjNaFw00MTA0 +MTcwOTI2MjJaMEwxLjAsBgNVBAMMJUF0b3MgVHJ1c3RlZFJvb3QgUm9vdCBDQSBF +Q0MgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNVBAYTAkRFMHYwEAYHKoZI +zj0CAQYFK4EEACIDYgAEloZYKDcKZ9Cg3iQZGeHkBQcfl+3oZIK59sRxUM6KDP/X +tXa7oWyTbIOiaG6l2b4siJVBzV3dscqDY4PMwL502eCdpO5KTlbgmClBk1IQ1SQ4 +AjJn8ZQSb+/Xxd4u/RmAo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR2 +KCXWfeBmmnoJsmo7jjPXNtNPojAOBgNVHQ8BAf8EBAMCAYYwCgYIKoZIzj0EAwMD +aAAwZQIwW5kp85wxtolrbNa9d+F851F+uDrNozZffPc8dz7kUK2o59JZDCaOMDtu +CCrCp1rIAjEAmeMM56PDr9NJLkaCI2ZdyQAUEv049OGYa3cpetskz2VAv9LcjBHo +9H1/IISpQuQo +-----END CERTIFICATE----- + +# Issuer: CN=Atos TrustedRoot Root CA RSA TLS 2021 O=Atos +# Subject: CN=Atos TrustedRoot Root CA RSA TLS 2021 O=Atos +# Label: "Atos TrustedRoot Root CA RSA TLS 2021" +# Serial: 111436099570196163832749341232207667876 +# MD5 Fingerprint: d4:d3:46:b8:9a:c0:9c:76:5d:9e:3a:c3:b9:99:31:d2 +# SHA1 Fingerprint: 18:52:3b:0d:06:37:e4:d6:3a:df:23:e4:98:fb:5b:16:fb:86:74:48 +# SHA256 Fingerprint: 81:a9:08:8e:a5:9f:b3:64:c5:48:a6:f8:55:59:09:9b:6f:04:05:ef:bf:18:e5:32:4e:c9:f4:57:ba:00:11:2f +-----BEGIN CERTIFICATE----- +MIIFZDCCA0ygAwIBAgIQU9XP5hmTC/srBRLYwiqipDANBgkqhkiG9w0BAQwFADBM +MS4wLAYDVQQDDCVBdG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgUlNBIFRMUyAyMDIx +MQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0yMTA0MjIwOTIxMTBaFw00 +MTA0MTcwOTIxMDlaMEwxLjAsBgNVBAMMJUF0b3MgVHJ1c3RlZFJvb3QgUm9vdCBD +QSBSU0EgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNVBAYTAkRFMIICIjAN +BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtoAOxHm9BYx9sKOdTSJNy/BBl01Z +4NH+VoyX8te9j2y3I49f1cTYQcvyAh5x5en2XssIKl4w8i1mx4QbZFc4nXUtVsYv +Ye+W/CBGvevUez8/fEc4BKkbqlLfEzfTFRVOvV98r61jx3ncCHvVoOX3W3WsgFWZ +kmGbzSoXfduP9LVq6hdKZChmFSlsAvFr1bqjM9xaZ6cF4r9lthawEO3NUDPJcFDs +GY6wx/J0W2tExn2WuZgIWWbeKQGb9Cpt0xU6kGpn8bRrZtkh68rZYnxGEFzedUln +nkL5/nWpo63/dgpnQOPF943HhZpZnmKaau1Fh5hnstVKPNe0OwANwI8f4UDErmwh +3El+fsqyjW22v5MvoVw+j8rtgI5Y4dtXz4U2OLJxpAmMkokIiEjxQGMYsluMWuPD +0xeqqxmjLBvk1cbiZnrXghmmOxYsL3GHX0WelXOTwkKBIROW1527k2gV+p2kHYzy +geBYBr3JtuP2iV2J+axEoctr+hbxx1A9JNr3w+SH1VbxT5Aw+kUJWdo0zuATHAR8 +ANSbhqRAvNncTFd+rrcztl524WWLZt+NyteYr842mIycg5kDcPOvdO3GDjbnvezB +c6eUWsuSZIKmAMFwoW4sKeFYV+xafJlrJaSQOoD0IJ2azsct+bJLKZWD6TWNp0lI +pw9MGZHQ9b8Q4HECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU +dEmZ0f+0emhFdcN+tNzMzjkz2ggwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB +DAUAA4ICAQAjQ1MkYlxt/T7Cz1UAbMVWiLkO3TriJQ2VSpfKgInuKs1l+NsW4AmS +4BjHeJi78+xCUvuppILXTdiK/ORO/auQxDh1MoSf/7OwKwIzNsAQkG8dnK/haZPs +o0UvFJ/1TCplQ3IM98P4lYsU84UgYt1UU90s3BiVaU+DR3BAM1h3Egyi61IxHkzJ +qM7F78PRreBrAwA0JrRUITWXAdxfG/F851X6LWh3e9NpzNMOa7pNdkTWwhWaJuyw +xfW70Xp0wmzNxbVe9kzmWy2B27O3Opee7c9GslA9hGCZcbUztVdF5kJHdWoOsAgM +rr3e97sPWD2PAzHoPYJQyi9eDF20l74gNAf0xBLh7tew2VktafcxBPTy+av5EzH4 +AXcOPUIjJsyacmdRIXrMPIWo6iFqO9taPKU0nprALN+AnCng33eU0aKAQv9qTFsR +0PXNor6uzFFcw9VUewyu1rkGd4Di7wcaaMxZUa1+XGdrudviB0JbuAEFWDlN5LuY +o7Ey7Nmj1m+UI/87tyll5gfp77YZ6ufCOB0yiJA8EytuzO+rdwY0d4RPcuSBhPm5 +dDTedk+SKlOxJTnbPP/lPqYO5Wue/9vsL3SD3460s6neFE3/MaNFcyT6lSnMEpcE +oji2jbDwN/zIIX8/syQbPYtuzE2wFg2WHYMfRsCbvUOZ58SWLs5fyQ== +-----END CERTIFICATE----- + +# Issuer: CN=TrustAsia Global Root CA G3 O=TrustAsia Technologies, Inc. +# Subject: CN=TrustAsia Global Root CA G3 O=TrustAsia Technologies, Inc. +# Label: "TrustAsia Global Root CA G3" +# Serial: 576386314500428537169965010905813481816650257167 +# MD5 Fingerprint: 30:42:1b:b7:bb:81:75:35:e4:16:4f:53:d2:94:de:04 +# SHA1 Fingerprint: 63:cf:b6:c1:27:2b:56:e4:88:8e:1c:23:9a:b6:2e:81:47:24:c3:c7 +# SHA256 Fingerprint: e0:d3:22:6a:eb:11:63:c2:e4:8f:f9:be:3b:50:b4:c6:43:1b:e7:bb:1e:ac:c5:c3:6b:5d:5e:c5:09:03:9a:08 +-----BEGIN CERTIFICATE----- +MIIFpTCCA42gAwIBAgIUZPYOZXdhaqs7tOqFhLuxibhxkw8wDQYJKoZIhvcNAQEM +BQAwWjELMAkGA1UEBhMCQ04xJTAjBgNVBAoMHFRydXN0QXNpYSBUZWNobm9sb2dp +ZXMsIEluYy4xJDAiBgNVBAMMG1RydXN0QXNpYSBHbG9iYWwgUm9vdCBDQSBHMzAe +Fw0yMTA1MjAwMjEwMTlaFw00NjA1MTkwMjEwMTlaMFoxCzAJBgNVBAYTAkNOMSUw +IwYDVQQKDBxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMSQwIgYDVQQDDBtU +cnVzdEFzaWEgR2xvYmFsIFJvb3QgQ0EgRzMwggIiMA0GCSqGSIb3DQEBAQUAA4IC +DwAwggIKAoICAQDAMYJhkuSUGwoqZdC+BqmHO1ES6nBBruL7dOoKjbmzTNyPtxNS +T1QY4SxzlZHFZjtqz6xjbYdT8PfxObegQ2OwxANdV6nnRM7EoYNl9lA+sX4WuDqK +AtCWHwDNBSHvBm3dIZwZQ0WhxeiAysKtQGIXBsaqvPPW5vxQfmZCHzyLpnl5hkA1 +nyDvP+uLRx+PjsXUjrYsyUQE49RDdT/VP68czH5GX6zfZBCK70bwkPAPLfSIC7Ep +qq+FqklYqL9joDiR5rPmd2jE+SoZhLsO4fWvieylL1AgdB4SQXMeJNnKziyhWTXA +yB1GJ2Faj/lN03J5Zh6fFZAhLf3ti1ZwA0pJPn9pMRJpxx5cynoTi+jm9WAPzJMs +hH/x/Gr8m0ed262IPfN2dTPXS6TIi/n1Q1hPy8gDVI+lhXgEGvNz8teHHUGf59gX +zhqcD0r83ERoVGjiQTz+LISGNzzNPy+i2+f3VANfWdP3kXjHi3dqFuVJhZBFcnAv +kV34PmVACxmZySYgWmjBNb9Pp1Hx2BErW+Canig7CjoKH8GB5S7wprlppYiU5msT +f9FkPz2ccEblooV7WIQn3MSAPmeamseaMQ4w7OYXQJXZRe0Blqq/DPNL0WP3E1jA +uPP6Z92bfW1K/zJMtSU7/xxnD4UiWQWRkUF3gdCFTIcQcf+eQxuulXUtgQIDAQAB +o2MwYTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFEDk5PIj7zjKsK5Xf/Ih +MBY027ySMB0GA1UdDgQWBBRA5OTyI+84yrCuV3/yITAWNNu8kjAOBgNVHQ8BAf8E +BAMCAQYwDQYJKoZIhvcNAQEMBQADggIBACY7UeFNOPMyGLS0XuFlXsSUT9SnYaP4 +wM8zAQLpw6o1D/GUE3d3NZ4tVlFEbuHGLige/9rsR82XRBf34EzC4Xx8MnpmyFq2 +XFNFV1pF1AWZLy4jVe5jaN/TG3inEpQGAHUNcoTpLrxaatXeL1nHo+zSh2bbt1S1 +JKv0Q3jbSwTEb93mPmY+KfJLaHEih6D4sTNjduMNhXJEIlU/HHzp/LgV6FL6qj6j +ITk1dImmasI5+njPtqzn59ZW/yOSLlALqbUHM/Q4X6RJpstlcHboCoWASzY9M/eV +VHUl2qzEc4Jl6VL1XP04lQJqaTDFHApXB64ipCz5xUG3uOyfT0gA+QEEVcys+TIx +xHWVBqB/0Y0n3bOppHKH/lmLmnp0Ft0WpWIp6zqW3IunaFnT63eROfjXy9mPX1on +AX1daBli2MjN9LdyR75bl87yraKZk62Uy5P2EgmVtqvXO9A/EcswFi55gORngS1d +7XB4tmBZrOFdRWOPyN9yaFvqHbgB8X7754qz41SgOAngPN5C8sLtLpvzHzW2Ntjj +gKGLzZlkD8Kqq7HK9W+eQ42EVJmzbsASZthwEPEGNTNDqJwuuhQxzhB/HIbjj9LV ++Hfsm6vxL2PZQl/gZ4FkkfGXL/xuJvYz+NO1+MRiqzFRJQJ6+N1rZdVtTTDIZbpo +FGWsJwt0ivKH +-----END CERTIFICATE----- + +# Issuer: CN=TrustAsia Global Root CA G4 O=TrustAsia Technologies, Inc. +# Subject: CN=TrustAsia Global Root CA G4 O=TrustAsia Technologies, Inc. +# Label: "TrustAsia Global Root CA G4" +# Serial: 451799571007117016466790293371524403291602933463 +# MD5 Fingerprint: 54:dd:b2:d7:5f:d8:3e:ed:7c:e0:0b:2e:cc:ed:eb:eb +# SHA1 Fingerprint: 57:73:a5:61:5d:80:b2:e6:ac:38:82:fc:68:07:31:ac:9f:b5:92:5a +# SHA256 Fingerprint: be:4b:56:cb:50:56:c0:13:6a:52:6d:f4:44:50:8d:aa:36:a0:b5:4f:42:e4:ac:38:f7:2a:f4:70:e4:79:65:4c +-----BEGIN CERTIFICATE----- +MIICVTCCAdygAwIBAgIUTyNkuI6XY57GU4HBdk7LKnQV1tcwCgYIKoZIzj0EAwMw +WjELMAkGA1UEBhMCQ04xJTAjBgNVBAoMHFRydXN0QXNpYSBUZWNobm9sb2dpZXMs +IEluYy4xJDAiBgNVBAMMG1RydXN0QXNpYSBHbG9iYWwgUm9vdCBDQSBHNDAeFw0y +MTA1MjAwMjEwMjJaFw00NjA1MTkwMjEwMjJaMFoxCzAJBgNVBAYTAkNOMSUwIwYD +VQQKDBxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMSQwIgYDVQQDDBtUcnVz +dEFzaWEgR2xvYmFsIFJvb3QgQ0EgRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATx +s8045CVD5d4ZCbuBeaIVXxVjAd7Cq92zphtnS4CDr5nLrBfbK5bKfFJV4hrhPVbw +LxYI+hW8m7tH5j/uqOFMjPXTNvk4XatwmkcN4oFBButJ+bAp3TPsUKV/eSm4IJij +YzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUpbtKl86zK3+kMd6Xg1mD +pm9xy94wHQYDVR0OBBYEFKW7SpfOsyt/pDHel4NZg6ZvccveMA4GA1UdDwEB/wQE +AwIBBjAKBggqhkjOPQQDAwNnADBkAjBe8usGzEkxn0AAbbd+NvBNEU/zy4k6LHiR +UKNbwMp1JvK/kF0LgoxgKJ/GcJpo5PECMFxYDlZ2z1jD1xCMuo6u47xkdUfFVZDj +/bpV6wfEU6s3qe4hsiFbYI89MvHVI5TWWA== +-----END CERTIFICATE----- + +# Issuer: CN=CommScope Public Trust ECC Root-01 O=CommScope +# Subject: CN=CommScope Public Trust ECC Root-01 O=CommScope +# Label: "CommScope Public Trust ECC Root-01" +# Serial: 385011430473757362783587124273108818652468453534 +# MD5 Fingerprint: 3a:40:a7:fc:03:8c:9c:38:79:2f:3a:a2:6c:b6:0a:16 +# SHA1 Fingerprint: 07:86:c0:d8:dd:8e:c0:80:98:06:98:d0:58:7a:ef:de:a6:cc:a2:5d +# SHA256 Fingerprint: 11:43:7c:da:7b:b4:5e:41:36:5f:45:b3:9a:38:98:6b:0d:e0:0d:ef:34:8e:0c:7b:b0:87:36:33:80:0b:c3:8b +-----BEGIN CERTIFICATE----- +MIICHTCCAaOgAwIBAgIUQ3CCd89NXTTxyq4yLzf39H91oJ4wCgYIKoZIzj0EAwMw +TjELMAkGA1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29t +bVNjb3BlIFB1YmxpYyBUcnVzdCBFQ0MgUm9vdC0wMTAeFw0yMTA0MjgxNzM1NDNa +Fw00NjA0MjgxNzM1NDJaME4xCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlDb21tU2Nv +cGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3QgRUNDIFJvb3QtMDEw +djAQBgcqhkjOPQIBBgUrgQQAIgNiAARLNumuV16ocNfQj3Rid8NeeqrltqLxeP0C +flfdkXmcbLlSiFS8LwS+uM32ENEp7LXQoMPwiXAZu1FlxUOcw5tjnSCDPgYLpkJE +hRGnSjot6dZoL0hOUysHP029uax3OVejQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD +VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSOB2LAUN3GGQYARnQE9/OufXVNMDAKBggq +hkjOPQQDAwNoADBlAjEAnDPfQeMjqEI2Jpc1XHvr20v4qotzVRVcrHgpD7oh2MSg +2NED3W3ROT3Ek2DS43KyAjB8xX6I01D1HiXo+k515liWpDVfG2XqYZpwI7UNo5uS +Um9poIyNStDuiw7LR47QjRE= +-----END CERTIFICATE----- + +# Issuer: CN=CommScope Public Trust ECC Root-02 O=CommScope +# Subject: CN=CommScope Public Trust ECC Root-02 O=CommScope +# Label: "CommScope Public Trust ECC Root-02" +# Serial: 234015080301808452132356021271193974922492992893 +# MD5 Fingerprint: 59:b0:44:d5:65:4d:b8:5c:55:19:92:02:b6:d1:94:b2 +# SHA1 Fingerprint: 3c:3f:ef:57:0f:fe:65:93:86:9e:a0:fe:b0:f6:ed:8e:d1:13:c7:e5 +# SHA256 Fingerprint: 2f:fb:7f:81:3b:bb:b3:c8:9a:b4:e8:16:2d:0f:16:d7:15:09:a8:30:cc:9d:73:c2:62:e5:14:08:75:d1:ad:4a +-----BEGIN CERTIFICATE----- +MIICHDCCAaOgAwIBAgIUKP2ZYEFHpgE6yhR7H+/5aAiDXX0wCgYIKoZIzj0EAwMw +TjELMAkGA1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29t +bVNjb3BlIFB1YmxpYyBUcnVzdCBFQ0MgUm9vdC0wMjAeFw0yMTA0MjgxNzQ0NTRa +Fw00NjA0MjgxNzQ0NTNaME4xCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlDb21tU2Nv +cGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3QgRUNDIFJvb3QtMDIw +djAQBgcqhkjOPQIBBgUrgQQAIgNiAAR4MIHoYx7l63FRD/cHB8o5mXxO1Q/MMDAL +j2aTPs+9xYa9+bG3tD60B8jzljHz7aRP+KNOjSkVWLjVb3/ubCK1sK9IRQq9qEmU +v4RDsNuESgMjGWdqb8FuvAY5N9GIIvejQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD +VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTmGHX/72DehKT1RsfeSlXjMjZ59TAKBggq +hkjOPQQDAwNnADBkAjAmc0l6tqvmSfR9Uj/UQQSugEODZXW5hYA4O9Zv5JOGq4/n +ich/m35rChJVYaoR4HkCMHfoMXGsPHED1oQmHhS48zs73u1Z/GtMMH9ZzkXpc2AV +mkzw5l4lIhVtwodZ0LKOag== +-----END CERTIFICATE----- + +# Issuer: CN=CommScope Public Trust RSA Root-01 O=CommScope +# Subject: CN=CommScope Public Trust RSA Root-01 O=CommScope +# Label: "CommScope Public Trust RSA Root-01" +# Serial: 354030733275608256394402989253558293562031411421 +# MD5 Fingerprint: 0e:b4:15:bc:87:63:5d:5d:02:73:d4:26:38:68:73:d8 +# SHA1 Fingerprint: 6d:0a:5f:f7:b4:23:06:b4:85:b3:b7:97:64:fc:ac:75:f5:33:f2:93 +# SHA256 Fingerprint: 02:bd:f9:6e:2a:45:dd:9b:f1:8f:c7:e1:db:df:21:a0:37:9b:a3:c9:c2:61:03:44:cf:d8:d6:06:fe:c1:ed:81 +-----BEGIN CERTIFICATE----- +MIIFbDCCA1SgAwIBAgIUPgNJgXUWdDGOTKvVxZAplsU5EN0wDQYJKoZIhvcNAQEL +BQAwTjELMAkGA1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwi +Q29tbVNjb3BlIFB1YmxpYyBUcnVzdCBSU0EgUm9vdC0wMTAeFw0yMTA0MjgxNjQ1 +NTRaFw00NjA0MjgxNjQ1NTNaME4xCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlDb21t +U2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3QgUlNBIFJvb3Qt +MDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwSGWjDR1C45FtnYSk +YZYSwu3D2iM0GXb26v1VWvZVAVMP8syMl0+5UMuzAURWlv2bKOx7dAvnQmtVzslh +suitQDy6uUEKBU8bJoWPQ7VAtYXR1HHcg0Hz9kXHgKKEUJdGzqAMxGBWBB0HW0al +DrJLpA6lfO741GIDuZNqihS4cPgugkY4Iw50x2tBt9Apo52AsH53k2NC+zSDO3Oj +WiE260f6GBfZumbCk6SP/F2krfxQapWsvCQz0b2If4b19bJzKo98rwjyGpg/qYFl +P8GMicWWMJoKz/TUyDTtnS+8jTiGU+6Xn6myY5QXjQ/cZip8UlF1y5mO6D1cv547 +KI2DAg+pn3LiLCuz3GaXAEDQpFSOm117RTYm1nJD68/A6g3czhLmfTifBSeolz7p +UcZsBSjBAg/pGG3svZwG1KdJ9FQFa2ww8esD1eo9anbCyxooSU1/ZOD6K9pzg4H/ +kQO9lLvkuI6cMmPNn7togbGEW682v3fuHX/3SZtS7NJ3Wn2RnU3COS3kuoL4b/JO +Hg9O5j9ZpSPcPYeoKFgo0fEbNttPxP/hjFtyjMcmAyejOQoBqsCyMWCDIqFPEgkB +Ea801M/XrmLTBQe0MXXgDW1XT2mH+VepuhX2yFJtocucH+X8eKg1mp9BFM6ltM6U +CBwJrVbl2rZJmkrqYxhTnCwuwwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G +A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUN12mmnQywsL5x6YVEFm45P3luG0wDQYJ +KoZIhvcNAQELBQADggIBAK+nz97/4L1CjU3lIpbfaOp9TSp90K09FlxD533Ahuh6 +NWPxzIHIxgvoLlI1pKZJkGNRrDSsBTtXAOnTYtPZKdVUvhwQkZyybf5Z/Xn36lbQ +nmhUQo8mUuJM3y+Xpi/SB5io82BdS5pYV4jvguX6r2yBS5KPQJqTRlnLX3gWsWc+ +QgvfKNmwrZggvkN80V4aCRckjXtdlemrwWCrWxhkgPut4AZ9HcpZuPN4KWfGVh2v +trV0KnahP/t1MJ+UXjulYPPLXAziDslg+MkfFoom3ecnf+slpoq9uC02EJqxWE2a +aE9gVOX2RhOOiKy8IUISrcZKiX2bwdgt6ZYD9KJ0DLwAHb/WNyVntHKLr4W96ioD +j8z7PEQkguIBpQtZtjSNMgsSDesnwv1B10A8ckYpwIzqug/xBpMu95yo9GA+o/E4 +Xo4TwbM6l4c/ksp4qRyv0LAbJh6+cOx69TOY6lz/KwsETkPdY34Op054A5U+1C0w +lREQKC6/oAI+/15Z0wUOlV9TRe9rh9VIzRamloPh37MG88EU26fsHItdkJANclHn +YfkUyq+Dj7+vsQpZXdxc1+SWrVtgHdqul7I52Qb1dgAT+GhMIbA1xNxVssnBQVoc +icCMb3SgazNNtQEo/a2tiRc7ppqEvOuM6sRxJKi6KfkIsidWNTJf6jn7MZrVGczw +-----END CERTIFICATE----- + +# Issuer: CN=CommScope Public Trust RSA Root-02 O=CommScope +# Subject: CN=CommScope Public Trust RSA Root-02 O=CommScope +# Label: "CommScope Public Trust RSA Root-02" +# Serial: 480062499834624527752716769107743131258796508494 +# MD5 Fingerprint: e1:29:f9:62:7b:76:e2:96:6d:f3:d4:d7:0f:ae:1f:aa +# SHA1 Fingerprint: ea:b0:e2:52:1b:89:93:4c:11:68:f2:d8:9a:ac:22:4c:a3:8a:57:ae +# SHA256 Fingerprint: ff:e9:43:d7:93:42:4b:4f:7c:44:0c:1c:3d:64:8d:53:63:f3:4b:82:dc:87:aa:7a:9f:11:8f:c5:de:e1:01:f1 +-----BEGIN CERTIFICATE----- +MIIFbDCCA1SgAwIBAgIUVBa/O345lXGN0aoApYYNK496BU4wDQYJKoZIhvcNAQEL +BQAwTjELMAkGA1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwi +Q29tbVNjb3BlIFB1YmxpYyBUcnVzdCBSU0EgUm9vdC0wMjAeFw0yMTA0MjgxNzE2 +NDNaFw00NjA0MjgxNzE2NDJaME4xCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlDb21t +U2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3QgUlNBIFJvb3Qt +MDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDh+g77aAASyE3VrCLE +NQE7xVTlWXZjpX/rwcRqmL0yjReA61260WI9JSMZNRTpf4mnG2I81lDnNJUDMrG0 +kyI9p+Kx7eZ7Ti6Hmw0zdQreqjXnfuU2mKKuJZ6VszKWpCtYHu8//mI0SFHRtI1C +rWDaSWqVcN3SAOLMV2MCe5bdSZdbkk6V0/nLKR8YSvgBKtJjCW4k6YnS5cciTNxz +hkcAqg2Ijq6FfUrpuzNPDlJwnZXjfG2WWy09X6GDRl224yW4fKcZgBzqZUPckXk2 +LHR88mcGyYnJ27/aaL8j7dxrrSiDeS/sOKUNNwFnJ5rpM9kzXzehxfCrPfp4sOcs +n/Y+n2Dg70jpkEUeBVF4GiwSLFworA2iI540jwXmojPOEXcT1A6kHkIfhs1w/tku +FT0du7jyU1fbzMZ0KZwYszZ1OC4PVKH4kh+Jlk+71O6d6Ts2QrUKOyrUZHk2EOH5 +kQMreyBUzQ0ZGshBMjTRsJnhkB4BQDa1t/qp5Xd1pCKBXbCL5CcSD1SIxtuFdOa3 +wNemKfrb3vOTlycEVS8KbzfFPROvCgCpLIscgSjX74Yxqa7ybrjKaixUR9gqiC6v +wQcQeKwRoi9C8DfF8rhW3Q5iLc4tVn5V8qdE9isy9COoR+jUKgF4z2rDN6ieZdIs +5fq6M8EGRPbmz6UNp2YINIos8wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G +A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUR9DnsSL/nSz12Vdgs7GxcJXvYXowDQYJ +KoZIhvcNAQELBQADggIBAIZpsU0v6Z9PIpNojuQhmaPORVMbc0RTAIFhzTHjCLqB +KCh6krm2qMhDnscTJk3C2OVVnJJdUNjCK9v+5qiXz1I6JMNlZFxHMaNlNRPDk7n3 ++VGXu6TwYofF1gbTl4MgqX67tiHCpQ2EAOHyJxCDut0DgdXdaMNmEMjRdrSzbyme +APnCKfWxkxlSaRosTKCL4BWaMS/TiJVZbuXEs1DIFAhKm4sTg7GkcrI7djNB3Nyq +pgdvHSQSn8h2vS/ZjvQs7rfSOBAkNlEv41xdgSGn2rtO/+YHqP65DSdsu3BaVXoT +6fEqSWnHX4dXTEN5bTpl6TBcQe7rd6VzEojov32u5cSoHw2OHG1QAk8mGEPej1WF +sQs3BWDJVTkSBKEqz3EWnzZRSb9wO55nnPt7eck5HHisd5FUmrh1CoFSl+NmYWvt +PjgelmFV4ZFUjO2MJB+ByRCac5krFk5yAD9UG/iNuovnFNa2RU9g7Jauwy8CTl2d +lklyALKrdVwPaFsdZcJfMw8eD/A7hvWwTruc9+olBdytoptLFwG+Qt81IR2tq670 +v64fG9PiO/yzcnMcmyiQiRM9HcEARwmWmjgb3bHPDcK0RPOWlc4yOo80nOAXx17O +rg3bhzjlP1v9mxnhMUF6cKojawHhRUzNlM47ni3niAIi9G7oyOzWPPO5std3eqx7 +-----END CERTIFICATE----- + +# Issuer: CN=Telekom Security TLS ECC Root 2020 O=Deutsche Telekom Security GmbH +# Subject: CN=Telekom Security TLS ECC Root 2020 O=Deutsche Telekom Security GmbH +# Label: "Telekom Security TLS ECC Root 2020" +# Serial: 72082518505882327255703894282316633856 +# MD5 Fingerprint: c1:ab:fe:6a:10:2c:03:8d:bc:1c:22:32:c0:85:a7:fd +# SHA1 Fingerprint: c0:f8:96:c5:a9:3b:01:06:21:07:da:18:42:48:bc:e9:9d:88:d5:ec +# SHA256 Fingerprint: 57:8a:f4:de:d0:85:3f:4e:59:98:db:4a:ea:f9:cb:ea:8d:94:5f:60:b6:20:a3:8d:1a:3c:13:b2:bc:7b:a8:e1 +-----BEGIN CERTIFICATE----- +MIICQjCCAcmgAwIBAgIQNjqWjMlcsljN0AFdxeVXADAKBggqhkjOPQQDAzBjMQsw +CQYDVQQGEwJERTEnMCUGA1UECgweRGV1dHNjaGUgVGVsZWtvbSBTZWN1cml0eSBH +bWJIMSswKQYDVQQDDCJUZWxla29tIFNlY3VyaXR5IFRMUyBFQ0MgUm9vdCAyMDIw +MB4XDTIwMDgyNTA3NDgyMFoXDTQ1MDgyNTIzNTk1OVowYzELMAkGA1UEBhMCREUx +JzAlBgNVBAoMHkRldXRzY2hlIFRlbGVrb20gU2VjdXJpdHkgR21iSDErMCkGA1UE +AwwiVGVsZWtvbSBTZWN1cml0eSBUTFMgRUNDIFJvb3QgMjAyMDB2MBAGByqGSM49 +AgEGBSuBBAAiA2IABM6//leov9Wq9xCazbzREaK9Z0LMkOsVGJDZos0MKiXrPk/O +tdKPD/M12kOLAoC+b1EkHQ9rK8qfwm9QMuU3ILYg/4gND21Ju9sGpIeQkpT0CdDP +f8iAC8GXs7s1J8nCG6NCMEAwHQYDVR0OBBYEFONyzG6VmUex5rNhTNHLq+O6zd6f +MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMDA2cA +MGQCMHVSi7ekEE+uShCLsoRbQuHmKjYC2qBuGT8lv9pZMo7k+5Dck2TOrbRBR2Di +z6fLHgIwN0GMZt9Ba9aDAEH9L1r3ULRn0SyocddDypwnJJGDSA3PzfdUga/sf+Rn +27iQ7t0l +-----END CERTIFICATE----- + +# Issuer: CN=Telekom Security TLS RSA Root 2023 O=Deutsche Telekom Security GmbH +# Subject: CN=Telekom Security TLS RSA Root 2023 O=Deutsche Telekom Security GmbH +# Label: "Telekom Security TLS RSA Root 2023" +# Serial: 44676229530606711399881795178081572759 +# MD5 Fingerprint: bf:5b:eb:54:40:cd:48:71:c4:20:8d:7d:de:0a:42:f2 +# SHA1 Fingerprint: 54:d3:ac:b3:bd:57:56:f6:85:9d:ce:e5:c3:21:e2:d4:ad:83:d0:93 +# SHA256 Fingerprint: ef:c6:5c:ad:bb:59:ad:b6:ef:e8:4d:a2:23:11:b3:56:24:b7:1b:3b:1e:a0:da:8b:66:55:17:4e:c8:97:86:46 +-----BEGIN CERTIFICATE----- +MIIFszCCA5ugAwIBAgIQIZxULej27HF3+k7ow3BXlzANBgkqhkiG9w0BAQwFADBj +MQswCQYDVQQGEwJERTEnMCUGA1UECgweRGV1dHNjaGUgVGVsZWtvbSBTZWN1cml0 +eSBHbWJIMSswKQYDVQQDDCJUZWxla29tIFNlY3VyaXR5IFRMUyBSU0EgUm9vdCAy +MDIzMB4XDTIzMDMyODEyMTY0NVoXDTQ4MDMyNzIzNTk1OVowYzELMAkGA1UEBhMC +REUxJzAlBgNVBAoMHkRldXRzY2hlIFRlbGVrb20gU2VjdXJpdHkgR21iSDErMCkG +A1UEAwwiVGVsZWtvbSBTZWN1cml0eSBUTFMgUlNBIFJvb3QgMjAyMzCCAiIwDQYJ +KoZIhvcNAQEBBQADggIPADCCAgoCggIBAO01oYGA88tKaVvC+1GDrib94W7zgRJ9 +cUD/h3VCKSHtgVIs3xLBGYSJwb3FKNXVS2xE1kzbB5ZKVXrKNoIENqil/Cf2SfHV +cp6R+SPWcHu79ZvB7JPPGeplfohwoHP89v+1VmLhc2o0mD6CuKyVU/QBoCcHcqMA +U6DksquDOFczJZSfvkgdmOGjup5czQRxUX11eKvzWarE4GC+j4NSuHUaQTXtvPM6 +Y+mpFEXX5lLRbtLevOP1Czvm4MS9Q2QTps70mDdsipWol8hHD/BeEIvnHRz+sTug +BTNoBUGCwQMrAcjnj02r6LX2zWtEtefdi+zqJbQAIldNsLGyMcEWzv/9FIS3R/qy +8XDe24tsNlikfLMR0cN3f1+2JeANxdKz+bi4d9s3cXFH42AYTyS2dTd4uaNir73J +co4vzLuu2+QVUhkHM/tqty1LkCiCc/4YizWN26cEar7qwU02OxY2kTLvtkCJkUPg +8qKrBC7m8kwOFjQgrIfBLX7JZkcXFBGk8/ehJImr2BrIoVyxo/eMbcgByU/J7MT8 +rFEz0ciD0cmfHdRHNCk+y7AO+oMLKFjlKdw/fKifybYKu6boRhYPluV75Gp6SG12 +mAWl3G0eQh5C2hrgUve1g8Aae3g1LDj1H/1Joy7SWWO/gLCMk3PLNaaZlSJhZQNg ++y+TS/qanIA7AgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUtqeX +gj10hZv3PJ+TmpV5dVKMbUcwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS2 +p5eCPXSFm/c8n5OalXl1UoxtRzANBgkqhkiG9w0BAQwFAAOCAgEAqMxhpr51nhVQ +pGv7qHBFfLp+sVr8WyP6Cnf4mHGCDG3gXkaqk/QeoMPhk9tLrbKmXauw1GLLXrtm +9S3ul0A8Yute1hTWjOKWi0FpkzXmuZlrYrShF2Y0pmtjxrlO8iLpWA1WQdH6DErw +M807u20hOq6OcrXDSvvpfeWxm4bu4uB9tPcy/SKE8YXJN3nptT+/XOR0so8RYgDd +GGah2XsjX/GO1WfoVNpbOms2b/mBsTNHM3dA+VKq3dSDz4V4mZqTuXNnQkYRIer+ +CqkbGmVps4+uFrb2S1ayLfmlyOw7YqPta9BO1UAJpB+Y1zqlklkg5LB9zVtzaL1t +xKITDmcZuI1CfmwMmm6gJC3VRRvcxAIU/oVbZZfKTpBQCHpCNfnqwmbU+AGuHrS+ +w6jv/naaoqYfRvaE7fzbzsQCzndILIyy7MMAo+wsVRjBfhnu4S/yrYObnqsZ38aK +L4x35bcF7DvB7L6Gs4a8wPfc5+pbrrLMtTWGS9DiP7bY+A4A7l3j941Y/8+LN+lj +X273CXE2whJdV/LItM3z7gLfEdxquVeEHVlNjM7IDiPCtyaaEBRx/pOyiriA8A4Q +ntOoUAw3gi/q4Iqd4Sw5/7W0cwDk90imc6y/st53BIe0o82bNSQ3+pCTE4FCxpgm +dTdmQRCsu/WU48IxK63nI1bMNSWSs1A= +-----END CERTIFICATE----- + +# Issuer: CN=FIRMAPROFESIONAL CA ROOT-A WEB O=Firmaprofesional SA +# Subject: CN=FIRMAPROFESIONAL CA ROOT-A WEB O=Firmaprofesional SA +# Label: "FIRMAPROFESIONAL CA ROOT-A WEB" +# Serial: 65916896770016886708751106294915943533 +# MD5 Fingerprint: 82:b2:ad:45:00:82:b0:66:63:f8:5f:c3:67:4e:ce:a3 +# SHA1 Fingerprint: a8:31:11:74:a6:14:15:0d:ca:77:dd:0e:e4:0c:5d:58:fc:a0:72:a5 +# SHA256 Fingerprint: be:f2:56:da:f2:6e:9c:69:bd:ec:16:02:35:97:98:f3:ca:f7:18:21:a0:3e:01:82:57:c5:3c:65:61:7f:3d:4a +-----BEGIN CERTIFICATE----- +MIICejCCAgCgAwIBAgIQMZch7a+JQn81QYehZ1ZMbTAKBggqhkjOPQQDAzBuMQsw +CQYDVQQGEwJFUzEcMBoGA1UECgwTRmlybWFwcm9mZXNpb25hbCBTQTEYMBYGA1UE +YQwPVkFURVMtQTYyNjM0MDY4MScwJQYDVQQDDB5GSVJNQVBST0ZFU0lPTkFMIENB +IFJPT1QtQSBXRUIwHhcNMjIwNDA2MDkwMTM2WhcNNDcwMzMxMDkwMTM2WjBuMQsw +CQYDVQQGEwJFUzEcMBoGA1UECgwTRmlybWFwcm9mZXNpb25hbCBTQTEYMBYGA1UE +YQwPVkFURVMtQTYyNjM0MDY4MScwJQYDVQQDDB5GSVJNQVBST0ZFU0lPTkFMIENB +IFJPT1QtQSBXRUIwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARHU+osEaR3xyrq89Zf +e9MEkVz6iMYiuYMQYneEMy3pA4jU4DP37XcsSmDq5G+tbbT4TIqk5B/K6k84Si6C +cyvHZpsKjECcfIr28jlgst7L7Ljkb+qbXbdTkBgyVcUgt5SjYzBhMA8GA1UdEwEB +/wQFMAMBAf8wHwYDVR0jBBgwFoAUk+FDY1w8ndYn81LsF7Kpryz3dvgwHQYDVR0O +BBYEFJPhQ2NcPJ3WJ/NS7Beyqa8s93b4MA4GA1UdDwEB/wQEAwIBBjAKBggqhkjO +PQQDAwNoADBlAjAdfKR7w4l1M+E7qUW/Runpod3JIha3RxEL2Jq68cgLcFBTApFw +hVmpHqTm6iMxoAACMQD94vizrxa5HnPEluPBMBnYfubDl94cT7iJLzPrSA8Z94dG +XSaQpYXFuXqUPoeovQA= +-----END CERTIFICATE----- + +# Issuer: CN=TWCA CYBER Root CA O=TAIWAN-CA OU=Root CA +# Subject: CN=TWCA CYBER Root CA O=TAIWAN-CA OU=Root CA +# Label: "TWCA CYBER Root CA" +# Serial: 85076849864375384482682434040119489222 +# MD5 Fingerprint: 0b:33:a0:97:52:95:d4:a9:fd:bb:db:6e:a3:55:5b:51 +# SHA1 Fingerprint: f6:b1:1c:1a:83:38:e9:7b:db:b3:a8:c8:33:24:e0:2d:9c:7f:26:66 +# SHA256 Fingerprint: 3f:63:bb:28:14:be:17:4e:c8:b6:43:9c:f0:8d:6d:56:f0:b7:c4:05:88:3a:56:48:a3:34:42:4d:6b:3e:c5:58 +-----BEGIN CERTIFICATE----- +MIIFjTCCA3WgAwIBAgIQQAE0jMIAAAAAAAAAATzyxjANBgkqhkiG9w0BAQwFADBQ +MQswCQYDVQQGEwJUVzESMBAGA1UEChMJVEFJV0FOLUNBMRAwDgYDVQQLEwdSb290 +IENBMRswGQYDVQQDExJUV0NBIENZQkVSIFJvb3QgQ0EwHhcNMjIxMTIyMDY1NDI5 +WhcNNDcxMTIyMTU1OTU5WjBQMQswCQYDVQQGEwJUVzESMBAGA1UEChMJVEFJV0FO +LUNBMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJUV0NBIENZQkVSIFJvb3Qg +Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDG+Moe2Qkgfh1sTs6P +40czRJzHyWmqOlt47nDSkvgEs1JSHWdyKKHfi12VCv7qze33Kc7wb3+szT3vsxxF +avcokPFhV8UMxKNQXd7UtcsZyoC5dc4pztKFIuwCY8xEMCDa6pFbVuYdHNWdZsc/ +34bKS1PE2Y2yHer43CdTo0fhYcx9tbD47nORxc5zb87uEB8aBs/pJ2DFTxnk684i +JkXXYJndzk834H/nY62wuFm40AZoNWDTNq5xQwTxaWV4fPMf88oon1oglWa0zbfu +j3ikRRjpJi+NmykosaS3Om251Bw4ckVYsV7r8Cibt4LK/c/WMw+f+5eesRycnupf +Xtuq3VTpMCEobY5583WSjCb+3MX2w7DfRFlDo7YDKPYIMKoNM+HvnKkHIuNZW0CP +2oi3aQiotyMuRAlZN1vH4xfyIutuOVLF3lSnmMlLIJXcRolftBL5hSmO68gnFSDA +S9TMfAxsNAwmmyYxpjyn9tnQS6Jk/zuZQXLB4HCX8SS7K8R0IrGsayIyJNN4KsDA +oS/xUgXJP+92ZuJF2A09rZXIx4kmyA+upwMu+8Ff+iDhcK2wZSA3M2Cw1a/XDBzC +kHDXShi8fgGwsOsVHkQGzaRP6AzRwyAQ4VRlnrZR0Bp2a0JaWHY06rc3Ga4udfmW +5cFZ95RXKSWNOkyrTZpB0F8mAwIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAQYwDwYD +VR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBSdhWEUfMFib5do5E83QOGt4A1WNzAd +BgNVHQ4EFgQUnYVhFHzBYm+XaORPN0DhreANVjcwDQYJKoZIhvcNAQEMBQADggIB +AGSPesRiDrWIzLjHhg6hShbNcAu3p4ULs3a2D6f/CIsLJc+o1IN1KriWiLb73y0t +tGlTITVX1olNc79pj3CjYcya2x6a4CD4bLubIp1dhDGaLIrdaqHXKGnK/nZVekZn +68xDiBaiA9a5F/gZbG0jAn/xX9AKKSM70aoK7akXJlQKTcKlTfjF/biBzysseKNn +TKkHmvPfXvt89YnNdJdhEGoHK4Fa0o635yDRIG4kqIQnoVesqlVYL9zZyvpoBJ7t +RCT5dEA7IzOrg1oYJkK2bVS1FmAwbLGg+LhBoF1JSdJlBTrq/p1hvIbZv97Tujqx +f36SNI7JAG7cmL3c7IAFrQI932XtCwP39xaEBDG6k5TY8hL4iuO/Qq+n1M0RFxbI +Qh0UqEL20kCGoE8jypZFVmAGzbdVAaYBlGX+bgUJurSkquLvWL69J1bY73NxW0Qz +8ppy6rBePm6pUlvscG21h483XjyMnM7k8M4MZ0HMzvaAq07MTFb1wWFZk7Q+ptq4 +NxKfKjLji7gh7MMrZQzvIt6IKTtM1/r+t+FHvpw+PoP7UV31aPcuIYXcv/Fa4nzX +xeSDwWrruoBa3lwtcHb4yOWHh8qgnaHlIhInD0Q9HWzq1MKLL295q39QpsQZp6F6 +t5b5wR9iWqJDB0BeJsas7a5wFsWqynKKTbDPAYsDP27X +-----END CERTIFICATE----- + +# Issuer: CN=SecureSign Root CA12 O=Cybertrust Japan Co., Ltd. +# Subject: CN=SecureSign Root CA12 O=Cybertrust Japan Co., Ltd. +# Label: "SecureSign Root CA12" +# Serial: 587887345431707215246142177076162061960426065942 +# MD5 Fingerprint: c6:89:ca:64:42:9b:62:08:49:0b:1e:7f:e9:07:3d:e8 +# SHA1 Fingerprint: 7a:22:1e:3d:de:1b:06:ac:9e:c8:47:70:16:8e:3c:e5:f7:6b:06:f4 +# SHA256 Fingerprint: 3f:03:4b:b5:70:4d:44:b2:d0:85:45:a0:20:57:de:93:eb:f3:90:5f:ce:72:1a:cb:c7:30:c0:6d:da:ee:90:4e +-----BEGIN CERTIFICATE----- +MIIDcjCCAlqgAwIBAgIUZvnHwa/swlG07VOX5uaCwysckBYwDQYJKoZIhvcNAQEL +BQAwUTELMAkGA1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28u +LCBMdGQuMR0wGwYDVQQDExRTZWN1cmVTaWduIFJvb3QgQ0ExMjAeFw0yMDA0MDgw +NTM2NDZaFw00MDA0MDgwNTM2NDZaMFExCzAJBgNVBAYTAkpQMSMwIQYDVQQKExpD +eWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMUU2VjdXJlU2lnbiBS +b290IENBMTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6OcE3emhF +KxS06+QT61d1I02PJC0W6K6OyX2kVzsqdiUzg2zqMoqUm048luT9Ub+ZyZN+v/mt +p7JIKwccJ/VMvHASd6SFVLX9kHrko+RRWAPNEHl57muTH2SOa2SroxPjcf59q5zd +J1M3s6oYwlkm7Fsf0uZlfO+TvdhYXAvA42VvPMfKWeP+bl+sg779XSVOKik71gur +FzJ4pOE+lEa+Ym6b3kaosRbnhW70CEBFEaCeVESE99g2zvVQR9wsMJvuwPWW0v4J +hscGWa5Pro4RmHvzC1KqYiaqId+OJTN5lxZJjfU+1UefNzFJM3IFTQy2VYzxV4+K +h9GtxRESOaCtAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD +AgEGMB0GA1UdDgQWBBRXNPN0zwRL1SXm8UC2LEzZLemgrTANBgkqhkiG9w0BAQsF +AAOCAQEAPrvbFxbS8hQBICw4g0utvsqFepq2m2um4fylOqyttCg6r9cBg0krY6Ld +mmQOmFxv3Y67ilQiLUoT865AQ9tPkbeGGuwAtEGBpE/6aouIs3YIcipJQMPTw4WJ +mBClnW8Zt7vPemVV2zfrPIpyMpcemik+rY3moxtt9XUa5rBouVui7mlHJzWhhpmA +8zNL4WukJsPvdFlseqJkth5Ew1DgDzk9qTPxpfPSvWKErI4cqc1avTc7bgoitPQV +55FYxTpE05Uo2cBl6XLK0A+9H7MV2anjpEcJnuDLN/v9vZfVvhgaaaI5gdka9at/ +yOPiZwud9AzqVN/Ssq+xIvEg37xEHA== +-----END CERTIFICATE----- + +# Issuer: CN=SecureSign Root CA14 O=Cybertrust Japan Co., Ltd. +# Subject: CN=SecureSign Root CA14 O=Cybertrust Japan Co., Ltd. +# Label: "SecureSign Root CA14" +# Serial: 575790784512929437950770173562378038616896959179 +# MD5 Fingerprint: 71:0d:72:fa:92:19:65:5e:89:04:ac:16:33:f0:bc:d5 +# SHA1 Fingerprint: dd:50:c0:f7:79:b3:64:2e:74:a2:b8:9d:9f:d3:40:dd:bb:f0:f2:4f +# SHA256 Fingerprint: 4b:00:9c:10:34:49:4f:9a:b5:6b:ba:3b:a1:d6:27:31:fc:4d:20:d8:95:5a:dc:ec:10:a9:25:60:72:61:e3:38 +-----BEGIN CERTIFICATE----- +MIIFcjCCA1qgAwIBAgIUZNtaDCBO6Ncpd8hQJ6JaJ90t8sswDQYJKoZIhvcNAQEM +BQAwUTELMAkGA1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28u +LCBMdGQuMR0wGwYDVQQDExRTZWN1cmVTaWduIFJvb3QgQ0ExNDAeFw0yMDA0MDgw +NzA2MTlaFw00NTA0MDgwNzA2MTlaMFExCzAJBgNVBAYTAkpQMSMwIQYDVQQKExpD +eWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMUU2VjdXJlU2lnbiBS +b290IENBMTQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDF0nqh1oq/ +FjHQmNE6lPxauG4iwWL3pwon71D2LrGeaBLwbCRjOfHw3xDG3rdSINVSW0KZnvOg +vlIfX8xnbacuUKLBl422+JX1sLrcneC+y9/3OPJH9aaakpUqYllQC6KxNedlsmGy +6pJxaeQp8E+BgQQ8sqVb1MWoWWd7VRxJq3qdwudzTe/NCcLEVxLbAQ4jeQkHO6Lo +/IrPj8BGJJw4J+CDnRugv3gVEOuGTgpa/d/aLIJ+7sr2KeH6caH3iGicnPCNvg9J +kdjqOvn90Ghx2+m1K06Ckm9mH+Dw3EzsytHqunQG+bOEkJTRX45zGRBdAuVwpcAQ +0BB8b8VYSbSwbprafZX1zNoCr7gsfXmPvkPx+SgojQlD+Ajda8iLLCSxjVIHvXib +y8posqTdDEx5YMaZ0ZPxMBoH064iwurO8YQJzOAUbn8/ftKChazcqRZOhaBgy/ac +18izju3Gm5h1DVXoX+WViwKkrkMpKBGk5hIwAUt1ax5mnXkvpXYvHUC0bcl9eQjs +0Wq2XSqypWa9a4X0dFbD9ed1Uigspf9mR6XU/v6eVL9lfgHWMI+lNpyiUBzuOIAB +SMbHdPTGrMNASRZhdCyvjG817XsYAFs2PJxQDcqSMxDxJklt33UkN4Ii1+iW/RVL +ApY+B3KVfqs9TC7XyvDf4Fg/LS8EmjijAQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUBpOjCl4oaTeqYR3r6/wtbyPk +86AwDQYJKoZIhvcNAQEMBQADggIBAJaAcgkGfpzMkwQWu6A6jZJOtxEaCnFxEM0E +rX+lRVAQZk5KQaID2RFPeje5S+LGjzJmdSX7684/AykmjbgWHfYfM25I5uj4V7Ib +ed87hwriZLoAymzvftAj63iP/2SbNDefNWWipAA9EiOWWF3KY4fGoweITedpdopT +zfFP7ELyk+OZpDc8h7hi2/DsHzc/N19DzFGdtfCXwreFamgLRB7lUe6TzktuhsHS +DCRZNhqfLJGP4xjblJUK7ZGqDpncllPjYYPGFrojutzdfhrGe0K22VoF3Jpf1d+4 +2kd92jjbrDnVHmtsKheMYc2xbXIBw8MgAGJoFjHVdqqGuw6qnsb58Nn4DSEC5MUo +FlkRudlpcyqSeLiSV5sI8jrlL5WwWLdrIBRtFO8KvH7YVdiI2i/6GaX7i+B/OfVy +K4XELKzvGUWSTLNhB9xNH27SgRNcmvMSZ4PPmz+Ln52kuaiWA3rF7iDeM9ovnhp6 +dB7h7sxaOgTdsxoEqBRjrLdHEoOabPXm6RUVkRqEGQ6UROcSjiVbgGcZ3GOTEAtl +Lor6CZpO2oYofaphNdgOpygau1LgePhsumywbrmHXumZNTfxPWQrqaA0k89jL9WB +365jJ6UeTo3cKXhZ+PmhIIynJkBugnLNeLLIjzwec+fBH7/PzqUqm9tEZDKgu39c +JRNItX+S +-----END CERTIFICATE----- + +# Issuer: CN=SecureSign Root CA15 O=Cybertrust Japan Co., Ltd. +# Subject: CN=SecureSign Root CA15 O=Cybertrust Japan Co., Ltd. +# Label: "SecureSign Root CA15" +# Serial: 126083514594751269499665114766174399806381178503 +# MD5 Fingerprint: 13:30:fc:c4:62:a6:a9:de:b5:c1:68:af:b5:d2:31:47 +# SHA1 Fingerprint: cb:ba:83:c8:c1:5a:5d:f1:f9:73:6f:ca:d7:ef:28:13:06:4a:07:7d +# SHA256 Fingerprint: e7:78:f0:f0:95:fe:84:37:29:cd:1a:00:82:17:9e:53:14:a9:c2:91:44:28:05:e1:fb:1d:8f:b6:b8:88:6c:3a +-----BEGIN CERTIFICATE----- +MIICIzCCAamgAwIBAgIUFhXHw9hJp75pDIqI7fBw+d23PocwCgYIKoZIzj0EAwMw +UTELMAkGA1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28uLCBM +dGQuMR0wGwYDVQQDExRTZWN1cmVTaWduIFJvb3QgQ0ExNTAeFw0yMDA0MDgwODMy +NTZaFw00NTA0MDgwODMyNTZaMFExCzAJBgNVBAYTAkpQMSMwIQYDVQQKExpDeWJl +cnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMUU2VjdXJlU2lnbiBSb290 +IENBMTUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQLUHSNZDKZmbPSYAi4Io5GdCx4 +wCtELW1fHcmuS1Iggz24FG1Th2CeX2yF2wYUleDHKP+dX+Sq8bOLbe1PL0vJSpSR +ZHX+AezB2Ot6lHhWGENfa4HL9rzatAy2KZMIaY+jQjBAMA8GA1UdEwEB/wQFMAMB +Af8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTrQciu/NWeUUj1vYv0hyCTQSvT +9DAKBggqhkjOPQQDAwNoADBlAjEA2S6Jfl5OpBEHvVnCB96rMjhTKkZEBhd6zlHp +4P9mLQlO4E/0BdGF9jVg3PVys0Z9AjBEmEYagoUeYWmJSwdLZrWeqrqgHkHZAXQ6 +bkU6iYAZezKYVWOr62Nuk22rGwlgMU4= +-----END CERTIFICATE----- + +# Issuer: CN=D-TRUST BR Root CA 2 2023 O=D-Trust GmbH +# Subject: CN=D-TRUST BR Root CA 2 2023 O=D-Trust GmbH +# Label: "D-TRUST BR Root CA 2 2023" +# Serial: 153168538924886464690566649552453098598 +# MD5 Fingerprint: e1:09:ed:d3:60:d4:56:1b:47:1f:b7:0c:5f:1b:5f:85 +# SHA1 Fingerprint: 2d:b0:70:ee:71:94:af:69:68:17:db:79:ce:58:9f:a0:6b:96:f7:87 +# SHA256 Fingerprint: 05:52:e6:f8:3f:df:65:e8:fa:96:70:e6:66:df:28:a4:e2:13:40:b5:10:cb:e5:25:66:f9:7c:4f:b9:4b:2b:d1 +-----BEGIN CERTIFICATE----- +MIIFqTCCA5GgAwIBAgIQczswBEhb2U14LnNLyaHcZjANBgkqhkiG9w0BAQ0FADBI +MQswCQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlE +LVRSVVNUIEJSIFJvb3QgQ0EgMiAyMDIzMB4XDTIzMDUwOTA4NTYzMVoXDTM4MDUw +OTA4NTYzMFowSDELMAkGA1UEBhMCREUxFTATBgNVBAoTDEQtVHJ1c3QgR21iSDEi +MCAGA1UEAxMZRC1UUlVTVCBCUiBSb290IENBIDIgMjAyMzCCAiIwDQYJKoZIhvcN +AQEBBQADggIPADCCAgoCggIBAK7/CVmRgApKaOYkP7in5Mg6CjoWzckjYaCTcfKr +i3OPoGdlYNJUa2NRb0kz4HIHE304zQaSBylSa053bATTlfrdTIzZXcFhfUvnKLNE +gXtRr90zsWh81k5M/itoucpmacTsXld/9w3HnDY25QdgrMBM6ghs7wZ8T1soegj8 +k12b9py0i4a6Ibn08OhZWiihNIQaJZG2tY/vsvmA+vk9PBFy2OMvhnbFeSzBqZCT +Rphny4NqoFAjpzv2gTng7fC5v2Xx2Mt6++9zA84A9H3X4F07ZrjcjrqDy4d2A/wl +2ecjbwb9Z/Pg/4S8R7+1FhhGaRTMBffb00msa8yr5LULQyReS2tNZ9/WtT5PeB+U +cSTq3nD88ZP+npNa5JRal1QMNXtfbO4AHyTsA7oC9Xb0n9Sa7YUsOCIvx9gvdhFP +/Wxc6PWOJ4d/GUohR5AdeY0cW/jPSoXk7bNbjb7EZChdQcRurDhaTyN0dKkSw/bS +uREVMweR2Ds3OmMwBtHFIjYoYiMQ4EbMl6zWK11kJNXuHA7e+whadSr2Y23OC0K+ +0bpwHJwh5Q8xaRfX/Aq03u2AnMuStIv13lmiWAmlY0cL4UEyNEHZmrHZqLAbWt4N +DfTisl01gLmB1IRpkQLLddCNxbU9CZEJjxShFHR5PtbJFR2kWVki3PaKRT08EtY+ +XTIvAgMBAAGjgY4wgYswDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUZ5Dw1t61 +GNVGKX5cq/ieCLxklRAwDgYDVR0PAQH/BAQDAgEGMEkGA1UdHwRCMEAwPqA8oDqG +OGh0dHA6Ly9jcmwuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3RfYnJfcm9vdF9jYV8y +XzIwMjMuY3JsMA0GCSqGSIb3DQEBDQUAA4ICAQA097N3U9swFrktpSHxQCF16+tI +FoE9c+CeJyrrd6kTpGoKWloUMz1oH4Guaf2Mn2VsNELZLdB/eBaxOqwjMa1ef67n +riv6uvw8l5VAk1/DLQOj7aRvU9f6QA4w9QAgLABMjDu0ox+2v5Eyq6+SmNMW5tTR +VFxDWy6u71cqqLRvpO8NVhTaIasgdp4D/Ca4nj8+AybmTNudX0KEPUUDAxxZiMrc +LmEkWqTqJwtzEr5SswrPMhfiHocaFpVIbVrg0M8JkiZmkdijYQ6qgYF/6FKC0ULn +4B0Y+qSFNueG4A3rvNTJ1jxD8V1Jbn6Bm2m1iWKPiFLY1/4nwSPFyysCu7Ff/vtD +hQNGvl3GyiEm/9cCnnRK3PgTFbGBVzbLZVzRHTF36SXDw7IyN9XxmAnkbWOACKsG +koHU6XCPpz+y7YaMgmo1yEJagtFSGkUPFaUA8JR7ZSdXOUPPfH/mvTWze/EZTN46 +ls/pdu4D58JDUjxqgejBWoC9EV2Ta/vH5mQ/u2kc6d0li690yVRAysuTEwrt+2aS +Ecr1wPrYg1UDfNPFIkZ1cGt5SAYqgpq/5usWDiJFAbzdNpQ0qTUmiteXue4Icr80 +knCDgKs4qllo3UCkGJCy89UDyibK79XH4I9TjvAA46jtn/mtd+ArY0+ew+43u3gJ +hJ65bvspmZDogNOfJA== +-----END CERTIFICATE----- + +# Issuer: CN=TrustAsia TLS ECC Root CA O=TrustAsia Technologies, Inc. +# Subject: CN=TrustAsia TLS ECC Root CA O=TrustAsia Technologies, Inc. +# Label: "TrustAsia TLS ECC Root CA" +# Serial: 310892014698942880364840003424242768478804666567 +# MD5 Fingerprint: 09:48:04:77:d2:fc:65:93:71:66:b1:11:95:4f:06:8c +# SHA1 Fingerprint: b5:ec:39:f3:a1:66:37:ae:c3:05:94:57:e2:be:11:be:b7:a1:7f:36 +# SHA256 Fingerprint: c0:07:6b:9e:f0:53:1f:b1:a6:56:d6:7c:4e:be:97:cd:5d:ba:a4:1e:f4:45:98:ac:c2:48:98:78:c9:2d:87:11 +-----BEGIN CERTIFICATE----- +MIICMTCCAbegAwIBAgIUNnThTXxlE8msg1UloD5Sfi9QaMcwCgYIKoZIzj0EAwMw +WDELMAkGA1UEBhMCQ04xJTAjBgNVBAoTHFRydXN0QXNpYSBUZWNobm9sb2dpZXMs +IEluYy4xIjAgBgNVBAMTGVRydXN0QXNpYSBUTFMgRUNDIFJvb3QgQ0EwHhcNMjQw +NTE1MDU0MTU2WhcNNDQwNTE1MDU0MTU1WjBYMQswCQYDVQQGEwJDTjElMCMGA1UE +ChMcVHJ1c3RBc2lhIFRlY2hub2xvZ2llcywgSW5jLjEiMCAGA1UEAxMZVHJ1c3RB +c2lhIFRMUyBFQ0MgUm9vdCBDQTB2MBAGByqGSM49AgEGBSuBBAAiA2IABLh/pVs/ +AT598IhtrimY4ZtcU5nb9wj/1WrgjstEpvDBjL1P1M7UiFPoXlfXTr4sP/MSpwDp +guMqWzJ8S5sUKZ74LYO1644xST0mYekdcouJtgq7nDM1D9rs3qlKH8kzsaNCMEAw +DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQULIVTu7FDzTLqnqOH/qKYqKaT6RAw +DgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMDA2gAMGUCMFRH18MtYYZI9HlaVQ01 +L18N9mdsd0AaRuf4aFtOJx24mH1/k78ITcTaRTChD15KeAIxAKORh/IRM4PDwYqR +OkwrULG9IpRdNYlzg8WbGf60oenUoWa2AaU2+dhoYSi3dOGiMQ== +-----END CERTIFICATE----- + +# Issuer: CN=TrustAsia TLS RSA Root CA O=TrustAsia Technologies, Inc. +# Subject: CN=TrustAsia TLS RSA Root CA O=TrustAsia Technologies, Inc. +# Label: "TrustAsia TLS RSA Root CA" +# Serial: 160405846464868906657516898462547310235378010780 +# MD5 Fingerprint: 3b:9e:c3:86:0f:34:3c:6b:c5:46:c4:8e:1d:e7:19:12 +# SHA1 Fingerprint: a5:46:50:c5:62:ea:95:9a:1a:a7:04:6f:17:58:c7:29:53:3d:03:fa +# SHA256 Fingerprint: 06:c0:8d:7d:af:d8:76:97:1e:b1:12:4f:e6:7f:84:7e:c0:c7:a1:58:d3:ea:53:cb:e9:40:e2:ea:97:91:f4:c3 +-----BEGIN CERTIFICATE----- +MIIFgDCCA2igAwIBAgIUHBjYz+VTPyI1RlNUJDxsR9FcSpwwDQYJKoZIhvcNAQEM +BQAwWDELMAkGA1UEBhMCQ04xJTAjBgNVBAoTHFRydXN0QXNpYSBUZWNobm9sb2dp +ZXMsIEluYy4xIjAgBgNVBAMTGVRydXN0QXNpYSBUTFMgUlNBIFJvb3QgQ0EwHhcN +MjQwNTE1MDU0MTU3WhcNNDQwNTE1MDU0MTU2WjBYMQswCQYDVQQGEwJDTjElMCMG +A1UEChMcVHJ1c3RBc2lhIFRlY2hub2xvZ2llcywgSW5jLjEiMCAGA1UEAxMZVHJ1 +c3RBc2lhIFRMUyBSU0EgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC +AgoCggIBAMMWuBtqpERz5dZO9LnPWwvB0ZqB9WOwj0PBuwhaGnrhB3YmH49pVr7+ +NmDQDIPNlOrnxS1cLwUWAp4KqC/lYCZUlviYQB2srp10Zy9U+5RjmOMmSoPGlbYJ +Q1DNDX3eRA5gEk9bNb2/mThtfWza4mhzH/kxpRkQcwUqwzIZheo0qt1CHjCNP561 +HmHVb70AcnKtEj+qpklz8oYVlQwQX1Fkzv93uMltrOXVmPGZLmzjyUT5tUMnCE32 +ft5EebuyjBza00tsLtbDeLdM1aTk2tyKjg7/D8OmYCYozza/+lcK7Fs/6TAWe8Tb +xNRkoDD75f0dcZLdKY9BWN4ArTr9PXwaqLEX8E40eFgl1oUh63kd0Nyrz2I8sMeX +i9bQn9P+PN7F4/w6g3CEIR0JwqH8uyghZVNgepBtljhb//HXeltt08lwSUq6HTrQ +UNoyIBnkiz/r1RYmNzz7dZ6wB3C4FGB33PYPXFIKvF1tjVEK2sUYyJtt3LCDs3+j +TnhMmCWr8n4uIF6CFabW2I+s5c0yhsj55NqJ4js+k8UTav/H9xj8Z7XvGCxUq0DT +bE3txci3OE9kxJRMT6DNrqXGJyV1J23G2pyOsAWZ1SgRxSHUuPzHlqtKZFlhaxP8 +S8ySpg+kUb8OWJDZgoM5pl+z+m6Ss80zDoWo8SnTq1mt1tve1CuBAgMBAAGjQjBA +MA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFLgHkXlcBvRG/XtZylomkadFK/hT +MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQwFAAOCAgEAIZtqBSBdGBanEqT3 +Rz/NyjuujsCCztxIJXgXbODgcMTWltnZ9r96nBO7U5WS/8+S4PPFJzVXqDuiGev4 +iqME3mmL5Dw8veWv0BIb5Ylrc5tvJQJLkIKvQMKtuppgJFqBTQUYo+IzeXoLH5Pt +7DlK9RME7I10nYEKqG/odv6LTytpEoYKNDbdgptvT+Bz3Ul/KD7JO6NXBNiT2Twp +2xIQaOHEibgGIOcberyxk2GaGUARtWqFVwHxtlotJnMnlvm5P1vQiJ3koP26TpUJ +g3933FEFlJ0gcXax7PqJtZwuhfG5WyRasQmr2soaB82G39tp27RIGAAtvKLEiUUj +pQ7hRGU+isFqMB3iYPg6qocJQrmBktwliJiJ8Xw18WLK7nn4GS/+X/jbh87qqA8M +pugLoDzga5SYnH+tBuYc6kIQX+ImFTw3OffXvO645e8D7r0i+yiGNFjEWn9hongP +XvPKnbwbPKfILfanIhHKA9jnZwqKDss1jjQ52MjqjZ9k4DewbNfFj8GQYSbbJIwe +SsCI3zWQzj8C9GRh3sfIB5XeMhg6j6JCQCTl1jNdfK7vsU1P1FeQNWrcrgSXSYk0 +ly4wBOeY99sLAZDBHwo/+ML+TvrbmnNzFrwFuHnYWa8G5z9nODmxfKuU4CkUpijy +323imttUQ/hHWKNddBWcwauwxzQ= +-----END CERTIFICATE----- + +# Issuer: CN=D-TRUST EV Root CA 2 2023 O=D-Trust GmbH +# Subject: CN=D-TRUST EV Root CA 2 2023 O=D-Trust GmbH +# Label: "D-TRUST EV Root CA 2 2023" +# Serial: 139766439402180512324132425437959641711 +# MD5 Fingerprint: 96:b4:78:09:f0:09:cb:77:eb:bb:1b:4d:6f:36:bc:b6 +# SHA1 Fingerprint: a5:5b:d8:47:6c:8f:19:f7:4c:f4:6d:6b:b6:c2:79:82:22:df:54:8b +# SHA256 Fingerprint: 8e:82:21:b2:e7:d4:00:78:36:a1:67:2f:0d:cc:29:9c:33:bc:07:d3:16:f1:32:fa:1a:20:6d:58:71:50:f1:ce +-----BEGIN CERTIFICATE----- +MIIFqTCCA5GgAwIBAgIQaSYJfoBLTKCnjHhiU19abzANBgkqhkiG9w0BAQ0FADBI +MQswCQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlE +LVRSVVNUIEVWIFJvb3QgQ0EgMiAyMDIzMB4XDTIzMDUwOTA5MTAzM1oXDTM4MDUw +OTA5MTAzMlowSDELMAkGA1UEBhMCREUxFTATBgNVBAoTDEQtVHJ1c3QgR21iSDEi +MCAGA1UEAxMZRC1UUlVTVCBFViBSb290IENBIDIgMjAyMzCCAiIwDQYJKoZIhvcN +AQEBBQADggIPADCCAgoCggIBANiOo4mAC7JXUtypU0w3uX9jFxPvp1sjW2l1sJkK +F8GLxNuo4MwxusLyzV3pt/gdr2rElYfXR8mV2IIEUD2BCP/kPbOx1sWy/YgJ25yE +7CUXFId/MHibaljJtnMoPDT3mfd/06b4HEV8rSyMlD/YZxBTfiLNTiVR8CUkNRFe +EMbsh2aJgWi6zCudR3Mfvc2RpHJqnKIbGKBv7FD0fUDCqDDPvXPIEysQEx6Lmqg6 +lHPTGGkKSv/BAQP/eX+1SH977ugpbzZMlWGG2Pmic4ruri+W7mjNPU0oQvlFKzIb +RlUWaqZLKfm7lVa/Rh3sHZMdwGWyH6FDrlaeoLGPaxK3YG14C8qKXO0elg6DpkiV +jTujIcSuWMYAsoS0I6SWhjW42J7YrDRJmGOVxcttSEfi8i4YHtAxq9107PncjLgc +jmgjutDzUNzPZY9zOjLHfP7KgiJPvo5iR2blzYfi6NUPGJ/lBHJLRjwQ8kTCZFZx +TnXonMkmdMV9WdEKWw9t/p51HBjGGjp82A0EzM23RWV6sY+4roRIPrN6TagD4uJ+ +ARZZaBhDM7DS3LAaQzXupdqpRlyuhoFBAUp0JuyfBr/CBTdkdXgpaP3F9ev+R/nk +hbDhezGdpn9yo7nELC7MmVcOIQxFAZRl62UJxmMiCzNJkkg8/M3OsD6Onov4/knF +NXJHAgMBAAGjgY4wgYswDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUqvyREBuH +kV8Wub9PS5FeAByxMoAwDgYDVR0PAQH/BAQDAgEGMEkGA1UdHwRCMEAwPqA8oDqG +OGh0dHA6Ly9jcmwuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3RfZXZfcm9vdF9jYV8y +XzIwMjMuY3JsMA0GCSqGSIb3DQEBDQUAA4ICAQCTy6UfmRHsmg1fLBWTxj++EI14 +QvBukEdHjqOSMo1wj/Zbjb6JzkcBahsgIIlbyIIQbODnmaprxiqgYzWRaoUlrRc4 +pZt+UPJ26oUFKidBK7GB0aL2QHWpDsvxVUjY7NHss+jOFKE17MJeNRqrphYBBo7q +3C+jisosketSjl8MmxfPy3MHGcRqwnNU73xDUmPBEcrCRbH0O1P1aa4846XerOhU +t7KR/aypH/KH5BfGSah82ApB9PI+53c0BFLd6IHyTS9URZ0V4U/M5d40VxDJI3IX +cI1QcB9WbMy5/zpaT2N6w25lBx2Eof+pDGOJbbJAiDnXH3dotfyc1dZnaVuodNv8 +ifYbMvekJKZ2t0dT741Jj6m2g1qllpBFYfXeA08mD6iL8AOWsKwV0HFaanuU5nCT +2vFp4LJiTZ6P/4mdm13NRemUAiKN4DV/6PEEeXFsVIP4M7kFMhtYVRFP0OUnR3Hs +7dpn1mKmS00PaaLJvOwiS5THaJQXfuKOKD62xur1NGyfN4gHONuGcfrNlUhDbqNP +gofXNJhuS5N5YHVpD/Aa1VP6IQzCP+k/HxiMkl14p3ZnGbuy6n/pcAlWVqOwDAst +Nl7F6cTVg8uGF5csbBNvh1qvSaYd2804BC5f4ko1Di1L+KIkBI3Y4WNeApI02phh +XBxvWHZks/wCuPWdCg== +-----END CERTIFICATE----- + +# Issuer: CN=SwissSign RSA TLS Root CA 2022 - 1 O=SwissSign AG +# Subject: CN=SwissSign RSA TLS Root CA 2022 - 1 O=SwissSign AG +# Label: "SwissSign RSA TLS Root CA 2022 - 1" +# Serial: 388078645722908516278762308316089881486363258315 +# MD5 Fingerprint: 16:2e:e4:19:76:81:85:ba:8e:91:58:f1:15:ef:72:39 +# SHA1 Fingerprint: 81:34:0a:be:4c:cd:ce:cc:e7:7d:cc:8a:d4:57:e2:45:a0:77:5d:ce +# SHA256 Fingerprint: 19:31:44:f4:31:e0:fd:db:74:07:17:d4:de:92:6a:57:11:33:88:4b:43:60:d3:0e:27:29:13:cb:e6:60:ce:41 +-----BEGIN CERTIFICATE----- +MIIFkzCCA3ugAwIBAgIUQ/oMX04bgBhE79G0TzUfRPSA7cswDQYJKoZIhvcNAQEL +BQAwUTELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzErMCkGA1UE +AxMiU3dpc3NTaWduIFJTQSBUTFMgUm9vdCBDQSAyMDIyIC0gMTAeFw0yMjA2MDgx +MTA4MjJaFw00NzA2MDgxMTA4MjJaMFExCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxT +d2lzc1NpZ24gQUcxKzApBgNVBAMTIlN3aXNzU2lnbiBSU0EgVExTIFJvb3QgQ0Eg +MjAyMiAtIDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDLKmjiC8NX +vDVjvHClO/OMPE5Xlm7DTjak9gLKHqquuN6orx122ro10JFwB9+zBvKK8i5VUXu7 +LCTLf5ImgKO0lPaCoaTo+nUdWfMHamFk4saMla+ju45vVs9xzF6BYQ1t8qsCLqSX +5XH8irCRIFucdFJtrhUnWXjyCcplDn/L9Ovn3KlMd/YrFgSVrpxxpT8q2kFC5zyE +EPThPYxr4iuRR1VPuFa+Rd4iUU1OKNlfGUEGjw5NBuBwQCMBauTLE5tzrE0USJIt +/m2n+IdreXXhvhCxqohAWVTXz8TQm0SzOGlkjIHRI36qOTw7D59Ke4LKa2/KIj4x +0LDQKhySio/YGZxH5D4MucLNvkEM+KRHBdvBFzA4OmnczcNpI/2aDwLOEGrOyvi5 +KaM2iYauC8BPY7kGWUleDsFpswrzd34unYyzJ5jSmY0lpx+Gs6ZUcDj8fV3oT4MM +0ZPlEuRU2j7yrTrePjxF8CgPBrnh25d7mUWe3f6VWQQvdT/TromZhqwUtKiE+shd +OxtYk8EXlFXIC+OCeYSf8wCENO7cMdWP8vpPlkwGqnj73mSiI80fPsWMvDdUDrta +clXvyFu1cvh43zcgTFeRc5JzrBh3Q4IgaezprClG5QtO+DdziZaKHG29777YtvTK +wP1H8K4LWCDFyB02rpeNUIMmJCn3nTsPBQIDAQABo2MwYTAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBRvjmKLk0Ow4UD2p8P98Q+4 +DxU4pTAdBgNVHQ4EFgQUb45ii5NDsOFA9qfD/fEPuA8VOKUwDQYJKoZIhvcNAQEL +BQADggIBAKwsKUF9+lz1GpUYvyypiqkkVHX1uECry6gkUSsYP2OprphWKwVDIqO3 +10aewCoSPY6WlkDfDDOLazeROpW7OSltwAJsipQLBwJNGD77+3v1dj2b9l4wBlgz +Hqp41eZUBDqyggmNzhYzWUUo8aWjlw5DI/0LIICQ/+Mmz7hkkeUFjxOgdg3XNwwQ +iJb0Pr6VvfHDffCjw3lHC1ySFWPtUnWK50Zpy1FVCypM9fJkT6lc/2cyjlUtMoIc +gC9qkfjLvH4YoiaoLqNTKIftV+Vlek4ASltOU8liNr3CjlvrzG4ngRhZi0Rjn9UM +ZfQpZX+RLOV/fuiJz48gy20HQhFRJjKKLjpHE7iNvUcNCfAWpO2Whi4Z2L6MOuhF +LhG6rlrnub+xzI/goP+4s9GFe3lmozm1O2bYQL7Pt2eLSMkZJVX8vY3PXtpOpvJp +zv1/THfQwUY1mFwjmwJFQ5Ra3bxHrSL+ul4vkSkphnsh3m5kt8sNjzdbowhq6/Td +Ao9QAwKxuDdollDruF/UKIqlIgyKhPBZLtU30WHlQnNYKoH3dtvi4k0NX/a3vgW0 +rk4N3hY9A4GzJl5LuEsAz/+MF7psYC0nhzck5npgL7XTgwSqT0N1osGDsieYK7EO +gLrAhV5Cud+xYJHT6xh+cHiudoO+cVrQkOPKwRYlZ0rwtnu64ZzZ +-----END CERTIFICATE----- + +# Issuer: CN=OISTE Server Root ECC G1 O=OISTE Foundation +# Subject: CN=OISTE Server Root ECC G1 O=OISTE Foundation +# Label: "OISTE Server Root ECC G1" +# Serial: 47819833811561661340092227008453318557 +# MD5 Fingerprint: 42:a7:d2:35:ae:02:92:db:19:76:08:de:2f:05:b4:d4 +# SHA1 Fingerprint: 3b:f6:8b:09:ae:2a:92:7b:ba:e3:8d:3f:11:95:d9:e6:44:0c:45:e2 +# SHA256 Fingerprint: ee:c9:97:c0:c3:0f:21:6f:7e:3b:8b:30:7d:2b:ae:42:41:2d:75:3f:c8:21:9d:af:d1:52:0b:25:72:85:0f:49 +-----BEGIN CERTIFICATE----- +MIICNTCCAbqgAwIBAgIQI/nD1jWvjyhLH/BU6n6XnTAKBggqhkjOPQQDAzBLMQsw +CQYDVQQGEwJDSDEZMBcGA1UECgwQT0lTVEUgRm91bmRhdGlvbjEhMB8GA1UEAwwY +T0lTVEUgU2VydmVyIFJvb3QgRUNDIEcxMB4XDTIzMDUzMTE0NDIyOFoXDTQ4MDUy +NDE0NDIyN1owSzELMAkGA1UEBhMCQ0gxGTAXBgNVBAoMEE9JU1RFIEZvdW5kYXRp +b24xITAfBgNVBAMMGE9JU1RFIFNlcnZlciBSb290IEVDQyBHMTB2MBAGByqGSM49 +AgEGBSuBBAAiA2IABBcv+hK8rBjzCvRE1nZCnrPoH7d5qVi2+GXROiFPqOujvqQy +cvO2Ackr/XeFblPdreqqLiWStukhEaivtUwL85Zgmjvn6hp4LrQ95SjeHIC6XG4N +2xml4z+cKrhAS93mT6NjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBQ3 +TYhlz/w9itWj8UnATgwQb0K0nDAdBgNVHQ4EFgQUN02IZc/8PYrVo/FJwE4MEG9C +tJwwDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2kAMGYCMQCpKjAd0MKfkFFR +QD6VVCHNFmb3U2wIFjnQEnx/Yxvf4zgAOdktUyBFCxxgZzFDJe0CMQCSia7pXGKD +YmH5LVerVrkR3SW+ak5KGoJr3M/TvEqzPNcum9v4KGm8ay3sMaE641c= +-----END CERTIFICATE----- + +# Issuer: CN=OISTE Server Root RSA G1 O=OISTE Foundation +# Subject: CN=OISTE Server Root RSA G1 O=OISTE Foundation +# Label: " OISTE Server Root RSA G1" +# Serial: 113845518112613905024960613408179309848 +# MD5 Fingerprint: 23:a7:9e:d4:70:b8:b9:14:57:41:8a:7e:44:59:e2:68 +# SHA1 Fingerprint: f7:00:34:25:94:88:68:31:e4:34:87:3f:70:fe:86:b3:86:9f:f0:6e +# SHA256 Fingerprint: 9a:e3:62:32:a5:18:9f:fd:db:35:3d:fd:26:52:0c:01:53:95:d2:27:77:da:c5:9d:b5:7b:98:c0:89:a6:51:e6 +-----BEGIN CERTIFICATE----- +MIIFgzCCA2ugAwIBAgIQVaXZZ5Qoxu0M+ifdWwFNGDANBgkqhkiG9w0BAQwFADBL +MQswCQYDVQQGEwJDSDEZMBcGA1UECgwQT0lTVEUgRm91bmRhdGlvbjEhMB8GA1UE +AwwYT0lTVEUgU2VydmVyIFJvb3QgUlNBIEcxMB4XDTIzMDUzMTE0MzcxNloXDTQ4 +MDUyNDE0MzcxNVowSzELMAkGA1UEBhMCQ0gxGTAXBgNVBAoMEE9JU1RFIEZvdW5k +YXRpb24xITAfBgNVBAMMGE9JU1RFIFNlcnZlciBSb290IFJTQSBHMTCCAiIwDQYJ +KoZIhvcNAQEBBQADggIPADCCAgoCggIBAKqu9KuCz/vlNwvn1ZatkOhLKdxVYOPM +vLO8LZK55KN68YG0nnJyQ98/qwsmtO57Gmn7KNByXEptaZnwYx4M0rH/1ow00O7b +rEi56rAUjtgHqSSY3ekJvqgiG1k50SeH3BzN+Puz6+mTeO0Pzjd8JnduodgsIUzk +ik/HEzxux9UTl7Ko2yRpg1bTacuCErudG/L4NPKYKyqOBGf244ehHa1uzjZ0Dl4z +O8vbUZeUapU8zhhabkvG/AePLhq5SvdkNCncpo1Q4Y2LS+VIG24ugBA/5J8bZT8R +tOpXaZ+0AOuFJJkk9SGdl6r7NH8CaxWQrbueWhl/pIzY+m0o/DjH40ytas7ZTpOS +jswMZ78LS5bOZmdTaMsXEY5Z96ycG7mOaES3GK/m5Q9l3JUJsJMStR8+lKXHiHUh +sd4JJCpM4rzsTGdHwimIuQq6+cF0zowYJmXa92/GjHtoXAvuY8BeS/FOzJ8vD+Ho +mnqT8eDI278n5mUpezbgMxVz8p1rhAhoKzYHKyfMeNhqhw5HdPSqoBNdZH702xSu ++zrkL8Fl47l6QGzwBrd7KJvX4V84c5Ss2XCTLdyEr0YconosP4EmQufU2MVshGYR +i3drVByjtdgQ8K4p92cIiBdcuJd5z+orKu5YM+Vt6SmqZQENghPsJQtdLEByFSnT +kCz3GkPVavBpAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU +8snBDw1jALvsRQ5KH7WxszbNDo0wHQYDVR0OBBYEFPLJwQ8NYwC77EUOSh+1sbM2 +zQ6NMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQwFAAOCAgEANGd5sjrG5T33 +I3K5Ce+SrScfoE4KsvXaFwyihdJ+klH9FWXXXGtkFu6KRcoMQzZENdl//nk6HOjG +5D1rd9QhEOP28yBOqb6J8xycqd+8MDoX0TJD0KqKchxRKEzdNsjkLWd9kYccnbz8 +qyiWXmFcuCIzGEgWUOrKL+mlSdx/PKQZvDatkuK59EvV6wit53j+F8Bdh3foZ3dP +AGav9LEDOr4SfEE15fSmG0eLy3n31r8Xbk5l8PjaV8GUgeV6Vg27Rn9vkf195hfk +gSe7BYhW3SCl95gtkRlpMV+bMPKZrXJAlszYd2abtNUOshD+FKrDgHGdPY3ofRRs +YWSGRqbXVMW215AWRqWFyp464+YTFrYVI8ypKVL9AMb2kI5Wj4kI3Zaq5tNqqYY1 +9tVFeEJKRvwDyF7YZvZFZSS0vod7VSCd9521Kvy5YhnLbDuv0204bKt7ph6N/Ome +/msVuduCmsuY33OhkKCgxeDoAaijFJzIwZqsFVAzje18KotzlUBDJvyBpCpfOZC3 +J8tRd/iWkx7P8nd9H0aTolkelUTFLXVksNb54Dxp6gS1HAviRkRNQzuXSXERvSS2 +wq1yVAb+axj5d9spLFKebXd7Yv0PTY6YMjAwcRLWJTXjn/hvnLXrahut6hDTlhZy +BiElxky8j3C7DOReIoMt0r7+hVu05L0= +-----END CERTIFICATE----- diff --git a/backend/venv/Lib/site-packages/certifi/core.py b/backend/venv/Lib/site-packages/certifi/core.py new file mode 100644 index 0000000..1c9661c --- /dev/null +++ b/backend/venv/Lib/site-packages/certifi/core.py @@ -0,0 +1,83 @@ +""" +certifi.py +~~~~~~~~~~ + +This module returns the installation location of cacert.pem or its contents. +""" +import sys +import atexit + +def exit_cacert_ctx() -> None: + _CACERT_CTX.__exit__(None, None, None) # type: ignore[union-attr] + + +if sys.version_info >= (3, 11): + + from importlib.resources import as_file, files + + _CACERT_CTX = None + _CACERT_PATH = None + + def where() -> str: + # This is slightly terrible, but we want to delay extracting the file + # in cases where we're inside of a zipimport situation until someone + # actually calls where(), but we don't want to re-extract the file + # on every call of where(), so we'll do it once then store it in a + # global variable. + global _CACERT_CTX + global _CACERT_PATH + if _CACERT_PATH is None: + # This is slightly janky, the importlib.resources API wants you to + # manage the cleanup of this file, so it doesn't actually return a + # path, it returns a context manager that will give you the path + # when you enter it and will do any cleanup when you leave it. In + # the common case of not needing a temporary file, it will just + # return the file system location and the __exit__() is a no-op. + # + # We also have to hold onto the actual context manager, because + # it will do the cleanup whenever it gets garbage collected, so + # we will also store that at the global level as well. + _CACERT_CTX = as_file(files("certifi").joinpath("cacert.pem")) + _CACERT_PATH = str(_CACERT_CTX.__enter__()) + atexit.register(exit_cacert_ctx) + + return _CACERT_PATH + + def contents() -> str: + return files("certifi").joinpath("cacert.pem").read_text(encoding="ascii") + +else: + + from importlib.resources import path as get_path, read_text + + _CACERT_CTX = None + _CACERT_PATH = None + + def where() -> str: + # This is slightly terrible, but we want to delay extracting the + # file in cases where we're inside of a zipimport situation until + # someone actually calls where(), but we don't want to re-extract + # the file on every call of where(), so we'll do it once then store + # it in a global variable. + global _CACERT_CTX + global _CACERT_PATH + if _CACERT_PATH is None: + # This is slightly janky, the importlib.resources API wants you + # to manage the cleanup of this file, so it doesn't actually + # return a path, it returns a context manager that will give + # you the path when you enter it and will do any cleanup when + # you leave it. In the common case of not needing a temporary + # file, it will just return the file system location and the + # __exit__() is a no-op. + # + # We also have to hold onto the actual context manager, because + # it will do the cleanup whenever it gets garbage collected, so + # we will also store that at the global level as well. + _CACERT_CTX = get_path("certifi", "cacert.pem") + _CACERT_PATH = str(_CACERT_CTX.__enter__()) + atexit.register(exit_cacert_ctx) + + return _CACERT_PATH + + def contents() -> str: + return read_text("certifi", "cacert.pem", encoding="ascii") diff --git a/backend/venv/Lib/site-packages/certifi/py.typed b/backend/venv/Lib/site-packages/certifi/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/backend/venv/Lib/site-packages/charset_normalizer-3.4.3.dist-info/INSTALLER b/backend/venv/Lib/site-packages/charset_normalizer-3.4.3.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/backend/venv/Lib/site-packages/charset_normalizer-3.4.3.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/backend/venv/Lib/site-packages/charset_normalizer-3.4.3.dist-info/METADATA b/backend/venv/Lib/site-packages/charset_normalizer-3.4.3.dist-info/METADATA new file mode 100644 index 0000000..65b5577 --- /dev/null +++ b/backend/venv/Lib/site-packages/charset_normalizer-3.4.3.dist-info/METADATA @@ -0,0 +1,750 @@ +Metadata-Version: 2.4 +Name: charset-normalizer +Version: 3.4.3 +Summary: The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet. +Author-email: "Ahmed R. TAHRI" +Maintainer-email: "Ahmed R. TAHRI" +License: MIT +Project-URL: Changelog, https://github.com/jawah/charset_normalizer/blob/master/CHANGELOG.md +Project-URL: Documentation, https://charset-normalizer.readthedocs.io/ +Project-URL: Code, https://github.com/jawah/charset_normalizer +Project-URL: Issue tracker, https://github.com/jawah/charset_normalizer/issues +Keywords: encoding,charset,charset-detector,detector,normalization,unicode,chardet,detect +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Classifier: Programming Language :: Python :: 3.13 +Classifier: Programming Language :: Python :: 3.14 +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Topic :: Text Processing :: Linguistic +Classifier: Topic :: Utilities +Classifier: Typing :: Typed +Requires-Python: >=3.7 +Description-Content-Type: text/markdown +License-File: LICENSE +Provides-Extra: unicode-backport +Dynamic: license-file + +

Charset Detection, for Everyone 👋

+ +

+ The Real First Universal Charset Detector
+ + + + + Download Count Total + + + + +

+

+ Featured Packages
+ + Static Badge + + + Static Badge + +

+

+ In other language (unofficial port - by the community)
+ + Static Badge + +

+ +> A library that helps you read text from an unknown charset encoding.
Motivated by `chardet`, +> I'm trying to resolve the issue by taking a new approach. +> All IANA character set names for which the Python core library provides codecs are supported. + +

+ >>>>> 👉 Try Me Online Now, Then Adopt Me 👈 <<<<< +

+ +This project offers you an alternative to **Universal Charset Encoding Detector**, also known as **Chardet**. + +| Feature | [Chardet](https://github.com/chardet/chardet) | Charset Normalizer | [cChardet](https://github.com/PyYoshi/cChardet) | +|--------------------------------------------------|:---------------------------------------------:|:--------------------------------------------------------------------------------------------------:|:-----------------------------------------------:| +| `Fast` | ❌ | ✅ | ✅ | +| `Universal**` | ❌ | ✅ | ❌ | +| `Reliable` **without** distinguishable standards | ❌ | ✅ | ✅ | +| `Reliable` **with** distinguishable standards | ✅ | ✅ | ✅ | +| `License` | LGPL-2.1
_restrictive_ | MIT | MPL-1.1
_restrictive_ | +| `Native Python` | ✅ | ✅ | ❌ | +| `Detect spoken language` | ❌ | ✅ | N/A | +| `UnicodeDecodeError Safety` | ❌ | ✅ | ❌ | +| `Whl Size (min)` | 193.6 kB | 42 kB | ~200 kB | +| `Supported Encoding` | 33 | 🎉 [99](https://charset-normalizer.readthedocs.io/en/latest/user/support.html#supported-encodings) | 40 | + +

+Reading Normalized TextCat Reading Text +

+ +*\*\* : They are clearly using specific code for a specific encoding even if covering most of used one*
+ +## ⚡ Performance + +This package offer better performance than its counterpart Chardet. Here are some numbers. + +| Package | Accuracy | Mean per file (ms) | File per sec (est) | +|-----------------------------------------------|:--------:|:------------------:|:------------------:| +| [chardet](https://github.com/chardet/chardet) | 86 % | 63 ms | 16 file/sec | +| charset-normalizer | **98 %** | **10 ms** | 100 file/sec | + +| Package | 99th percentile | 95th percentile | 50th percentile | +|-----------------------------------------------|:---------------:|:---------------:|:---------------:| +| [chardet](https://github.com/chardet/chardet) | 265 ms | 71 ms | 7 ms | +| charset-normalizer | 100 ms | 50 ms | 5 ms | + +_updated as of december 2024 using CPython 3.12_ + +Chardet's performance on larger file (1MB+) are very poor. Expect huge difference on large payload. + +> Stats are generated using 400+ files using default parameters. More details on used files, see GHA workflows. +> And yes, these results might change at any time. The dataset can be updated to include more files. +> The actual delays heavily depends on your CPU capabilities. The factors should remain the same. +> Keep in mind that the stats are generous and that Chardet accuracy vs our is measured using Chardet initial capability +> (e.g. Supported Encoding) Challenge-them if you want. + +## ✨ Installation + +Using pip: + +```sh +pip install charset-normalizer -U +``` + +## 🚀 Basic Usage + +### CLI +This package comes with a CLI. + +``` +usage: normalizer [-h] [-v] [-a] [-n] [-m] [-r] [-f] [-t THRESHOLD] + file [file ...] + +The Real First Universal Charset Detector. Discover originating encoding used +on text file. Normalize text to unicode. + +positional arguments: + files File(s) to be analysed + +optional arguments: + -h, --help show this help message and exit + -v, --verbose Display complementary information about file if any. + Stdout will contain logs about the detection process. + -a, --with-alternative + Output complementary possibilities if any. Top-level + JSON WILL be a list. + -n, --normalize Permit to normalize input file. If not set, program + does not write anything. + -m, --minimal Only output the charset detected to STDOUT. Disabling + JSON output. + -r, --replace Replace file when trying to normalize it instead of + creating a new one. + -f, --force Replace file without asking if you are sure, use this + flag with caution. + -t THRESHOLD, --threshold THRESHOLD + Define a custom maximum amount of chaos allowed in + decoded content. 0. <= chaos <= 1. + --version Show version information and exit. +``` + +```bash +normalizer ./data/sample.1.fr.srt +``` + +or + +```bash +python -m charset_normalizer ./data/sample.1.fr.srt +``` + +🎉 Since version 1.4.0 the CLI produce easily usable stdout result in JSON format. + +```json +{ + "path": "/home/default/projects/charset_normalizer/data/sample.1.fr.srt", + "encoding": "cp1252", + "encoding_aliases": [ + "1252", + "windows_1252" + ], + "alternative_encodings": [ + "cp1254", + "cp1256", + "cp1258", + "iso8859_14", + "iso8859_15", + "iso8859_16", + "iso8859_3", + "iso8859_9", + "latin_1", + "mbcs" + ], + "language": "French", + "alphabets": [ + "Basic Latin", + "Latin-1 Supplement" + ], + "has_sig_or_bom": false, + "chaos": 0.149, + "coherence": 97.152, + "unicode_path": null, + "is_preferred": true +} +``` + +### Python +*Just print out normalized text* +```python +from charset_normalizer import from_path + +results = from_path('./my_subtitle.srt') + +print(str(results.best())) +``` + +*Upgrade your code without effort* +```python +from charset_normalizer import detect +``` + +The above code will behave the same as **chardet**. We ensure that we offer the best (reasonable) BC result possible. + +See the docs for advanced usage : [readthedocs.io](https://charset-normalizer.readthedocs.io/en/latest/) + +## 😇 Why + +When I started using Chardet, I noticed that it was not suited to my expectations, and I wanted to propose a +reliable alternative using a completely different method. Also! I never back down on a good challenge! + +I **don't care** about the **originating charset** encoding, because **two different tables** can +produce **two identical rendered string.** +What I want is to get readable text, the best I can. + +In a way, **I'm brute forcing text decoding.** How cool is that ? 😎 + +Don't confuse package **ftfy** with charset-normalizer or chardet. ftfy goal is to repair Unicode string whereas charset-normalizer to convert raw file in unknown encoding to unicode. + +## 🍰 How + + - Discard all charset encoding table that could not fit the binary content. + - Measure noise, or the mess once opened (by chunks) with a corresponding charset encoding. + - Extract matches with the lowest mess detected. + - Additionally, we measure coherence / probe for a language. + +**Wait a minute**, what is noise/mess and coherence according to **YOU ?** + +*Noise :* I opened hundred of text files, **written by humans**, with the wrong encoding table. **I observed**, then +**I established** some ground rules about **what is obvious** when **it seems like** a mess (aka. defining noise in rendered text). + I know that my interpretation of what is noise is probably incomplete, feel free to contribute in order to + improve or rewrite it. + +*Coherence :* For each language there is on earth, we have computed ranked letter appearance occurrences (the best we can). So I thought +that intel is worth something here. So I use those records against decoded text to check if I can detect intelligent design. + +## ⚡ Known limitations + + - Language detection is unreliable when text contains two or more languages sharing identical letters. (eg. HTML (english tags) + Turkish content (Sharing Latin characters)) + - Every charset detector heavily depends on sufficient content. In common cases, do not bother run detection on very tiny content. + +## ⚠️ About Python EOLs + +**If you are running:** + +- Python >=2.7,<3.5: Unsupported +- Python 3.5: charset-normalizer < 2.1 +- Python 3.6: charset-normalizer < 3.1 +- Python 3.7: charset-normalizer < 4.0 + +Upgrade your Python interpreter as soon as possible. + +## 👤 Contributing + +Contributions, issues and feature requests are very much welcome.
+Feel free to check [issues page](https://github.com/ousret/charset_normalizer/issues) if you want to contribute. + +## 📝 License + +Copyright © [Ahmed TAHRI @Ousret](https://github.com/Ousret).
+This project is [MIT](https://github.com/Ousret/charset_normalizer/blob/master/LICENSE) licensed. + +Characters frequencies used in this project © 2012 [Denny Vrandečić](http://simia.net/letters/) + +## 💼 For Enterprise + +Professional support for charset-normalizer is available as part of the [Tidelift +Subscription][1]. Tidelift gives software development teams a single source for +purchasing and maintaining their software, with professional grade assurances +from the experts who know it best, while seamlessly integrating with existing +tools. + +[1]: https://tidelift.com/subscription/pkg/pypi-charset-normalizer?utm_source=pypi-charset-normalizer&utm_medium=readme + +[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/7297/badge)](https://www.bestpractices.dev/projects/7297) + +# Changelog +All notable changes to charset-normalizer will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). + +## [3.4.3](https://github.com/Ousret/charset_normalizer/compare/3.4.2...3.4.3) (2025-08-09) + +### Changed +- mypy(c) is no longer a required dependency at build time if `CHARSET_NORMALIZER_USE_MYPYC` isn't set to `1`. (#595) (#583) +- automatically lower confidence on small bytes samples that are not Unicode in `detect` output legacy function. (#391) + +### Added +- Custom build backend to overcome inability to mark mypy as an optional dependency in the build phase. +- Support for Python 3.14 + +### Fixed +- sdist archive contained useless directories. +- automatically fallback on valid UTF-16 or UTF-32 even if the md says it's noisy. (#633) + +### Misc +- SBOM are automatically published to the relevant GitHub release to comply with regulatory changes. + Each published wheel comes with its SBOM. We choose CycloneDX as the format. +- Prebuilt optimized wheel are no longer distributed by default for CPython 3.7 due to a change in cibuildwheel. + +## [3.4.2](https://github.com/Ousret/charset_normalizer/compare/3.4.1...3.4.2) (2025-05-02) + +### Fixed +- Addressed the DeprecationWarning in our CLI regarding `argparse.FileType` by backporting the target class into the package. (#591) +- Improved the overall reliability of the detector with CJK Ideographs. (#605) (#587) + +### Changed +- Optional mypyc compilation upgraded to version 1.15 for Python >= 3.8 + +## [3.4.1](https://github.com/Ousret/charset_normalizer/compare/3.4.0...3.4.1) (2024-12-24) + +### Changed +- Project metadata are now stored using `pyproject.toml` instead of `setup.cfg` using setuptools as the build backend. +- Enforce annotation delayed loading for a simpler and consistent types in the project. +- Optional mypyc compilation upgraded to version 1.14 for Python >= 3.8 + +### Added +- pre-commit configuration. +- noxfile. + +### Removed +- `build-requirements.txt` as per using `pyproject.toml` native build configuration. +- `bin/integration.py` and `bin/serve.py` in favor of downstream integration test (see noxfile). +- `setup.cfg` in favor of `pyproject.toml` metadata configuration. +- Unused `utils.range_scan` function. + +### Fixed +- Converting content to Unicode bytes may insert `utf_8` instead of preferred `utf-8`. (#572) +- Deprecation warning "'count' is passed as positional argument" when converting to Unicode bytes on Python 3.13+ + +## [3.4.0](https://github.com/Ousret/charset_normalizer/compare/3.3.2...3.4.0) (2024-10-08) + +### Added +- Argument `--no-preemptive` in the CLI to prevent the detector to search for hints. +- Support for Python 3.13 (#512) + +### Fixed +- Relax the TypeError exception thrown when trying to compare a CharsetMatch with anything else than a CharsetMatch. +- Improved the general reliability of the detector based on user feedbacks. (#520) (#509) (#498) (#407) (#537) +- Declared charset in content (preemptive detection) not changed when converting to utf-8 bytes. (#381) + +## [3.3.2](https://github.com/Ousret/charset_normalizer/compare/3.3.1...3.3.2) (2023-10-31) + +### Fixed +- Unintentional memory usage regression when using large payload that match several encoding (#376) +- Regression on some detection case showcased in the documentation (#371) + +### Added +- Noise (md) probe that identify malformed arabic representation due to the presence of letters in isolated form (credit to my wife) + +## [3.3.1](https://github.com/Ousret/charset_normalizer/compare/3.3.0...3.3.1) (2023-10-22) + +### Changed +- Optional mypyc compilation upgraded to version 1.6.1 for Python >= 3.8 +- Improved the general detection reliability based on reports from the community + +## [3.3.0](https://github.com/Ousret/charset_normalizer/compare/3.2.0...3.3.0) (2023-09-30) + +### Added +- Allow to execute the CLI (e.g. normalizer) through `python -m charset_normalizer.cli` or `python -m charset_normalizer` +- Support for 9 forgotten encoding that are supported by Python but unlisted in `encoding.aliases` as they have no alias (#323) + +### Removed +- (internal) Redundant utils.is_ascii function and unused function is_private_use_only +- (internal) charset_normalizer.assets is moved inside charset_normalizer.constant + +### Changed +- (internal) Unicode code blocks in constants are updated using the latest v15.0.0 definition to improve detection +- Optional mypyc compilation upgraded to version 1.5.1 for Python >= 3.8 + +### Fixed +- Unable to properly sort CharsetMatch when both chaos/noise and coherence were close due to an unreachable condition in \_\_lt\_\_ (#350) + +## [3.2.0](https://github.com/Ousret/charset_normalizer/compare/3.1.0...3.2.0) (2023-06-07) + +### Changed +- Typehint for function `from_path` no longer enforce `PathLike` as its first argument +- Minor improvement over the global detection reliability + +### Added +- Introduce function `is_binary` that relies on main capabilities, and optimized to detect binaries +- Propagate `enable_fallback` argument throughout `from_bytes`, `from_path`, and `from_fp` that allow a deeper control over the detection (default True) +- Explicit support for Python 3.12 + +### Fixed +- Edge case detection failure where a file would contain 'very-long' camel cased word (Issue #289) + +## [3.1.0](https://github.com/Ousret/charset_normalizer/compare/3.0.1...3.1.0) (2023-03-06) + +### Added +- Argument `should_rename_legacy` for legacy function `detect` and disregard any new arguments without errors (PR #262) + +### Removed +- Support for Python 3.6 (PR #260) + +### Changed +- Optional speedup provided by mypy/c 1.0.1 + +## [3.0.1](https://github.com/Ousret/charset_normalizer/compare/3.0.0...3.0.1) (2022-11-18) + +### Fixed +- Multi-bytes cutter/chunk generator did not always cut correctly (PR #233) + +### Changed +- Speedup provided by mypy/c 0.990 on Python >= 3.7 + +## [3.0.0](https://github.com/Ousret/charset_normalizer/compare/2.1.1...3.0.0) (2022-10-20) + +### Added +- Extend the capability of explain=True when cp_isolation contains at most two entries (min one), will log in details of the Mess-detector results +- Support for alternative language frequency set in charset_normalizer.assets.FREQUENCIES +- Add parameter `language_threshold` in `from_bytes`, `from_path` and `from_fp` to adjust the minimum expected coherence ratio +- `normalizer --version` now specify if current version provide extra speedup (meaning mypyc compilation whl) + +### Changed +- Build with static metadata using 'build' frontend +- Make the language detection stricter +- Optional: Module `md.py` can be compiled using Mypyc to provide an extra speedup up to 4x faster than v2.1 + +### Fixed +- CLI with opt --normalize fail when using full path for files +- TooManyAccentuatedPlugin induce false positive on the mess detection when too few alpha character have been fed to it +- Sphinx warnings when generating the documentation + +### Removed +- Coherence detector no longer return 'Simple English' instead return 'English' +- Coherence detector no longer return 'Classical Chinese' instead return 'Chinese' +- Breaking: Method `first()` and `best()` from CharsetMatch +- UTF-7 will no longer appear as "detected" without a recognized SIG/mark (is unreliable/conflict with ASCII) +- Breaking: Class aliases CharsetDetector, CharsetDoctor, CharsetNormalizerMatch and CharsetNormalizerMatches +- Breaking: Top-level function `normalize` +- Breaking: Properties `chaos_secondary_pass`, `coherence_non_latin` and `w_counter` from CharsetMatch +- Support for the backport `unicodedata2` + +## [3.0.0rc1](https://github.com/Ousret/charset_normalizer/compare/3.0.0b2...3.0.0rc1) (2022-10-18) + +### Added +- Extend the capability of explain=True when cp_isolation contains at most two entries (min one), will log in details of the Mess-detector results +- Support for alternative language frequency set in charset_normalizer.assets.FREQUENCIES +- Add parameter `language_threshold` in `from_bytes`, `from_path` and `from_fp` to adjust the minimum expected coherence ratio + +### Changed +- Build with static metadata using 'build' frontend +- Make the language detection stricter + +### Fixed +- CLI with opt --normalize fail when using full path for files +- TooManyAccentuatedPlugin induce false positive on the mess detection when too few alpha character have been fed to it + +### Removed +- Coherence detector no longer return 'Simple English' instead return 'English' +- Coherence detector no longer return 'Classical Chinese' instead return 'Chinese' + +## [3.0.0b2](https://github.com/Ousret/charset_normalizer/compare/3.0.0b1...3.0.0b2) (2022-08-21) + +### Added +- `normalizer --version` now specify if current version provide extra speedup (meaning mypyc compilation whl) + +### Removed +- Breaking: Method `first()` and `best()` from CharsetMatch +- UTF-7 will no longer appear as "detected" without a recognized SIG/mark (is unreliable/conflict with ASCII) + +### Fixed +- Sphinx warnings when generating the documentation + +## [3.0.0b1](https://github.com/Ousret/charset_normalizer/compare/2.1.0...3.0.0b1) (2022-08-15) + +### Changed +- Optional: Module `md.py` can be compiled using Mypyc to provide an extra speedup up to 4x faster than v2.1 + +### Removed +- Breaking: Class aliases CharsetDetector, CharsetDoctor, CharsetNormalizerMatch and CharsetNormalizerMatches +- Breaking: Top-level function `normalize` +- Breaking: Properties `chaos_secondary_pass`, `coherence_non_latin` and `w_counter` from CharsetMatch +- Support for the backport `unicodedata2` + +## [2.1.1](https://github.com/Ousret/charset_normalizer/compare/2.1.0...2.1.1) (2022-08-19) + +### Deprecated +- Function `normalize` scheduled for removal in 3.0 + +### Changed +- Removed useless call to decode in fn is_unprintable (#206) + +### Fixed +- Third-party library (i18n xgettext) crashing not recognizing utf_8 (PEP 263) with underscore from [@aleksandernovikov](https://github.com/aleksandernovikov) (#204) + +## [2.1.0](https://github.com/Ousret/charset_normalizer/compare/2.0.12...2.1.0) (2022-06-19) + +### Added +- Output the Unicode table version when running the CLI with `--version` (PR #194) + +### Changed +- Re-use decoded buffer for single byte character sets from [@nijel](https://github.com/nijel) (PR #175) +- Fixing some performance bottlenecks from [@deedy5](https://github.com/deedy5) (PR #183) + +### Fixed +- Workaround potential bug in cpython with Zero Width No-Break Space located in Arabic Presentation Forms-B, Unicode 1.1 not acknowledged as space (PR #175) +- CLI default threshold aligned with the API threshold from [@oleksandr-kuzmenko](https://github.com/oleksandr-kuzmenko) (PR #181) + +### Removed +- Support for Python 3.5 (PR #192) + +### Deprecated +- Use of backport unicodedata from `unicodedata2` as Python is quickly catching up, scheduled for removal in 3.0 (PR #194) + +## [2.0.12](https://github.com/Ousret/charset_normalizer/compare/2.0.11...2.0.12) (2022-02-12) + +### Fixed +- ASCII miss-detection on rare cases (PR #170) + +## [2.0.11](https://github.com/Ousret/charset_normalizer/compare/2.0.10...2.0.11) (2022-01-30) + +### Added +- Explicit support for Python 3.11 (PR #164) + +### Changed +- The logging behavior have been completely reviewed, now using only TRACE and DEBUG levels (PR #163 #165) + +## [2.0.10](https://github.com/Ousret/charset_normalizer/compare/2.0.9...2.0.10) (2022-01-04) + +### Fixed +- Fallback match entries might lead to UnicodeDecodeError for large bytes sequence (PR #154) + +### Changed +- Skipping the language-detection (CD) on ASCII (PR #155) + +## [2.0.9](https://github.com/Ousret/charset_normalizer/compare/2.0.8...2.0.9) (2021-12-03) + +### Changed +- Moderating the logging impact (since 2.0.8) for specific environments (PR #147) + +### Fixed +- Wrong logging level applied when setting kwarg `explain` to True (PR #146) + +## [2.0.8](https://github.com/Ousret/charset_normalizer/compare/2.0.7...2.0.8) (2021-11-24) +### Changed +- Improvement over Vietnamese detection (PR #126) +- MD improvement on trailing data and long foreign (non-pure latin) data (PR #124) +- Efficiency improvements in cd/alphabet_languages from [@adbar](https://github.com/adbar) (PR #122) +- call sum() without an intermediary list following PEP 289 recommendations from [@adbar](https://github.com/adbar) (PR #129) +- Code style as refactored by Sourcery-AI (PR #131) +- Minor adjustment on the MD around european words (PR #133) +- Remove and replace SRTs from assets / tests (PR #139) +- Initialize the library logger with a `NullHandler` by default from [@nmaynes](https://github.com/nmaynes) (PR #135) +- Setting kwarg `explain` to True will add provisionally (bounded to function lifespan) a specific stream handler (PR #135) + +### Fixed +- Fix large (misleading) sequence giving UnicodeDecodeError (PR #137) +- Avoid using too insignificant chunk (PR #137) + +### Added +- Add and expose function `set_logging_handler` to configure a specific StreamHandler from [@nmaynes](https://github.com/nmaynes) (PR #135) +- Add `CHANGELOG.md` entries, format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) (PR #141) + +## [2.0.7](https://github.com/Ousret/charset_normalizer/compare/2.0.6...2.0.7) (2021-10-11) +### Added +- Add support for Kazakh (Cyrillic) language detection (PR #109) + +### Changed +- Further, improve inferring the language from a given single-byte code page (PR #112) +- Vainly trying to leverage PEP263 when PEP3120 is not supported (PR #116) +- Refactoring for potential performance improvements in loops from [@adbar](https://github.com/adbar) (PR #113) +- Various detection improvement (MD+CD) (PR #117) + +### Removed +- Remove redundant logging entry about detected language(s) (PR #115) + +### Fixed +- Fix a minor inconsistency between Python 3.5 and other versions regarding language detection (PR #117 #102) + +## [2.0.6](https://github.com/Ousret/charset_normalizer/compare/2.0.5...2.0.6) (2021-09-18) +### Fixed +- Unforeseen regression with the loss of the backward-compatibility with some older minor of Python 3.5.x (PR #100) +- Fix CLI crash when using --minimal output in certain cases (PR #103) + +### Changed +- Minor improvement to the detection efficiency (less than 1%) (PR #106 #101) + +## [2.0.5](https://github.com/Ousret/charset_normalizer/compare/2.0.4...2.0.5) (2021-09-14) +### Changed +- The project now comply with: flake8, mypy, isort and black to ensure a better overall quality (PR #81) +- The BC-support with v1.x was improved, the old staticmethods are restored (PR #82) +- The Unicode detection is slightly improved (PR #93) +- Add syntax sugar \_\_bool\_\_ for results CharsetMatches list-container (PR #91) + +### Removed +- The project no longer raise warning on tiny content given for detection, will be simply logged as warning instead (PR #92) + +### Fixed +- In some rare case, the chunks extractor could cut in the middle of a multi-byte character and could mislead the mess detection (PR #95) +- Some rare 'space' characters could trip up the UnprintablePlugin/Mess detection (PR #96) +- The MANIFEST.in was not exhaustive (PR #78) + +## [2.0.4](https://github.com/Ousret/charset_normalizer/compare/2.0.3...2.0.4) (2021-07-30) +### Fixed +- The CLI no longer raise an unexpected exception when no encoding has been found (PR #70) +- Fix accessing the 'alphabets' property when the payload contains surrogate characters (PR #68) +- The logger could mislead (explain=True) on detected languages and the impact of one MBCS match (PR #72) +- Submatch factoring could be wrong in rare edge cases (PR #72) +- Multiple files given to the CLI were ignored when publishing results to STDOUT. (After the first path) (PR #72) +- Fix line endings from CRLF to LF for certain project files (PR #67) + +### Changed +- Adjust the MD to lower the sensitivity, thus improving the global detection reliability (PR #69 #76) +- Allow fallback on specified encoding if any (PR #71) + +## [2.0.3](https://github.com/Ousret/charset_normalizer/compare/2.0.2...2.0.3) (2021-07-16) +### Changed +- Part of the detection mechanism has been improved to be less sensitive, resulting in more accurate detection results. Especially ASCII. (PR #63) +- According to the community wishes, the detection will fall back on ASCII or UTF-8 in a last-resort case. (PR #64) + +## [2.0.2](https://github.com/Ousret/charset_normalizer/compare/2.0.1...2.0.2) (2021-07-15) +### Fixed +- Empty/Too small JSON payload miss-detection fixed. Report from [@tseaver](https://github.com/tseaver) (PR #59) + +### Changed +- Don't inject unicodedata2 into sys.modules from [@akx](https://github.com/akx) (PR #57) + +## [2.0.1](https://github.com/Ousret/charset_normalizer/compare/2.0.0...2.0.1) (2021-07-13) +### Fixed +- Make it work where there isn't a filesystem available, dropping assets frequencies.json. Report from [@sethmlarson](https://github.com/sethmlarson). (PR #55) +- Using explain=False permanently disable the verbose output in the current runtime (PR #47) +- One log entry (language target preemptive) was not show in logs when using explain=True (PR #47) +- Fix undesired exception (ValueError) on getitem of instance CharsetMatches (PR #52) + +### Changed +- Public function normalize default args values were not aligned with from_bytes (PR #53) + +### Added +- You may now use charset aliases in cp_isolation and cp_exclusion arguments (PR #47) + +## [2.0.0](https://github.com/Ousret/charset_normalizer/compare/1.4.1...2.0.0) (2021-07-02) +### Changed +- 4x to 5 times faster than the previous 1.4.0 release. At least 2x faster than Chardet. +- Accent has been made on UTF-8 detection, should perform rather instantaneous. +- The backward compatibility with Chardet has been greatly improved. The legacy detect function returns an identical charset name whenever possible. +- The detection mechanism has been slightly improved, now Turkish content is detected correctly (most of the time) +- The program has been rewritten to ease the readability and maintainability. (+Using static typing)+ +- utf_7 detection has been reinstated. + +### Removed +- This package no longer require anything when used with Python 3.5 (Dropped cached_property) +- Removed support for these languages: Catalan, Esperanto, Kazakh, Baque, Volapük, Azeri, Galician, Nynorsk, Macedonian, and Serbocroatian. +- The exception hook on UnicodeDecodeError has been removed. + +### Deprecated +- Methods coherence_non_latin, w_counter, chaos_secondary_pass of the class CharsetMatch are now deprecated and scheduled for removal in v3.0 + +### Fixed +- The CLI output used the relative path of the file(s). Should be absolute. + +## [1.4.1](https://github.com/Ousret/charset_normalizer/compare/1.4.0...1.4.1) (2021-05-28) +### Fixed +- Logger configuration/usage no longer conflict with others (PR #44) + +## [1.4.0](https://github.com/Ousret/charset_normalizer/compare/1.3.9...1.4.0) (2021-05-21) +### Removed +- Using standard logging instead of using the package loguru. +- Dropping nose test framework in favor of the maintained pytest. +- Choose to not use dragonmapper package to help with gibberish Chinese/CJK text. +- Require cached_property only for Python 3.5 due to constraint. Dropping for every other interpreter version. +- Stop support for UTF-7 that does not contain a SIG. +- Dropping PrettyTable, replaced with pure JSON output in CLI. + +### Fixed +- BOM marker in a CharsetNormalizerMatch instance could be False in rare cases even if obviously present. Due to the sub-match factoring process. +- Not searching properly for the BOM when trying utf32/16 parent codec. + +### Changed +- Improving the package final size by compressing frequencies.json. +- Huge improvement over the larges payload. + +### Added +- CLI now produces JSON consumable output. +- Return ASCII if given sequences fit. Given reasonable confidence. + +## [1.3.9](https://github.com/Ousret/charset_normalizer/compare/1.3.8...1.3.9) (2021-05-13) + +### Fixed +- In some very rare cases, you may end up getting encode/decode errors due to a bad bytes payload (PR #40) + +## [1.3.8](https://github.com/Ousret/charset_normalizer/compare/1.3.7...1.3.8) (2021-05-12) + +### Fixed +- Empty given payload for detection may cause an exception if trying to access the `alphabets` property. (PR #39) + +## [1.3.7](https://github.com/Ousret/charset_normalizer/compare/1.3.6...1.3.7) (2021-05-12) + +### Fixed +- The legacy detect function should return UTF-8-SIG if sig is present in the payload. (PR #38) + +## [1.3.6](https://github.com/Ousret/charset_normalizer/compare/1.3.5...1.3.6) (2021-02-09) + +### Changed +- Amend the previous release to allow prettytable 2.0 (PR #35) + +## [1.3.5](https://github.com/Ousret/charset_normalizer/compare/1.3.4...1.3.5) (2021-02-08) + +### Fixed +- Fix error while using the package with a python pre-release interpreter (PR #33) + +### Changed +- Dependencies refactoring, constraints revised. + +### Added +- Add python 3.9 and 3.10 to the supported interpreters + +MIT License + +Copyright (c) 2025 TAHRI Ahmed R. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/backend/venv/Lib/site-packages/charset_normalizer-3.4.3.dist-info/RECORD b/backend/venv/Lib/site-packages/charset_normalizer-3.4.3.dist-info/RECORD new file mode 100644 index 0000000..66baa63 --- /dev/null +++ b/backend/venv/Lib/site-packages/charset_normalizer-3.4.3.dist-info/RECORD @@ -0,0 +1,35 @@ +../../Scripts/normalizer.exe,sha256=ZwV2Wsn3TUtj9xrG-sZNWplwHcRG6U2hAKVeNJBYuts,108453 +charset_normalizer-3.4.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +charset_normalizer-3.4.3.dist-info/METADATA,sha256=tqX3UoI-UkqIN99aZsk646yI4NgMbu1MjlKr6BbITG4,37450 +charset_normalizer-3.4.3.dist-info/RECORD,, +charset_normalizer-3.4.3.dist-info/WHEEL,sha256=8UP9x9puWI0P1V_d7K2oMTBqfeLNm21CTzZ_Ptr0NXU,101 +charset_normalizer-3.4.3.dist-info/entry_points.txt,sha256=ADSTKrkXZ3hhdOVFi6DcUEHQRS0xfxDIE_pEz4wLIXA,65 +charset_normalizer-3.4.3.dist-info/licenses/LICENSE,sha256=GFd0hdNwTxpHne2OVzwJds_tMV_S_ReYP6mI2kwvcNE,1092 +charset_normalizer-3.4.3.dist-info/top_level.txt,sha256=7ASyzePr8_xuZWJsnqJjIBtyV8vhEo0wBCv1MPRRi3Q,19 +charset_normalizer/__init__.py,sha256=0NT8MHi7SKq3juMqYfOdrkzjisK0L73lneNHH4qaUAs,1638 +charset_normalizer/__main__.py,sha256=2sj_BS6H0sU25C1bMqz9DVwa6kOK9lchSEbSU-_iu7M,115 +charset_normalizer/__pycache__/__init__.cpython-312.pyc,, +charset_normalizer/__pycache__/__main__.cpython-312.pyc,, +charset_normalizer/__pycache__/api.cpython-312.pyc,, +charset_normalizer/__pycache__/cd.cpython-312.pyc,, +charset_normalizer/__pycache__/constant.cpython-312.pyc,, +charset_normalizer/__pycache__/legacy.cpython-312.pyc,, +charset_normalizer/__pycache__/md.cpython-312.pyc,, +charset_normalizer/__pycache__/models.cpython-312.pyc,, +charset_normalizer/__pycache__/utils.cpython-312.pyc,, +charset_normalizer/__pycache__/version.cpython-312.pyc,, +charset_normalizer/api.py,sha256=ODy4hX78b3ldTl5sViYPU1yzQ5qkclfgSIFE8BtNrTI,23337 +charset_normalizer/cd.py,sha256=uq8nVxRpR6Guc16ACvOWtL8KO3w7vYaCh8hHisuOyTg,12917 +charset_normalizer/cli/__init__.py,sha256=d9MUx-1V_qD3x9igIy4JT4oC5CU0yjulk7QyZWeRFhg,144 +charset_normalizer/cli/__main__.py,sha256=-pdJCyPywouPyFsC8_eTSgTmvh1YEvgjsvy1WZ0XjaA,13027 +charset_normalizer/cli/__pycache__/__init__.cpython-312.pyc,, +charset_normalizer/cli/__pycache__/__main__.cpython-312.pyc,, +charset_normalizer/constant.py,sha256=mCJmYzpBU27Ut9kiNWWoBbhhxQ-aRVw3K7LSwoFwBGI,44728 +charset_normalizer/legacy.py,sha256=ui08NlKqAXU3Y7smK-NFJjEgRRQz9ruM7aNCbT0OOrE,2811 +charset_normalizer/md.cp312-win_amd64.pyd,sha256=g0RpGMPXP-JEUwuUQ4HfHBk37fGvhfyam3QJ_YBggRw,10752 +charset_normalizer/md.py,sha256=LSuW2hNgXSgF7JGdRapLAHLuj6pABHiP85LTNAYmu7c,20780 +charset_normalizer/md__mypyc.cp312-win_amd64.pyd,sha256=JwWtMR29KFo4s4KtQCg1ZELLU_6L7JEtItpIwtpC-v4,128512 +charset_normalizer/models.py,sha256=ZR2PE-fqf6dASZfqdE5Uhkmr0o1MciSdXOjuNqwkmvg,12754 +charset_normalizer/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +charset_normalizer/utils.py,sha256=XtWIQeOuz7cnGebMzyi4Vvi1JtA84QBSIeR9PDzF7pw,12584 +charset_normalizer/version.py,sha256=laniWEeVCCfwRgYLf_rZ2f0qWaNwWTEXQEfUUL_MMvw,123 diff --git a/backend/venv/Lib/site-packages/charset_normalizer-3.4.3.dist-info/WHEEL b/backend/venv/Lib/site-packages/charset_normalizer-3.4.3.dist-info/WHEEL new file mode 100644 index 0000000..10ac2c2 --- /dev/null +++ b/backend/venv/Lib/site-packages/charset_normalizer-3.4.3.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: setuptools (80.9.0) +Root-Is-Purelib: false +Tag: cp312-cp312-win_amd64 + diff --git a/backend/venv/Lib/site-packages/charset_normalizer-3.4.3.dist-info/entry_points.txt b/backend/venv/Lib/site-packages/charset_normalizer-3.4.3.dist-info/entry_points.txt new file mode 100644 index 0000000..65619e7 --- /dev/null +++ b/backend/venv/Lib/site-packages/charset_normalizer-3.4.3.dist-info/entry_points.txt @@ -0,0 +1,2 @@ +[console_scripts] +normalizer = charset_normalizer.cli:cli_detect diff --git a/backend/venv/Lib/site-packages/charset_normalizer-3.4.3.dist-info/licenses/LICENSE b/backend/venv/Lib/site-packages/charset_normalizer-3.4.3.dist-info/licenses/LICENSE new file mode 100644 index 0000000..9725772 --- /dev/null +++ b/backend/venv/Lib/site-packages/charset_normalizer-3.4.3.dist-info/licenses/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 TAHRI Ahmed R. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/backend/venv/Lib/site-packages/charset_normalizer-3.4.3.dist-info/top_level.txt b/backend/venv/Lib/site-packages/charset_normalizer-3.4.3.dist-info/top_level.txt new file mode 100644 index 0000000..66958f0 --- /dev/null +++ b/backend/venv/Lib/site-packages/charset_normalizer-3.4.3.dist-info/top_level.txt @@ -0,0 +1 @@ +charset_normalizer diff --git a/backend/venv/Lib/site-packages/charset_normalizer/__init__.py b/backend/venv/Lib/site-packages/charset_normalizer/__init__.py new file mode 100644 index 0000000..0d3a379 --- /dev/null +++ b/backend/venv/Lib/site-packages/charset_normalizer/__init__.py @@ -0,0 +1,48 @@ +""" +Charset-Normalizer +~~~~~~~~~~~~~~ +The Real First Universal Charset Detector. +A library that helps you read text from an unknown charset encoding. +Motivated by chardet, This package is trying to resolve the issue by taking a new approach. +All IANA character set names for which the Python core library provides codecs are supported. + +Basic usage: + >>> from charset_normalizer import from_bytes + >>> results = from_bytes('Bсеки човек има право на образование. Oбразованието!'.encode('utf_8')) + >>> best_guess = results.best() + >>> str(best_guess) + 'Bсеки човек има право на образование. Oбразованието!' + +Others methods and usages are available - see the full documentation +at . +:copyright: (c) 2021 by Ahmed TAHRI +:license: MIT, see LICENSE for more details. +""" + +from __future__ import annotations + +import logging + +from .api import from_bytes, from_fp, from_path, is_binary +from .legacy import detect +from .models import CharsetMatch, CharsetMatches +from .utils import set_logging_handler +from .version import VERSION, __version__ + +__all__ = ( + "from_fp", + "from_path", + "from_bytes", + "is_binary", + "detect", + "CharsetMatch", + "CharsetMatches", + "__version__", + "VERSION", + "set_logging_handler", +) + +# Attach a NullHandler to the top level logger by default +# https://docs.python.org/3.3/howto/logging.html#configuring-logging-for-a-library + +logging.getLogger("charset_normalizer").addHandler(logging.NullHandler()) diff --git a/backend/venv/Lib/site-packages/charset_normalizer/__main__.py b/backend/venv/Lib/site-packages/charset_normalizer/__main__.py new file mode 100644 index 0000000..e0e76f7 --- /dev/null +++ b/backend/venv/Lib/site-packages/charset_normalizer/__main__.py @@ -0,0 +1,6 @@ +from __future__ import annotations + +from .cli import cli_detect + +if __name__ == "__main__": + cli_detect() diff --git a/backend/venv/Lib/site-packages/charset_normalizer/__pycache__/__init__.cpython-312.pyc b/backend/venv/Lib/site-packages/charset_normalizer/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..058f090724781629f327629f6da9439d86beae12 GIT binary patch literal 1791 zcmcIk&1)M+6rYu3$zIt`Z66AS(kX@5YHc~S2`wTuIR3x}+Y0{ZVG%5&-H~?V*$-xB z<*J9`=F&f*e?!T|ErgoVx_>|~D@-vggd745xjBSF>8WpaB|F8vb`Njgdo%C7-}{>1 z#>R96-yeUya9Tx#o-1MS6*5M99Ru?%vXOyo&CW5+%NaRM@p+av@^-- z`G+$DAlHAp{8-DRhaX*Q2V813JCLsbkNfPvRzux9yb z{i}a{`o2T)E+q`FyIe?o;JY2l1;~93g#vej2y;qo zEa?{#w|L-T;^W9a^n)WGTUmTeeJikCzg^Y01L<~%q&9AL(_@>;S-kJK0*AypByEa; zmAnhLu?)bs2v~i90LU2LT;5qu{Sr%3jv;yM6ORhq z3OGJ;T+2yaJ?Kg&0DJ+bS6P9Zj%&kJz)CHF37m;23cq9$ta$K z24}O;ilF&+U_~DFC6R96>oBAD94SLlo1bsH(utZ?EAZy)k>FI$-)!1aRj*k=*yV29 zku^MHRq(={g^$(1Eju1e?Edn`?xtR2u0?%8Yj}Hee>MfMwYjpkv$vMcn5RYxh8iG> zs{T?fXGKfO#P@>?m)Lo!w!BhEbhR$ocqFBiZ-vQ7%7jEZ$%re=rt8DTfrldaghj06 zlF|NZZWC!a$@rTR6>xJ3hTddByA3;HI#4@CIhd6`U)$Z=tnVac(^NYSB{I#5&f#H1 zyrjsGBEyP|D5Bm@URGpWkugO^fh3bRYgc(YDVZkJ-!v25G+U93I5kZUj}S^qeK1L$ zgl-n)I;e`56d7$3tDDA6iXQAA6W8&Rp-4hCv*4vZ_6(0grXmx@Ao56?$}LEo@|Jf3an^l=NP1kp&X;#B-GJFs6iWptu?*RZc z0^$J3WnR;?SGg&z@aKm}``|eme}QV}sP+`S^9 literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/charset_normalizer/__pycache__/__main__.cpython-312.pyc b/backend/venv/Lib/site-packages/charset_normalizer/__pycache__/__main__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6ceb5ce21f628d1f5d15db591b3a358139707d96 GIT binary patch literal 366 zcmXv}Jxc>Y5S_iflaLU56&ov4_(32RA~vQBMiiT{uxxHebKKqDvAc;ReZYU>nt_^C#nupD1%(@EOIvOEs zqls;nv&-()MTgxX#x15ZlP4|K7h#M_vJt8g>qLEKB8z*uQ^hSB77m0qXt~OCDw1e| z`e2oAKOYyBlQfgV1W$F{1t@<8qK4I&f*6t@SbmP@upLXUH{7qeRjz4cW BXea;x literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/charset_normalizer/__pycache__/api.cpython-312.pyc b/backend/venv/Lib/site-packages/charset_normalizer/__pycache__/api.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..260a78f10400929471be1573dd1c459f1c735e0a GIT binary patch literal 18174 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 literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/charset_normalizer/__pycache__/constant.cpython-312.pyc b/backend/venv/Lib/site-packages/charset_normalizer/__pycache__/constant.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ee557773156f92292f76cad7b35e0ee895c51dec GIT binary patch literal 40821 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 H@6Y@{^9aMn literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/charset_normalizer/__pycache__/legacy.cpython-312.pyc b/backend/venv/Lib/site-packages/charset_normalizer/__pycache__/legacy.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d792c76fc4f1318dc1dd33304cc7737f1ddb8862 GIT binary patch literal 3021 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 literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/charset_normalizer/__pycache__/models.cpython-312.pyc b/backend/venv/Lib/site-packages/charset_normalizer/__pycache__/models.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c25845e41597803a288d68c425d11840436a9672 GIT binary patch literal 17134 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 literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/charset_normalizer/__pycache__/version.cpython-312.pyc b/backend/venv/Lib/site-packages/charset_normalizer/__pycache__/version.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5fcf1d555ee54ec1fcce29654e32b69069de7b7c GIT binary patch literal 393 zcmYLEF-yZh6wW10TQ5{xI&~@N(!nULU5dE09fZnk=prqF4$6 zMD@T(wN#)G&C;lLy0Vo2BT3zXd1vVpy_BA=!RC3u1T99C3y1meBN>-KY}mffLOYb4 znCcaC$E?J_Y?sn;24lho7{?If<8e6V6l0!T6dM>XY~)lIf#-yA=BU~2?RVO@$}DmI zW%U|56ml6VZiD$5ort0a6>i7^)a~>RTIh^Yw~9EECRNn82QKvqil`rIc6Y?c*rR(qC-*1ciw&7RH2}bus)E#a dRsriTtNBag8Rnm0;QW{E^mEndI{sDpnZtnm9 literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/charset_normalizer/api.py b/backend/venv/Lib/site-packages/charset_normalizer/api.py new file mode 100644 index 0000000..ebd9639 --- /dev/null +++ b/backend/venv/Lib/site-packages/charset_normalizer/api.py @@ -0,0 +1,669 @@ +from __future__ import annotations + +import logging +from os import PathLike +from typing import BinaryIO + +from .cd import ( + coherence_ratio, + encoding_languages, + mb_encoding_languages, + merge_coherence_ratios, +) +from .constant import IANA_SUPPORTED, TOO_BIG_SEQUENCE, TOO_SMALL_SEQUENCE, TRACE +from .md import mess_ratio +from .models import CharsetMatch, CharsetMatches +from .utils import ( + any_specified_encoding, + cut_sequence_chunks, + iana_name, + identify_sig_or_bom, + is_cp_similar, + is_multi_byte_encoding, + should_strip_sig_or_bom, +) + +logger = logging.getLogger("charset_normalizer") +explain_handler = logging.StreamHandler() +explain_handler.setFormatter( + logging.Formatter("%(asctime)s | %(levelname)s | %(message)s") +) + + +def from_bytes( + sequences: bytes | bytearray, + steps: int = 5, + chunk_size: int = 512, + threshold: float = 0.2, + cp_isolation: list[str] | None = None, + cp_exclusion: list[str] | None = None, + preemptive_behaviour: bool = True, + explain: bool = False, + language_threshold: float = 0.1, + enable_fallback: bool = True, +) -> CharsetMatches: + """ + Given a raw bytes sequence, return the best possibles charset usable to render str objects. + If there is no results, it is a strong indicator that the source is binary/not text. + By default, the process will extract 5 blocks of 512o each to assess the mess and coherence of a given sequence. + And will give up a particular code page after 20% of measured mess. Those criteria are customizable at will. + + The preemptive behavior DOES NOT replace the traditional detection workflow, it prioritize a particular code page + but never take it for granted. Can improve the performance. + + You may want to focus your attention to some code page or/and not others, use cp_isolation and cp_exclusion for that + purpose. + + This function will strip the SIG in the payload/sequence every time except on UTF-16, UTF-32. + By default the library does not setup any handler other than the NullHandler, if you choose to set the 'explain' + toggle to True it will alter the logger configuration to add a StreamHandler that is suitable for debugging. + Custom logging format and handler can be set manually. + """ + + if not isinstance(sequences, (bytearray, bytes)): + raise TypeError( + "Expected object of type bytes or bytearray, got: {}".format( + type(sequences) + ) + ) + + if explain: + previous_logger_level: int = logger.level + logger.addHandler(explain_handler) + logger.setLevel(TRACE) + + length: int = len(sequences) + + if length == 0: + logger.debug("Encoding detection on empty bytes, assuming utf_8 intention.") + if explain: # Defensive: ensure exit path clean handler + logger.removeHandler(explain_handler) + logger.setLevel(previous_logger_level or logging.WARNING) + return CharsetMatches([CharsetMatch(sequences, "utf_8", 0.0, False, [], "")]) + + if cp_isolation is not None: + logger.log( + TRACE, + "cp_isolation is set. use this flag for debugging purpose. " + "limited list of encoding allowed : %s.", + ", ".join(cp_isolation), + ) + cp_isolation = [iana_name(cp, False) for cp in cp_isolation] + else: + cp_isolation = [] + + if cp_exclusion is not None: + logger.log( + TRACE, + "cp_exclusion is set. use this flag for debugging purpose. " + "limited list of encoding excluded : %s.", + ", ".join(cp_exclusion), + ) + cp_exclusion = [iana_name(cp, False) for cp in cp_exclusion] + else: + cp_exclusion = [] + + if length <= (chunk_size * steps): + logger.log( + TRACE, + "override steps (%i) and chunk_size (%i) as content does not fit (%i byte(s) given) parameters.", + steps, + chunk_size, + length, + ) + steps = 1 + chunk_size = length + + if steps > 1 and length / steps < chunk_size: + chunk_size = int(length / steps) + + is_too_small_sequence: bool = len(sequences) < TOO_SMALL_SEQUENCE + is_too_large_sequence: bool = len(sequences) >= TOO_BIG_SEQUENCE + + if is_too_small_sequence: + logger.log( + TRACE, + "Trying to detect encoding from a tiny portion of ({}) byte(s).".format( + length + ), + ) + elif is_too_large_sequence: + logger.log( + TRACE, + "Using lazy str decoding because the payload is quite large, ({}) byte(s).".format( + length + ), + ) + + prioritized_encodings: list[str] = [] + + specified_encoding: str | None = ( + any_specified_encoding(sequences) if preemptive_behaviour else None + ) + + if specified_encoding is not None: + prioritized_encodings.append(specified_encoding) + logger.log( + TRACE, + "Detected declarative mark in sequence. Priority +1 given for %s.", + specified_encoding, + ) + + tested: set[str] = set() + tested_but_hard_failure: list[str] = [] + tested_but_soft_failure: list[str] = [] + + fallback_ascii: CharsetMatch | None = None + fallback_u8: CharsetMatch | None = None + fallback_specified: CharsetMatch | None = None + + results: CharsetMatches = CharsetMatches() + + early_stop_results: CharsetMatches = CharsetMatches() + + sig_encoding, sig_payload = identify_sig_or_bom(sequences) + + if sig_encoding is not None: + prioritized_encodings.append(sig_encoding) + logger.log( + TRACE, + "Detected a SIG or BOM mark on first %i byte(s). Priority +1 given for %s.", + len(sig_payload), + sig_encoding, + ) + + prioritized_encodings.append("ascii") + + if "utf_8" not in prioritized_encodings: + prioritized_encodings.append("utf_8") + + for encoding_iana in prioritized_encodings + IANA_SUPPORTED: + if cp_isolation and encoding_iana not in cp_isolation: + continue + + if cp_exclusion and encoding_iana in cp_exclusion: + continue + + if encoding_iana in tested: + continue + + tested.add(encoding_iana) + + decoded_payload: str | None = None + bom_or_sig_available: bool = sig_encoding == encoding_iana + strip_sig_or_bom: bool = bom_or_sig_available and should_strip_sig_or_bom( + encoding_iana + ) + + if encoding_iana in {"utf_16", "utf_32"} and not bom_or_sig_available: + logger.log( + TRACE, + "Encoding %s won't be tested as-is because it require a BOM. Will try some sub-encoder LE/BE.", + encoding_iana, + ) + continue + if encoding_iana in {"utf_7"} and not bom_or_sig_available: + logger.log( + TRACE, + "Encoding %s won't be tested as-is because detection is unreliable without BOM/SIG.", + encoding_iana, + ) + continue + + try: + is_multi_byte_decoder: bool = is_multi_byte_encoding(encoding_iana) + except (ModuleNotFoundError, ImportError): + logger.log( + TRACE, + "Encoding %s does not provide an IncrementalDecoder", + encoding_iana, + ) + continue + + try: + if is_too_large_sequence and is_multi_byte_decoder is False: + str( + ( + sequences[: int(50e4)] + if strip_sig_or_bom is False + else sequences[len(sig_payload) : int(50e4)] + ), + encoding=encoding_iana, + ) + else: + decoded_payload = str( + ( + sequences + if strip_sig_or_bom is False + else sequences[len(sig_payload) :] + ), + encoding=encoding_iana, + ) + except (UnicodeDecodeError, LookupError) as e: + if not isinstance(e, LookupError): + logger.log( + TRACE, + "Code page %s does not fit given bytes sequence at ALL. %s", + encoding_iana, + str(e), + ) + tested_but_hard_failure.append(encoding_iana) + continue + + similar_soft_failure_test: bool = False + + for encoding_soft_failed in tested_but_soft_failure: + if is_cp_similar(encoding_iana, encoding_soft_failed): + similar_soft_failure_test = True + break + + if similar_soft_failure_test: + logger.log( + TRACE, + "%s is deemed too similar to code page %s and was consider unsuited already. Continuing!", + encoding_iana, + encoding_soft_failed, + ) + continue + + r_ = range( + 0 if not bom_or_sig_available else len(sig_payload), + length, + int(length / steps), + ) + + multi_byte_bonus: bool = ( + is_multi_byte_decoder + and decoded_payload is not None + and len(decoded_payload) < length + ) + + if multi_byte_bonus: + logger.log( + TRACE, + "Code page %s is a multi byte encoding table and it appear that at least one character " + "was encoded using n-bytes.", + encoding_iana, + ) + + max_chunk_gave_up: int = int(len(r_) / 4) + + max_chunk_gave_up = max(max_chunk_gave_up, 2) + early_stop_count: int = 0 + lazy_str_hard_failure = False + + md_chunks: list[str] = [] + md_ratios = [] + + try: + for chunk in cut_sequence_chunks( + sequences, + encoding_iana, + r_, + chunk_size, + bom_or_sig_available, + strip_sig_or_bom, + sig_payload, + is_multi_byte_decoder, + decoded_payload, + ): + md_chunks.append(chunk) + + md_ratios.append( + mess_ratio( + chunk, + threshold, + explain is True and 1 <= len(cp_isolation) <= 2, + ) + ) + + if md_ratios[-1] >= threshold: + early_stop_count += 1 + + if (early_stop_count >= max_chunk_gave_up) or ( + bom_or_sig_available and strip_sig_or_bom is False + ): + break + except ( + UnicodeDecodeError + ) as e: # Lazy str loading may have missed something there + logger.log( + TRACE, + "LazyStr Loading: After MD chunk decode, code page %s does not fit given bytes sequence at ALL. %s", + encoding_iana, + str(e), + ) + early_stop_count = max_chunk_gave_up + lazy_str_hard_failure = True + + # We might want to check the sequence again with the whole content + # Only if initial MD tests passes + if ( + not lazy_str_hard_failure + and is_too_large_sequence + and not is_multi_byte_decoder + ): + try: + sequences[int(50e3) :].decode(encoding_iana, errors="strict") + except UnicodeDecodeError as e: + logger.log( + TRACE, + "LazyStr Loading: After final lookup, code page %s does not fit given bytes sequence at ALL. %s", + encoding_iana, + str(e), + ) + tested_but_hard_failure.append(encoding_iana) + continue + + mean_mess_ratio: float = sum(md_ratios) / len(md_ratios) if md_ratios else 0.0 + if mean_mess_ratio >= threshold or early_stop_count >= max_chunk_gave_up: + tested_but_soft_failure.append(encoding_iana) + logger.log( + TRACE, + "%s was excluded because of initial chaos probing. Gave up %i time(s). " + "Computed mean chaos is %f %%.", + encoding_iana, + early_stop_count, + round(mean_mess_ratio * 100, ndigits=3), + ) + # Preparing those fallbacks in case we got nothing. + if ( + enable_fallback + and encoding_iana + in ["ascii", "utf_8", specified_encoding, "utf_16", "utf_32"] + and not lazy_str_hard_failure + ): + fallback_entry = CharsetMatch( + sequences, + encoding_iana, + threshold, + bom_or_sig_available, + [], + decoded_payload, + preemptive_declaration=specified_encoding, + ) + if encoding_iana == specified_encoding: + fallback_specified = fallback_entry + elif encoding_iana == "ascii": + fallback_ascii = fallback_entry + else: + fallback_u8 = fallback_entry + continue + + logger.log( + TRACE, + "%s passed initial chaos probing. Mean measured chaos is %f %%", + encoding_iana, + round(mean_mess_ratio * 100, ndigits=3), + ) + + if not is_multi_byte_decoder: + target_languages: list[str] = encoding_languages(encoding_iana) + else: + target_languages = mb_encoding_languages(encoding_iana) + + if target_languages: + logger.log( + TRACE, + "{} should target any language(s) of {}".format( + encoding_iana, str(target_languages) + ), + ) + + cd_ratios = [] + + # We shall skip the CD when its about ASCII + # Most of the time its not relevant to run "language-detection" on it. + if encoding_iana != "ascii": + for chunk in md_chunks: + chunk_languages = coherence_ratio( + chunk, + language_threshold, + ",".join(target_languages) if target_languages else None, + ) + + cd_ratios.append(chunk_languages) + + cd_ratios_merged = merge_coherence_ratios(cd_ratios) + + if cd_ratios_merged: + logger.log( + TRACE, + "We detected language {} using {}".format( + cd_ratios_merged, encoding_iana + ), + ) + + current_match = CharsetMatch( + sequences, + encoding_iana, + mean_mess_ratio, + bom_or_sig_available, + cd_ratios_merged, + ( + decoded_payload + if ( + is_too_large_sequence is False + or encoding_iana in [specified_encoding, "ascii", "utf_8"] + ) + else None + ), + preemptive_declaration=specified_encoding, + ) + + results.append(current_match) + + if ( + encoding_iana in [specified_encoding, "ascii", "utf_8"] + and mean_mess_ratio < 0.1 + ): + # If md says nothing to worry about, then... stop immediately! + if mean_mess_ratio == 0.0: + logger.debug( + "Encoding detection: %s is most likely the one.", + current_match.encoding, + ) + if explain: # Defensive: ensure exit path clean handler + logger.removeHandler(explain_handler) + logger.setLevel(previous_logger_level) + return CharsetMatches([current_match]) + + early_stop_results.append(current_match) + + if ( + len(early_stop_results) + and (specified_encoding is None or specified_encoding in tested) + and "ascii" in tested + and "utf_8" in tested + ): + probable_result: CharsetMatch = early_stop_results.best() # type: ignore[assignment] + logger.debug( + "Encoding detection: %s is most likely the one.", + probable_result.encoding, + ) + if explain: # Defensive: ensure exit path clean handler + logger.removeHandler(explain_handler) + logger.setLevel(previous_logger_level) + + return CharsetMatches([probable_result]) + + if encoding_iana == sig_encoding: + logger.debug( + "Encoding detection: %s is most likely the one as we detected a BOM or SIG within " + "the beginning of the sequence.", + encoding_iana, + ) + if explain: # Defensive: ensure exit path clean handler + logger.removeHandler(explain_handler) + logger.setLevel(previous_logger_level) + return CharsetMatches([results[encoding_iana]]) + + if len(results) == 0: + if fallback_u8 or fallback_ascii or fallback_specified: + logger.log( + TRACE, + "Nothing got out of the detection process. Using ASCII/UTF-8/Specified fallback.", + ) + + if fallback_specified: + logger.debug( + "Encoding detection: %s will be used as a fallback match", + fallback_specified.encoding, + ) + results.append(fallback_specified) + elif ( + (fallback_u8 and fallback_ascii is None) + or ( + fallback_u8 + and fallback_ascii + and fallback_u8.fingerprint != fallback_ascii.fingerprint + ) + or (fallback_u8 is not None) + ): + logger.debug("Encoding detection: utf_8 will be used as a fallback match") + results.append(fallback_u8) + elif fallback_ascii: + logger.debug("Encoding detection: ascii will be used as a fallback match") + results.append(fallback_ascii) + + if results: + logger.debug( + "Encoding detection: Found %s as plausible (best-candidate) for content. With %i alternatives.", + results.best().encoding, # type: ignore + len(results) - 1, + ) + else: + logger.debug("Encoding detection: Unable to determine any suitable charset.") + + if explain: + logger.removeHandler(explain_handler) + logger.setLevel(previous_logger_level) + + return results + + +def from_fp( + fp: BinaryIO, + steps: int = 5, + chunk_size: int = 512, + threshold: float = 0.20, + cp_isolation: list[str] | None = None, + cp_exclusion: list[str] | None = None, + preemptive_behaviour: bool = True, + explain: bool = False, + language_threshold: float = 0.1, + enable_fallback: bool = True, +) -> CharsetMatches: + """ + Same thing than the function from_bytes but using a file pointer that is already ready. + Will not close the file pointer. + """ + return from_bytes( + fp.read(), + steps, + chunk_size, + threshold, + cp_isolation, + cp_exclusion, + preemptive_behaviour, + explain, + language_threshold, + enable_fallback, + ) + + +def from_path( + path: str | bytes | PathLike, # type: ignore[type-arg] + steps: int = 5, + chunk_size: int = 512, + threshold: float = 0.20, + cp_isolation: list[str] | None = None, + cp_exclusion: list[str] | None = None, + preemptive_behaviour: bool = True, + explain: bool = False, + language_threshold: float = 0.1, + enable_fallback: bool = True, +) -> CharsetMatches: + """ + Same thing than the function from_bytes but with one extra step. Opening and reading given file path in binary mode. + Can raise IOError. + """ + with open(path, "rb") as fp: + return from_fp( + fp, + steps, + chunk_size, + threshold, + cp_isolation, + cp_exclusion, + preemptive_behaviour, + explain, + language_threshold, + enable_fallback, + ) + + +def is_binary( + fp_or_path_or_payload: PathLike | str | BinaryIO | bytes, # type: ignore[type-arg] + steps: int = 5, + chunk_size: int = 512, + threshold: float = 0.20, + cp_isolation: list[str] | None = None, + cp_exclusion: list[str] | None = None, + preemptive_behaviour: bool = True, + explain: bool = False, + language_threshold: float = 0.1, + enable_fallback: bool = False, +) -> bool: + """ + Detect if the given input (file, bytes, or path) points to a binary file. aka. not a string. + Based on the same main heuristic algorithms and default kwargs at the sole exception that fallbacks match + are disabled to be stricter around ASCII-compatible but unlikely to be a string. + """ + if isinstance(fp_or_path_or_payload, (str, PathLike)): + guesses = from_path( + fp_or_path_or_payload, + steps=steps, + chunk_size=chunk_size, + threshold=threshold, + cp_isolation=cp_isolation, + cp_exclusion=cp_exclusion, + preemptive_behaviour=preemptive_behaviour, + explain=explain, + language_threshold=language_threshold, + enable_fallback=enable_fallback, + ) + elif isinstance( + fp_or_path_or_payload, + ( + bytes, + bytearray, + ), + ): + guesses = from_bytes( + fp_or_path_or_payload, + steps=steps, + chunk_size=chunk_size, + threshold=threshold, + cp_isolation=cp_isolation, + cp_exclusion=cp_exclusion, + preemptive_behaviour=preemptive_behaviour, + explain=explain, + language_threshold=language_threshold, + enable_fallback=enable_fallback, + ) + else: + guesses = from_fp( + fp_or_path_or_payload, + steps=steps, + chunk_size=chunk_size, + threshold=threshold, + cp_isolation=cp_isolation, + cp_exclusion=cp_exclusion, + preemptive_behaviour=preemptive_behaviour, + explain=explain, + language_threshold=language_threshold, + enable_fallback=enable_fallback, + ) + + return not guesses diff --git a/backend/venv/Lib/site-packages/charset_normalizer/cd.py b/backend/venv/Lib/site-packages/charset_normalizer/cd.py new file mode 100644 index 0000000..71a3ed5 --- /dev/null +++ b/backend/venv/Lib/site-packages/charset_normalizer/cd.py @@ -0,0 +1,395 @@ +from __future__ import annotations + +import importlib +from codecs import IncrementalDecoder +from collections import Counter +from functools import lru_cache +from typing import Counter as TypeCounter + +from .constant import ( + FREQUENCIES, + KO_NAMES, + LANGUAGE_SUPPORTED_COUNT, + TOO_SMALL_SEQUENCE, + ZH_NAMES, +) +from .md import is_suspiciously_successive_range +from .models import CoherenceMatches +from .utils import ( + is_accentuated, + is_latin, + is_multi_byte_encoding, + is_unicode_range_secondary, + unicode_range, +) + + +def encoding_unicode_range(iana_name: str) -> list[str]: + """ + Return associated unicode ranges in a single byte code page. + """ + if is_multi_byte_encoding(iana_name): + raise OSError("Function not supported on multi-byte code page") + + decoder = importlib.import_module(f"encodings.{iana_name}").IncrementalDecoder + + p: IncrementalDecoder = decoder(errors="ignore") + seen_ranges: dict[str, int] = {} + character_count: int = 0 + + for i in range(0x40, 0xFF): + chunk: str = p.decode(bytes([i])) + + if chunk: + character_range: str | None = unicode_range(chunk) + + if character_range is None: + continue + + if is_unicode_range_secondary(character_range) is False: + if character_range not in seen_ranges: + seen_ranges[character_range] = 0 + seen_ranges[character_range] += 1 + character_count += 1 + + return sorted( + [ + character_range + for character_range in seen_ranges + if seen_ranges[character_range] / character_count >= 0.15 + ] + ) + + +def unicode_range_languages(primary_range: str) -> list[str]: + """ + Return inferred languages used with a unicode range. + """ + languages: list[str] = [] + + for language, characters in FREQUENCIES.items(): + for character in characters: + if unicode_range(character) == primary_range: + languages.append(language) + break + + return languages + + +@lru_cache() +def encoding_languages(iana_name: str) -> list[str]: + """ + Single-byte encoding language association. Some code page are heavily linked to particular language(s). + This function does the correspondence. + """ + unicode_ranges: list[str] = encoding_unicode_range(iana_name) + primary_range: str | None = None + + for specified_range in unicode_ranges: + if "Latin" not in specified_range: + primary_range = specified_range + break + + if primary_range is None: + return ["Latin Based"] + + return unicode_range_languages(primary_range) + + +@lru_cache() +def mb_encoding_languages(iana_name: str) -> list[str]: + """ + Multi-byte encoding language association. Some code page are heavily linked to particular language(s). + This function does the correspondence. + """ + if ( + iana_name.startswith("shift_") + or iana_name.startswith("iso2022_jp") + or iana_name.startswith("euc_j") + or iana_name == "cp932" + ): + return ["Japanese"] + if iana_name.startswith("gb") or iana_name in ZH_NAMES: + return ["Chinese"] + if iana_name.startswith("iso2022_kr") or iana_name in KO_NAMES: + return ["Korean"] + + return [] + + +@lru_cache(maxsize=LANGUAGE_SUPPORTED_COUNT) +def get_target_features(language: str) -> tuple[bool, bool]: + """ + Determine main aspects from a supported language if it contains accents and if is pure Latin. + """ + target_have_accents: bool = False + target_pure_latin: bool = True + + for character in FREQUENCIES[language]: + if not target_have_accents and is_accentuated(character): + target_have_accents = True + if target_pure_latin and is_latin(character) is False: + target_pure_latin = False + + return target_have_accents, target_pure_latin + + +def alphabet_languages( + characters: list[str], ignore_non_latin: bool = False +) -> list[str]: + """ + Return associated languages associated to given characters. + """ + languages: list[tuple[str, float]] = [] + + source_have_accents = any(is_accentuated(character) for character in characters) + + for language, language_characters in FREQUENCIES.items(): + target_have_accents, target_pure_latin = get_target_features(language) + + if ignore_non_latin and target_pure_latin is False: + continue + + if target_have_accents is False and source_have_accents: + continue + + character_count: int = len(language_characters) + + character_match_count: int = len( + [c for c in language_characters if c in characters] + ) + + ratio: float = character_match_count / character_count + + if ratio >= 0.2: + languages.append((language, ratio)) + + languages = sorted(languages, key=lambda x: x[1], reverse=True) + + return [compatible_language[0] for compatible_language in languages] + + +def characters_popularity_compare( + language: str, ordered_characters: list[str] +) -> float: + """ + Determine if a ordered characters list (by occurrence from most appearance to rarest) match a particular language. + The result is a ratio between 0. (absolutely no correspondence) and 1. (near perfect fit). + Beware that is function is not strict on the match in order to ease the detection. (Meaning close match is 1.) + """ + if language not in FREQUENCIES: + raise ValueError(f"{language} not available") + + character_approved_count: int = 0 + FREQUENCIES_language_set = set(FREQUENCIES[language]) + + ordered_characters_count: int = len(ordered_characters) + target_language_characters_count: int = len(FREQUENCIES[language]) + + large_alphabet: bool = target_language_characters_count > 26 + + for character, character_rank in zip( + ordered_characters, range(0, ordered_characters_count) + ): + if character not in FREQUENCIES_language_set: + continue + + character_rank_in_language: int = FREQUENCIES[language].index(character) + expected_projection_ratio: float = ( + target_language_characters_count / ordered_characters_count + ) + character_rank_projection: int = int(character_rank * expected_projection_ratio) + + if ( + large_alphabet is False + and abs(character_rank_projection - character_rank_in_language) > 4 + ): + continue + + if ( + large_alphabet is True + and abs(character_rank_projection - character_rank_in_language) + < target_language_characters_count / 3 + ): + character_approved_count += 1 + continue + + characters_before_source: list[str] = FREQUENCIES[language][ + 0:character_rank_in_language + ] + characters_after_source: list[str] = FREQUENCIES[language][ + character_rank_in_language: + ] + characters_before: list[str] = ordered_characters[0:character_rank] + characters_after: list[str] = ordered_characters[character_rank:] + + before_match_count: int = len( + set(characters_before) & set(characters_before_source) + ) + + after_match_count: int = len( + set(characters_after) & set(characters_after_source) + ) + + if len(characters_before_source) == 0 and before_match_count <= 4: + character_approved_count += 1 + continue + + if len(characters_after_source) == 0 and after_match_count <= 4: + character_approved_count += 1 + continue + + if ( + before_match_count / len(characters_before_source) >= 0.4 + or after_match_count / len(characters_after_source) >= 0.4 + ): + character_approved_count += 1 + continue + + return character_approved_count / len(ordered_characters) + + +def alpha_unicode_split(decoded_sequence: str) -> list[str]: + """ + Given a decoded text sequence, return a list of str. Unicode range / alphabet separation. + Ex. a text containing English/Latin with a bit a Hebrew will return two items in the resulting list; + One containing the latin letters and the other hebrew. + """ + layers: dict[str, str] = {} + + for character in decoded_sequence: + if character.isalpha() is False: + continue + + character_range: str | None = unicode_range(character) + + if character_range is None: + continue + + layer_target_range: str | None = None + + for discovered_range in layers: + if ( + is_suspiciously_successive_range(discovered_range, character_range) + is False + ): + layer_target_range = discovered_range + break + + if layer_target_range is None: + layer_target_range = character_range + + if layer_target_range not in layers: + layers[layer_target_range] = character.lower() + continue + + layers[layer_target_range] += character.lower() + + return list(layers.values()) + + +def merge_coherence_ratios(results: list[CoherenceMatches]) -> CoherenceMatches: + """ + This function merge results previously given by the function coherence_ratio. + The return type is the same as coherence_ratio. + """ + per_language_ratios: dict[str, list[float]] = {} + for result in results: + for sub_result in result: + language, ratio = sub_result + if language not in per_language_ratios: + per_language_ratios[language] = [ratio] + continue + per_language_ratios[language].append(ratio) + + merge = [ + ( + language, + round( + sum(per_language_ratios[language]) / len(per_language_ratios[language]), + 4, + ), + ) + for language in per_language_ratios + ] + + return sorted(merge, key=lambda x: x[1], reverse=True) + + +def filter_alt_coherence_matches(results: CoherenceMatches) -> CoherenceMatches: + """ + We shall NOT return "English—" in CoherenceMatches because it is an alternative + of "English". This function only keeps the best match and remove the em-dash in it. + """ + index_results: dict[str, list[float]] = dict() + + for result in results: + language, ratio = result + no_em_name: str = language.replace("—", "") + + if no_em_name not in index_results: + index_results[no_em_name] = [] + + index_results[no_em_name].append(ratio) + + if any(len(index_results[e]) > 1 for e in index_results): + filtered_results: CoherenceMatches = [] + + for language in index_results: + filtered_results.append((language, max(index_results[language]))) + + return filtered_results + + return results + + +@lru_cache(maxsize=2048) +def coherence_ratio( + decoded_sequence: str, threshold: float = 0.1, lg_inclusion: str | None = None +) -> CoherenceMatches: + """ + Detect ANY language that can be identified in given sequence. The sequence will be analysed by layers. + A layer = Character extraction by alphabets/ranges. + """ + + results: list[tuple[str, float]] = [] + ignore_non_latin: bool = False + + sufficient_match_count: int = 0 + + lg_inclusion_list = lg_inclusion.split(",") if lg_inclusion is not None else [] + if "Latin Based" in lg_inclusion_list: + ignore_non_latin = True + lg_inclusion_list.remove("Latin Based") + + for layer in alpha_unicode_split(decoded_sequence): + sequence_frequencies: TypeCounter[str] = Counter(layer) + most_common = sequence_frequencies.most_common() + + character_count: int = sum(o for c, o in most_common) + + if character_count <= TOO_SMALL_SEQUENCE: + continue + + popular_character_ordered: list[str] = [c for c, o in most_common] + + for language in lg_inclusion_list or alphabet_languages( + popular_character_ordered, ignore_non_latin + ): + ratio: float = characters_popularity_compare( + language, popular_character_ordered + ) + + if ratio < threshold: + continue + elif ratio >= 0.8: + sufficient_match_count += 1 + + results.append((language, round(ratio, 4))) + + if sufficient_match_count >= 3: + break + + return sorted( + filter_alt_coherence_matches(results), key=lambda x: x[1], reverse=True + ) diff --git a/backend/venv/Lib/site-packages/charset_normalizer/cli/__init__.py b/backend/venv/Lib/site-packages/charset_normalizer/cli/__init__.py new file mode 100644 index 0000000..543a5a4 --- /dev/null +++ b/backend/venv/Lib/site-packages/charset_normalizer/cli/__init__.py @@ -0,0 +1,8 @@ +from __future__ import annotations + +from .__main__ import cli_detect, query_yes_no + +__all__ = ( + "cli_detect", + "query_yes_no", +) diff --git a/backend/venv/Lib/site-packages/charset_normalizer/cli/__main__.py b/backend/venv/Lib/site-packages/charset_normalizer/cli/__main__.py new file mode 100644 index 0000000..cb64156 --- /dev/null +++ b/backend/venv/Lib/site-packages/charset_normalizer/cli/__main__.py @@ -0,0 +1,381 @@ +from __future__ import annotations + +import argparse +import sys +import typing +from json import dumps +from os.path import abspath, basename, dirname, join, realpath +from platform import python_version +from unicodedata import unidata_version + +import charset_normalizer.md as md_module +from charset_normalizer import from_fp +from charset_normalizer.models import CliDetectionResult +from charset_normalizer.version import __version__ + + +def query_yes_no(question: str, default: str = "yes") -> bool: + """Ask a yes/no question via input() and return their answer. + + "question" is a string that is presented to the user. + "default" is the presumed answer if the user just hits . + It must be "yes" (the default), "no" or None (meaning + an answer is required of the user). + + The "answer" return value is True for "yes" or False for "no". + + Credit goes to (c) https://stackoverflow.com/questions/3041986/apt-command-line-interface-like-yes-no-input + """ + valid = {"yes": True, "y": True, "ye": True, "no": False, "n": False} + if default is None: + prompt = " [y/n] " + elif default == "yes": + prompt = " [Y/n] " + elif default == "no": + prompt = " [y/N] " + else: + raise ValueError("invalid default answer: '%s'" % default) + + while True: + sys.stdout.write(question + prompt) + choice = input().lower() + if default is not None and choice == "": + return valid[default] + elif choice in valid: + return valid[choice] + else: + sys.stdout.write("Please respond with 'yes' or 'no' (or 'y' or 'n').\n") + + +class FileType: + """Factory for creating file object types + + Instances of FileType are typically passed as type= arguments to the + ArgumentParser add_argument() method. + + Keyword Arguments: + - mode -- A string indicating how the file is to be opened. Accepts the + same values as the builtin open() function. + - bufsize -- The file's desired buffer size. Accepts the same values as + the builtin open() function. + - encoding -- The file's encoding. Accepts the same values as the + builtin open() function. + - errors -- A string indicating how encoding and decoding errors are to + be handled. Accepts the same value as the builtin open() function. + + Backported from CPython 3.12 + """ + + def __init__( + self, + mode: str = "r", + bufsize: int = -1, + encoding: str | None = None, + errors: str | None = None, + ): + self._mode = mode + self._bufsize = bufsize + self._encoding = encoding + self._errors = errors + + def __call__(self, string: str) -> typing.IO: # type: ignore[type-arg] + # the special argument "-" means sys.std{in,out} + if string == "-": + if "r" in self._mode: + return sys.stdin.buffer if "b" in self._mode else sys.stdin + elif any(c in self._mode for c in "wax"): + return sys.stdout.buffer if "b" in self._mode else sys.stdout + else: + msg = f'argument "-" with mode {self._mode}' + raise ValueError(msg) + + # all other arguments are used as file names + try: + return open(string, self._mode, self._bufsize, self._encoding, self._errors) + except OSError as e: + message = f"can't open '{string}': {e}" + raise argparse.ArgumentTypeError(message) + + def __repr__(self) -> str: + args = self._mode, self._bufsize + kwargs = [("encoding", self._encoding), ("errors", self._errors)] + args_str = ", ".join( + [repr(arg) for arg in args if arg != -1] + + [f"{kw}={arg!r}" for kw, arg in kwargs if arg is not None] + ) + return f"{type(self).__name__}({args_str})" + + +def cli_detect(argv: list[str] | None = None) -> int: + """ + CLI assistant using ARGV and ArgumentParser + :param argv: + :return: 0 if everything is fine, anything else equal trouble + """ + parser = argparse.ArgumentParser( + description="The Real First Universal Charset Detector. " + "Discover originating encoding used on text file. " + "Normalize text to unicode." + ) + + parser.add_argument( + "files", type=FileType("rb"), nargs="+", help="File(s) to be analysed" + ) + parser.add_argument( + "-v", + "--verbose", + action="store_true", + default=False, + dest="verbose", + help="Display complementary information about file if any. " + "Stdout will contain logs about the detection process.", + ) + parser.add_argument( + "-a", + "--with-alternative", + action="store_true", + default=False, + dest="alternatives", + help="Output complementary possibilities if any. Top-level JSON WILL be a list.", + ) + parser.add_argument( + "-n", + "--normalize", + action="store_true", + default=False, + dest="normalize", + help="Permit to normalize input file. If not set, program does not write anything.", + ) + parser.add_argument( + "-m", + "--minimal", + action="store_true", + default=False, + dest="minimal", + help="Only output the charset detected to STDOUT. Disabling JSON output.", + ) + parser.add_argument( + "-r", + "--replace", + action="store_true", + default=False, + dest="replace", + help="Replace file when trying to normalize it instead of creating a new one.", + ) + parser.add_argument( + "-f", + "--force", + action="store_true", + default=False, + dest="force", + help="Replace file without asking if you are sure, use this flag with caution.", + ) + parser.add_argument( + "-i", + "--no-preemptive", + action="store_true", + default=False, + dest="no_preemptive", + help="Disable looking at a charset declaration to hint the detector.", + ) + parser.add_argument( + "-t", + "--threshold", + action="store", + default=0.2, + type=float, + dest="threshold", + help="Define a custom maximum amount of noise allowed in decoded content. 0. <= noise <= 1.", + ) + parser.add_argument( + "--version", + action="version", + version="Charset-Normalizer {} - Python {} - Unicode {} - SpeedUp {}".format( + __version__, + python_version(), + unidata_version, + "OFF" if md_module.__file__.lower().endswith(".py") else "ON", + ), + help="Show version information and exit.", + ) + + args = parser.parse_args(argv) + + if args.replace is True and args.normalize is False: + if args.files: + for my_file in args.files: + my_file.close() + print("Use --replace in addition of --normalize only.", file=sys.stderr) + return 1 + + if args.force is True and args.replace is False: + if args.files: + for my_file in args.files: + my_file.close() + print("Use --force in addition of --replace only.", file=sys.stderr) + return 1 + + if args.threshold < 0.0 or args.threshold > 1.0: + if args.files: + for my_file in args.files: + my_file.close() + print("--threshold VALUE should be between 0. AND 1.", file=sys.stderr) + return 1 + + x_ = [] + + for my_file in args.files: + matches = from_fp( + my_file, + threshold=args.threshold, + explain=args.verbose, + preemptive_behaviour=args.no_preemptive is False, + ) + + best_guess = matches.best() + + if best_guess is None: + print( + 'Unable to identify originating encoding for "{}". {}'.format( + my_file.name, + ( + "Maybe try increasing maximum amount of chaos." + if args.threshold < 1.0 + else "" + ), + ), + file=sys.stderr, + ) + x_.append( + CliDetectionResult( + abspath(my_file.name), + None, + [], + [], + "Unknown", + [], + False, + 1.0, + 0.0, + None, + True, + ) + ) + else: + x_.append( + CliDetectionResult( + abspath(my_file.name), + best_guess.encoding, + best_guess.encoding_aliases, + [ + cp + for cp in best_guess.could_be_from_charset + if cp != best_guess.encoding + ], + best_guess.language, + best_guess.alphabets, + best_guess.bom, + best_guess.percent_chaos, + best_guess.percent_coherence, + None, + True, + ) + ) + + if len(matches) > 1 and args.alternatives: + for el in matches: + if el != best_guess: + x_.append( + CliDetectionResult( + abspath(my_file.name), + el.encoding, + el.encoding_aliases, + [ + cp + for cp in el.could_be_from_charset + if cp != el.encoding + ], + el.language, + el.alphabets, + el.bom, + el.percent_chaos, + el.percent_coherence, + None, + False, + ) + ) + + if args.normalize is True: + if best_guess.encoding.startswith("utf") is True: + print( + '"{}" file does not need to be normalized, as it already came from unicode.'.format( + my_file.name + ), + file=sys.stderr, + ) + if my_file.closed is False: + my_file.close() + continue + + dir_path = dirname(realpath(my_file.name)) + file_name = basename(realpath(my_file.name)) + + o_: list[str] = file_name.split(".") + + if args.replace is False: + o_.insert(-1, best_guess.encoding) + if my_file.closed is False: + my_file.close() + elif ( + args.force is False + and query_yes_no( + 'Are you sure to normalize "{}" by replacing it ?'.format( + my_file.name + ), + "no", + ) + is False + ): + if my_file.closed is False: + my_file.close() + continue + + try: + x_[0].unicode_path = join(dir_path, ".".join(o_)) + + with open(x_[0].unicode_path, "wb") as fp: + fp.write(best_guess.output()) + except OSError as e: + print(str(e), file=sys.stderr) + if my_file.closed is False: + my_file.close() + return 2 + + if my_file.closed is False: + my_file.close() + + if args.minimal is False: + print( + dumps( + [el.__dict__ for el in x_] if len(x_) > 1 else x_[0].__dict__, + ensure_ascii=True, + indent=4, + ) + ) + else: + for my_file in args.files: + print( + ", ".join( + [ + el.encoding or "undefined" + for el in x_ + if el.path == abspath(my_file.name) + ] + ) + ) + + return 0 + + +if __name__ == "__main__": + cli_detect() diff --git a/backend/venv/Lib/site-packages/charset_normalizer/cli/__pycache__/__init__.cpython-312.pyc b/backend/venv/Lib/site-packages/charset_normalizer/cli/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..86d98a857c06835d77232025b1e1b93e4ac19e7f GIT binary patch literal 354 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 literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/charset_normalizer/constant.py b/backend/venv/Lib/site-packages/charset_normalizer/constant.py new file mode 100644 index 0000000..cc71a01 --- /dev/null +++ b/backend/venv/Lib/site-packages/charset_normalizer/constant.py @@ -0,0 +1,2015 @@ +from __future__ import annotations + +from codecs import BOM_UTF8, BOM_UTF16_BE, BOM_UTF16_LE, BOM_UTF32_BE, BOM_UTF32_LE +from encodings.aliases import aliases +from re import IGNORECASE +from re import compile as re_compile + +# Contain for each eligible encoding a list of/item bytes SIG/BOM +ENCODING_MARKS: dict[str, bytes | list[bytes]] = { + "utf_8": BOM_UTF8, + "utf_7": [ + b"\x2b\x2f\x76\x38", + b"\x2b\x2f\x76\x39", + b"\x2b\x2f\x76\x2b", + b"\x2b\x2f\x76\x2f", + b"\x2b\x2f\x76\x38\x2d", + ], + "gb18030": b"\x84\x31\x95\x33", + "utf_32": [BOM_UTF32_BE, BOM_UTF32_LE], + "utf_16": [BOM_UTF16_BE, BOM_UTF16_LE], +} + +TOO_SMALL_SEQUENCE: int = 32 +TOO_BIG_SEQUENCE: int = int(10e6) + +UTF8_MAXIMAL_ALLOCATION: int = 1_112_064 + +# Up-to-date Unicode ucd/15.0.0 +UNICODE_RANGES_COMBINED: dict[str, range] = { + "Control character": range(32), + "Basic Latin": range(32, 128), + "Latin-1 Supplement": range(128, 256), + "Latin Extended-A": range(256, 384), + "Latin Extended-B": range(384, 592), + "IPA Extensions": range(592, 688), + "Spacing Modifier Letters": range(688, 768), + "Combining Diacritical Marks": range(768, 880), + "Greek and Coptic": range(880, 1024), + "Cyrillic": range(1024, 1280), + "Cyrillic Supplement": range(1280, 1328), + "Armenian": range(1328, 1424), + "Hebrew": range(1424, 1536), + "Arabic": range(1536, 1792), + "Syriac": range(1792, 1872), + "Arabic Supplement": range(1872, 1920), + "Thaana": range(1920, 1984), + "NKo": range(1984, 2048), + "Samaritan": range(2048, 2112), + "Mandaic": range(2112, 2144), + "Syriac Supplement": range(2144, 2160), + "Arabic Extended-B": range(2160, 2208), + "Arabic Extended-A": range(2208, 2304), + "Devanagari": range(2304, 2432), + "Bengali": range(2432, 2560), + "Gurmukhi": range(2560, 2688), + "Gujarati": range(2688, 2816), + "Oriya": range(2816, 2944), + "Tamil": range(2944, 3072), + "Telugu": range(3072, 3200), + "Kannada": range(3200, 3328), + "Malayalam": range(3328, 3456), + "Sinhala": range(3456, 3584), + "Thai": range(3584, 3712), + "Lao": range(3712, 3840), + "Tibetan": range(3840, 4096), + "Myanmar": range(4096, 4256), + "Georgian": range(4256, 4352), + "Hangul Jamo": range(4352, 4608), + "Ethiopic": range(4608, 4992), + "Ethiopic Supplement": range(4992, 5024), + "Cherokee": range(5024, 5120), + "Unified Canadian Aboriginal Syllabics": range(5120, 5760), + "Ogham": range(5760, 5792), + "Runic": range(5792, 5888), + "Tagalog": range(5888, 5920), + "Hanunoo": range(5920, 5952), + "Buhid": range(5952, 5984), + "Tagbanwa": range(5984, 6016), + "Khmer": range(6016, 6144), + "Mongolian": range(6144, 6320), + "Unified Canadian Aboriginal Syllabics Extended": range(6320, 6400), + "Limbu": range(6400, 6480), + "Tai Le": range(6480, 6528), + "New Tai Lue": range(6528, 6624), + "Khmer Symbols": range(6624, 6656), + "Buginese": range(6656, 6688), + "Tai Tham": range(6688, 6832), + "Combining Diacritical Marks Extended": range(6832, 6912), + "Balinese": range(6912, 7040), + "Sundanese": range(7040, 7104), + "Batak": range(7104, 7168), + "Lepcha": range(7168, 7248), + "Ol Chiki": range(7248, 7296), + "Cyrillic Extended-C": range(7296, 7312), + "Georgian Extended": range(7312, 7360), + "Sundanese Supplement": range(7360, 7376), + "Vedic Extensions": range(7376, 7424), + "Phonetic Extensions": range(7424, 7552), + "Phonetic Extensions Supplement": range(7552, 7616), + "Combining Diacritical Marks Supplement": range(7616, 7680), + "Latin Extended Additional": range(7680, 7936), + "Greek Extended": range(7936, 8192), + "General Punctuation": range(8192, 8304), + "Superscripts and Subscripts": range(8304, 8352), + "Currency Symbols": range(8352, 8400), + "Combining Diacritical Marks for Symbols": range(8400, 8448), + "Letterlike Symbols": range(8448, 8528), + "Number Forms": range(8528, 8592), + "Arrows": range(8592, 8704), + "Mathematical Operators": range(8704, 8960), + "Miscellaneous Technical": range(8960, 9216), + "Control Pictures": range(9216, 9280), + "Optical Character Recognition": range(9280, 9312), + "Enclosed Alphanumerics": range(9312, 9472), + "Box Drawing": range(9472, 9600), + "Block Elements": range(9600, 9632), + "Geometric Shapes": range(9632, 9728), + "Miscellaneous Symbols": range(9728, 9984), + "Dingbats": range(9984, 10176), + "Miscellaneous Mathematical Symbols-A": range(10176, 10224), + "Supplemental Arrows-A": range(10224, 10240), + "Braille Patterns": range(10240, 10496), + "Supplemental Arrows-B": range(10496, 10624), + "Miscellaneous Mathematical Symbols-B": range(10624, 10752), + "Supplemental Mathematical Operators": range(10752, 11008), + "Miscellaneous Symbols and Arrows": range(11008, 11264), + "Glagolitic": range(11264, 11360), + "Latin Extended-C": range(11360, 11392), + "Coptic": range(11392, 11520), + "Georgian Supplement": range(11520, 11568), + "Tifinagh": range(11568, 11648), + "Ethiopic Extended": range(11648, 11744), + "Cyrillic Extended-A": range(11744, 11776), + "Supplemental Punctuation": range(11776, 11904), + "CJK Radicals Supplement": range(11904, 12032), + "Kangxi Radicals": range(12032, 12256), + "Ideographic Description Characters": range(12272, 12288), + "CJK Symbols and Punctuation": range(12288, 12352), + "Hiragana": range(12352, 12448), + "Katakana": range(12448, 12544), + "Bopomofo": range(12544, 12592), + "Hangul Compatibility Jamo": range(12592, 12688), + "Kanbun": range(12688, 12704), + "Bopomofo Extended": range(12704, 12736), + "CJK Strokes": range(12736, 12784), + "Katakana Phonetic Extensions": range(12784, 12800), + "Enclosed CJK Letters and Months": range(12800, 13056), + "CJK Compatibility": range(13056, 13312), + "CJK Unified Ideographs Extension A": range(13312, 19904), + "Yijing Hexagram Symbols": range(19904, 19968), + "CJK Unified Ideographs": range(19968, 40960), + "Yi Syllables": range(40960, 42128), + "Yi Radicals": range(42128, 42192), + "Lisu": range(42192, 42240), + "Vai": range(42240, 42560), + "Cyrillic Extended-B": range(42560, 42656), + "Bamum": range(42656, 42752), + "Modifier Tone Letters": range(42752, 42784), + "Latin Extended-D": range(42784, 43008), + "Syloti Nagri": range(43008, 43056), + "Common Indic Number Forms": range(43056, 43072), + "Phags-pa": range(43072, 43136), + "Saurashtra": range(43136, 43232), + "Devanagari Extended": range(43232, 43264), + "Kayah Li": range(43264, 43312), + "Rejang": range(43312, 43360), + "Hangul Jamo Extended-A": range(43360, 43392), + "Javanese": range(43392, 43488), + "Myanmar Extended-B": range(43488, 43520), + "Cham": range(43520, 43616), + "Myanmar Extended-A": range(43616, 43648), + "Tai Viet": range(43648, 43744), + "Meetei Mayek Extensions": range(43744, 43776), + "Ethiopic Extended-A": range(43776, 43824), + "Latin Extended-E": range(43824, 43888), + "Cherokee Supplement": range(43888, 43968), + "Meetei Mayek": range(43968, 44032), + "Hangul Syllables": range(44032, 55216), + "Hangul Jamo Extended-B": range(55216, 55296), + "High Surrogates": range(55296, 56192), + "High Private Use Surrogates": range(56192, 56320), + "Low Surrogates": range(56320, 57344), + "Private Use Area": range(57344, 63744), + "CJK Compatibility Ideographs": range(63744, 64256), + "Alphabetic Presentation Forms": range(64256, 64336), + "Arabic Presentation Forms-A": range(64336, 65024), + "Variation Selectors": range(65024, 65040), + "Vertical Forms": range(65040, 65056), + "Combining Half Marks": range(65056, 65072), + "CJK Compatibility Forms": range(65072, 65104), + "Small Form Variants": range(65104, 65136), + "Arabic Presentation Forms-B": range(65136, 65280), + "Halfwidth and Fullwidth Forms": range(65280, 65520), + "Specials": range(65520, 65536), + "Linear B Syllabary": range(65536, 65664), + "Linear B Ideograms": range(65664, 65792), + "Aegean Numbers": range(65792, 65856), + "Ancient Greek Numbers": range(65856, 65936), + "Ancient Symbols": range(65936, 66000), + "Phaistos Disc": range(66000, 66048), + "Lycian": range(66176, 66208), + "Carian": range(66208, 66272), + "Coptic Epact Numbers": range(66272, 66304), + "Old Italic": range(66304, 66352), + "Gothic": range(66352, 66384), + "Old Permic": range(66384, 66432), + "Ugaritic": range(66432, 66464), + "Old Persian": range(66464, 66528), + "Deseret": range(66560, 66640), + "Shavian": range(66640, 66688), + "Osmanya": range(66688, 66736), + "Osage": range(66736, 66816), + "Elbasan": range(66816, 66864), + "Caucasian Albanian": range(66864, 66928), + "Vithkuqi": range(66928, 67008), + "Linear A": range(67072, 67456), + "Latin Extended-F": range(67456, 67520), + "Cypriot Syllabary": range(67584, 67648), + "Imperial Aramaic": range(67648, 67680), + "Palmyrene": range(67680, 67712), + "Nabataean": range(67712, 67760), + "Hatran": range(67808, 67840), + "Phoenician": range(67840, 67872), + "Lydian": range(67872, 67904), + "Meroitic Hieroglyphs": range(67968, 68000), + "Meroitic Cursive": range(68000, 68096), + "Kharoshthi": range(68096, 68192), + "Old South Arabian": range(68192, 68224), + "Old North Arabian": range(68224, 68256), + "Manichaean": range(68288, 68352), + "Avestan": range(68352, 68416), + "Inscriptional Parthian": range(68416, 68448), + "Inscriptional Pahlavi": range(68448, 68480), + "Psalter Pahlavi": range(68480, 68528), + "Old Turkic": range(68608, 68688), + "Old Hungarian": range(68736, 68864), + "Hanifi Rohingya": range(68864, 68928), + "Rumi Numeral Symbols": range(69216, 69248), + "Yezidi": range(69248, 69312), + "Arabic Extended-C": range(69312, 69376), + "Old Sogdian": range(69376, 69424), + "Sogdian": range(69424, 69488), + "Old Uyghur": range(69488, 69552), + "Chorasmian": range(69552, 69600), + "Elymaic": range(69600, 69632), + "Brahmi": range(69632, 69760), + "Kaithi": range(69760, 69840), + "Sora Sompeng": range(69840, 69888), + "Chakma": range(69888, 69968), + "Mahajani": range(69968, 70016), + "Sharada": range(70016, 70112), + "Sinhala Archaic Numbers": range(70112, 70144), + "Khojki": range(70144, 70224), + "Multani": range(70272, 70320), + "Khudawadi": range(70320, 70400), + "Grantha": range(70400, 70528), + "Newa": range(70656, 70784), + "Tirhuta": range(70784, 70880), + "Siddham": range(71040, 71168), + "Modi": range(71168, 71264), + "Mongolian Supplement": range(71264, 71296), + "Takri": range(71296, 71376), + "Ahom": range(71424, 71504), + "Dogra": range(71680, 71760), + "Warang Citi": range(71840, 71936), + "Dives Akuru": range(71936, 72032), + "Nandinagari": range(72096, 72192), + "Zanabazar Square": range(72192, 72272), + "Soyombo": range(72272, 72368), + "Unified Canadian Aboriginal Syllabics Extended-A": range(72368, 72384), + "Pau Cin Hau": range(72384, 72448), + "Devanagari Extended-A": range(72448, 72544), + "Bhaiksuki": range(72704, 72816), + "Marchen": range(72816, 72896), + "Masaram Gondi": range(72960, 73056), + "Gunjala Gondi": range(73056, 73136), + "Makasar": range(73440, 73472), + "Kawi": range(73472, 73568), + "Lisu Supplement": range(73648, 73664), + "Tamil Supplement": range(73664, 73728), + "Cuneiform": range(73728, 74752), + "Cuneiform Numbers and Punctuation": range(74752, 74880), + "Early Dynastic Cuneiform": range(74880, 75088), + "Cypro-Minoan": range(77712, 77824), + "Egyptian Hieroglyphs": range(77824, 78896), + "Egyptian Hieroglyph Format Controls": range(78896, 78944), + "Anatolian Hieroglyphs": range(82944, 83584), + "Bamum Supplement": range(92160, 92736), + "Mro": range(92736, 92784), + "Tangsa": range(92784, 92880), + "Bassa Vah": range(92880, 92928), + "Pahawh Hmong": range(92928, 93072), + "Medefaidrin": range(93760, 93856), + "Miao": range(93952, 94112), + "Ideographic Symbols and Punctuation": range(94176, 94208), + "Tangut": range(94208, 100352), + "Tangut Components": range(100352, 101120), + "Khitan Small Script": range(101120, 101632), + "Tangut Supplement": range(101632, 101760), + "Kana Extended-B": range(110576, 110592), + "Kana Supplement": range(110592, 110848), + "Kana Extended-A": range(110848, 110896), + "Small Kana Extension": range(110896, 110960), + "Nushu": range(110960, 111360), + "Duployan": range(113664, 113824), + "Shorthand Format Controls": range(113824, 113840), + "Znamenny Musical Notation": range(118528, 118736), + "Byzantine Musical Symbols": range(118784, 119040), + "Musical Symbols": range(119040, 119296), + "Ancient Greek Musical Notation": range(119296, 119376), + "Kaktovik Numerals": range(119488, 119520), + "Mayan Numerals": range(119520, 119552), + "Tai Xuan Jing Symbols": range(119552, 119648), + "Counting Rod Numerals": range(119648, 119680), + "Mathematical Alphanumeric Symbols": range(119808, 120832), + "Sutton SignWriting": range(120832, 121520), + "Latin Extended-G": range(122624, 122880), + "Glagolitic Supplement": range(122880, 122928), + "Cyrillic Extended-D": range(122928, 123024), + "Nyiakeng Puachue Hmong": range(123136, 123216), + "Toto": range(123536, 123584), + "Wancho": range(123584, 123648), + "Nag Mundari": range(124112, 124160), + "Ethiopic Extended-B": range(124896, 124928), + "Mende Kikakui": range(124928, 125152), + "Adlam": range(125184, 125280), + "Indic Siyaq Numbers": range(126064, 126144), + "Ottoman Siyaq Numbers": range(126208, 126288), + "Arabic Mathematical Alphabetic Symbols": range(126464, 126720), + "Mahjong Tiles": range(126976, 127024), + "Domino Tiles": range(127024, 127136), + "Playing Cards": range(127136, 127232), + "Enclosed Alphanumeric Supplement": range(127232, 127488), + "Enclosed Ideographic Supplement": range(127488, 127744), + "Miscellaneous Symbols and Pictographs": range(127744, 128512), + "Emoticons range(Emoji)": range(128512, 128592), + "Ornamental Dingbats": range(128592, 128640), + "Transport and Map Symbols": range(128640, 128768), + "Alchemical Symbols": range(128768, 128896), + "Geometric Shapes Extended": range(128896, 129024), + "Supplemental Arrows-C": range(129024, 129280), + "Supplemental Symbols and Pictographs": range(129280, 129536), + "Chess Symbols": range(129536, 129648), + "Symbols and Pictographs Extended-A": range(129648, 129792), + "Symbols for Legacy Computing": range(129792, 130048), + "CJK Unified Ideographs Extension B": range(131072, 173792), + "CJK Unified Ideographs Extension C": range(173824, 177984), + "CJK Unified Ideographs Extension D": range(177984, 178208), + "CJK Unified Ideographs Extension E": range(178208, 183984), + "CJK Unified Ideographs Extension F": range(183984, 191472), + "CJK Compatibility Ideographs Supplement": range(194560, 195104), + "CJK Unified Ideographs Extension G": range(196608, 201552), + "CJK Unified Ideographs Extension H": range(201552, 205744), + "Tags": range(917504, 917632), + "Variation Selectors Supplement": range(917760, 918000), + "Supplementary Private Use Area-A": range(983040, 1048576), + "Supplementary Private Use Area-B": range(1048576, 1114112), +} + + +UNICODE_SECONDARY_RANGE_KEYWORD: list[str] = [ + "Supplement", + "Extended", + "Extensions", + "Modifier", + "Marks", + "Punctuation", + "Symbols", + "Forms", + "Operators", + "Miscellaneous", + "Drawing", + "Block", + "Shapes", + "Supplemental", + "Tags", +] + +RE_POSSIBLE_ENCODING_INDICATION = re_compile( + r"(?:(?:encoding)|(?:charset)|(?:coding))(?:[\:= ]{1,10})(?:[\"\']?)([a-zA-Z0-9\-_]+)(?:[\"\']?)", + IGNORECASE, +) + +IANA_NO_ALIASES = [ + "cp720", + "cp737", + "cp856", + "cp874", + "cp875", + "cp1006", + "koi8_r", + "koi8_t", + "koi8_u", +] + +IANA_SUPPORTED: list[str] = sorted( + filter( + lambda x: x.endswith("_codec") is False + and x not in {"rot_13", "tactis", "mbcs"}, + list(set(aliases.values())) + IANA_NO_ALIASES, + ) +) + +IANA_SUPPORTED_COUNT: int = len(IANA_SUPPORTED) + +# pre-computed code page that are similar using the function cp_similarity. +IANA_SUPPORTED_SIMILAR: dict[str, list[str]] = { + "cp037": ["cp1026", "cp1140", "cp273", "cp500"], + "cp1026": ["cp037", "cp1140", "cp273", "cp500"], + "cp1125": ["cp866"], + "cp1140": ["cp037", "cp1026", "cp273", "cp500"], + "cp1250": ["iso8859_2"], + "cp1251": ["kz1048", "ptcp154"], + "cp1252": ["iso8859_15", "iso8859_9", "latin_1"], + "cp1253": ["iso8859_7"], + "cp1254": ["iso8859_15", "iso8859_9", "latin_1"], + "cp1257": ["iso8859_13"], + "cp273": ["cp037", "cp1026", "cp1140", "cp500"], + "cp437": ["cp850", "cp858", "cp860", "cp861", "cp862", "cp863", "cp865"], + "cp500": ["cp037", "cp1026", "cp1140", "cp273"], + "cp850": ["cp437", "cp857", "cp858", "cp865"], + "cp857": ["cp850", "cp858", "cp865"], + "cp858": ["cp437", "cp850", "cp857", "cp865"], + "cp860": ["cp437", "cp861", "cp862", "cp863", "cp865"], + "cp861": ["cp437", "cp860", "cp862", "cp863", "cp865"], + "cp862": ["cp437", "cp860", "cp861", "cp863", "cp865"], + "cp863": ["cp437", "cp860", "cp861", "cp862", "cp865"], + "cp865": ["cp437", "cp850", "cp857", "cp858", "cp860", "cp861", "cp862", "cp863"], + "cp866": ["cp1125"], + "iso8859_10": ["iso8859_14", "iso8859_15", "iso8859_4", "iso8859_9", "latin_1"], + "iso8859_11": ["tis_620"], + "iso8859_13": ["cp1257"], + "iso8859_14": [ + "iso8859_10", + "iso8859_15", + "iso8859_16", + "iso8859_3", + "iso8859_9", + "latin_1", + ], + "iso8859_15": [ + "cp1252", + "cp1254", + "iso8859_10", + "iso8859_14", + "iso8859_16", + "iso8859_3", + "iso8859_9", + "latin_1", + ], + "iso8859_16": [ + "iso8859_14", + "iso8859_15", + "iso8859_2", + "iso8859_3", + "iso8859_9", + "latin_1", + ], + "iso8859_2": ["cp1250", "iso8859_16", "iso8859_4"], + "iso8859_3": ["iso8859_14", "iso8859_15", "iso8859_16", "iso8859_9", "latin_1"], + "iso8859_4": ["iso8859_10", "iso8859_2", "iso8859_9", "latin_1"], + "iso8859_7": ["cp1253"], + "iso8859_9": [ + "cp1252", + "cp1254", + "cp1258", + "iso8859_10", + "iso8859_14", + "iso8859_15", + "iso8859_16", + "iso8859_3", + "iso8859_4", + "latin_1", + ], + "kz1048": ["cp1251", "ptcp154"], + "latin_1": [ + "cp1252", + "cp1254", + "cp1258", + "iso8859_10", + "iso8859_14", + "iso8859_15", + "iso8859_16", + "iso8859_3", + "iso8859_4", + "iso8859_9", + ], + "mac_iceland": ["mac_roman", "mac_turkish"], + "mac_roman": ["mac_iceland", "mac_turkish"], + "mac_turkish": ["mac_iceland", "mac_roman"], + "ptcp154": ["cp1251", "kz1048"], + "tis_620": ["iso8859_11"], +} + + +CHARDET_CORRESPONDENCE: dict[str, str] = { + "iso2022_kr": "ISO-2022-KR", + "iso2022_jp": "ISO-2022-JP", + "euc_kr": "EUC-KR", + "tis_620": "TIS-620", + "utf_32": "UTF-32", + "euc_jp": "EUC-JP", + "koi8_r": "KOI8-R", + "iso8859_1": "ISO-8859-1", + "iso8859_2": "ISO-8859-2", + "iso8859_5": "ISO-8859-5", + "iso8859_6": "ISO-8859-6", + "iso8859_7": "ISO-8859-7", + "iso8859_8": "ISO-8859-8", + "utf_16": "UTF-16", + "cp855": "IBM855", + "mac_cyrillic": "MacCyrillic", + "gb2312": "GB2312", + "gb18030": "GB18030", + "cp932": "CP932", + "cp866": "IBM866", + "utf_8": "utf-8", + "utf_8_sig": "UTF-8-SIG", + "shift_jis": "SHIFT_JIS", + "big5": "Big5", + "cp1250": "windows-1250", + "cp1251": "windows-1251", + "cp1252": "Windows-1252", + "cp1253": "windows-1253", + "cp1255": "windows-1255", + "cp1256": "windows-1256", + "cp1254": "Windows-1254", + "cp949": "CP949", +} + + +COMMON_SAFE_ASCII_CHARACTERS: set[str] = { + "<", + ">", + "=", + ":", + "/", + "&", + ";", + "{", + "}", + "[", + "]", + ",", + "|", + '"', + "-", + "(", + ")", +} + +# Sample character sets — replace with full lists if needed +COMMON_CHINESE_CHARACTERS = "的一是在不了有和人这中大为上个国我以要他时来用们生到作地于出就分对成会可主发年动同工也能下过子说产种面而方后多定行学法所民得经十三之进着等部度家电力里如水化高自二理起小物现实加量都两体制机当使点从业本去把性好应开它合还因由其些然前外天政四日那社义事平形相全表间样与关各重新线内数正心反你明看原又么利比或但质气第向道命此变条只没结解问意建月公无系军很情者最立代想已通并提直题党程展五果料象员革位入常文总次品式活设及管特件长求老头基资边流路级少图山统接知较将组见计别她手角期根论运农指几九区强放决西被干做必战先回则任取据处队南给色光门即保治北造百规热领七海口东导器压志世金增争济阶油思术极交受联什认六共权收证改清己美再采转更单风切打白教速花带安场身车例真务具万每目至达走积示议声报斗完类八离华名确才科张信马节话米整空元况今集温传土许步群广石记需段研界拉林律叫且究观越织装影算低持音众书布复容儿须际商非验连断深难近矿千周委素技备半办青省列习响约支般史感劳便团往酸历市克何除消构府太准精值号率族维划选标写存候毛亲快效斯院查江型眼王按格养易置派层片始却专状育厂京识适属圆包火住调满县局照参红细引听该铁价严龙飞" + +COMMON_JAPANESE_CHARACTERS = "日一国年大十二本中長出三時行見月分後前生五間上東四今金九入学高円子外八六下来気小七山話女北午百書先名川千水半男西電校語土木聞食車何南万毎白天母火右読友左休父雨" + +COMMON_KOREAN_CHARACTERS = "一二三四五六七八九十百千萬上下左右中人女子大小山川日月火水木金土父母天地國名年時文校學生" + +# Combine all into a set +COMMON_CJK_CHARACTERS = set( + "".join( + [ + COMMON_CHINESE_CHARACTERS, + COMMON_JAPANESE_CHARACTERS, + COMMON_KOREAN_CHARACTERS, + ] + ) +) + +KO_NAMES: set[str] = {"johab", "cp949", "euc_kr"} +ZH_NAMES: set[str] = {"big5", "cp950", "big5hkscs", "hz"} + +# Logging LEVEL below DEBUG +TRACE: int = 5 + + +# Language label that contain the em dash "—" +# character are to be considered alternative seq to origin +FREQUENCIES: dict[str, list[str]] = { + "English": [ + "e", + "a", + "t", + "i", + "o", + "n", + "s", + "r", + "h", + "l", + "d", + "c", + "u", + "m", + "f", + "p", + "g", + "w", + "y", + "b", + "v", + "k", + "x", + "j", + "z", + "q", + ], + "English—": [ + "e", + "a", + "t", + "i", + "o", + "n", + "s", + "r", + "h", + "l", + "d", + "c", + "m", + "u", + "f", + "p", + "g", + "w", + "b", + "y", + "v", + "k", + "j", + "x", + "z", + "q", + ], + "German": [ + "e", + "n", + "i", + "r", + "s", + "t", + "a", + "d", + "h", + "u", + "l", + "g", + "o", + "c", + "m", + "b", + "f", + "k", + "w", + "z", + "p", + "v", + "ü", + "ä", + "ö", + "j", + ], + "French": [ + "e", + "a", + "s", + "n", + "i", + "t", + "r", + "l", + "u", + "o", + "d", + "c", + "p", + "m", + "é", + "v", + "g", + "f", + "b", + "h", + "q", + "à", + "x", + "è", + "y", + "j", + ], + "Dutch": [ + "e", + "n", + "a", + "i", + "r", + "t", + "o", + "d", + "s", + "l", + "g", + "h", + "v", + "m", + "u", + "k", + "c", + "p", + "b", + "w", + "j", + "z", + "f", + "y", + "x", + "ë", + ], + "Italian": [ + "e", + "i", + "a", + "o", + "n", + "l", + "t", + "r", + "s", + "c", + "d", + "u", + "p", + "m", + "g", + "v", + "f", + "b", + "z", + "h", + "q", + "è", + "à", + "k", + "y", + "ò", + ], + "Polish": [ + "a", + "i", + "o", + "e", + "n", + "r", + "z", + "w", + "s", + "c", + "t", + "k", + "y", + "d", + "p", + "m", + "u", + "l", + "j", + "ł", + "g", + "b", + "h", + "ą", + "ę", + "ó", + ], + "Spanish": [ + "e", + "a", + "o", + "n", + "s", + "r", + "i", + "l", + "d", + "t", + "c", + "u", + "m", + "p", + "b", + "g", + "v", + "f", + "y", + "ó", + "h", + "q", + "í", + "j", + "z", + "á", + ], + "Russian": [ + "о", + "а", + "е", + "и", + "н", + "с", + "т", + "р", + "в", + "л", + "к", + "м", + "д", + "п", + "у", + "г", + "я", + "ы", + "з", + "б", + "й", + "ь", + "ч", + "х", + "ж", + "ц", + ], + # Jap-Kanji + "Japanese": [ + "人", + "一", + "大", + "亅", + "丁", + "丨", + "竹", + "笑", + "口", + "日", + "今", + "二", + "彳", + "行", + "十", + "土", + "丶", + "寸", + "寺", + "時", + "乙", + "丿", + "乂", + "气", + "気", + "冂", + "巾", + "亠", + "市", + "目", + "儿", + "見", + "八", + "小", + "凵", + "県", + "月", + "彐", + "門", + "間", + "木", + "東", + "山", + "出", + "本", + "中", + "刀", + "分", + "耳", + "又", + "取", + "最", + "言", + "田", + "心", + "思", + "刂", + "前", + "京", + "尹", + "事", + "生", + "厶", + "云", + "会", + "未", + "来", + "白", + "冫", + "楽", + "灬", + "馬", + "尸", + "尺", + "駅", + "明", + "耂", + "者", + "了", + "阝", + "都", + "高", + "卜", + "占", + "厂", + "广", + "店", + "子", + "申", + "奄", + "亻", + "俺", + "上", + "方", + "冖", + "学", + "衣", + "艮", + "食", + "自", + ], + # Jap-Katakana + "Japanese—": [ + "ー", + "ン", + "ス", + "・", + "ル", + "ト", + "リ", + "イ", + "ア", + "ラ", + "ッ", + "ク", + "ド", + "シ", + "レ", + "ジ", + "タ", + "フ", + "ロ", + "カ", + "テ", + "マ", + "ィ", + "グ", + "バ", + "ム", + "プ", + "オ", + "コ", + "デ", + "ニ", + "ウ", + "メ", + "サ", + "ビ", + "ナ", + "ブ", + "ャ", + "エ", + "ュ", + "チ", + "キ", + "ズ", + "ダ", + "パ", + "ミ", + "ェ", + "ョ", + "ハ", + "セ", + "ベ", + "ガ", + "モ", + "ツ", + "ネ", + "ボ", + "ソ", + "ノ", + "ァ", + "ヴ", + "ワ", + "ポ", + "ペ", + "ピ", + "ケ", + "ゴ", + "ギ", + "ザ", + "ホ", + "ゲ", + "ォ", + "ヤ", + "ヒ", + "ユ", + "ヨ", + "ヘ", + "ゼ", + "ヌ", + "ゥ", + "ゾ", + "ヶ", + "ヂ", + "ヲ", + "ヅ", + "ヵ", + "ヱ", + "ヰ", + "ヮ", + "ヽ", + "゠", + "ヾ", + "ヷ", + "ヿ", + "ヸ", + "ヹ", + "ヺ", + ], + # Jap-Hiragana + "Japanese——": [ + "の", + "に", + "る", + "た", + "と", + "は", + "し", + "い", + "を", + "で", + "て", + "が", + "な", + "れ", + "か", + "ら", + "さ", + "っ", + "り", + "す", + "あ", + "も", + "こ", + "ま", + "う", + "く", + "よ", + "き", + "ん", + "め", + "お", + "け", + "そ", + "つ", + "だ", + "や", + "え", + "ど", + "わ", + "ち", + "み", + "せ", + "じ", + "ば", + "へ", + "び", + "ず", + "ろ", + "ほ", + "げ", + "む", + "べ", + "ひ", + "ょ", + "ゆ", + "ぶ", + "ご", + "ゃ", + "ね", + "ふ", + "ぐ", + "ぎ", + "ぼ", + "ゅ", + "づ", + "ざ", + "ぞ", + "ぬ", + "ぜ", + "ぱ", + "ぽ", + "ぷ", + "ぴ", + "ぃ", + "ぁ", + "ぇ", + "ぺ", + "ゞ", + "ぢ", + "ぉ", + "ぅ", + "ゐ", + "ゝ", + "ゑ", + "゛", + "゜", + "ゎ", + "ゔ", + "゚", + "ゟ", + "゙", + "ゕ", + "ゖ", + ], + "Portuguese": [ + "a", + "e", + "o", + "s", + "i", + "r", + "d", + "n", + "t", + "m", + "u", + "c", + "l", + "p", + "g", + "v", + "b", + "f", + "h", + "ã", + "q", + "é", + "ç", + "á", + "z", + "í", + ], + "Swedish": [ + "e", + "a", + "n", + "r", + "t", + "s", + "i", + "l", + "d", + "o", + "m", + "k", + "g", + "v", + "h", + "f", + "u", + "p", + "ä", + "c", + "b", + "ö", + "å", + "y", + "j", + "x", + ], + "Chinese": [ + "的", + "一", + "是", + "不", + "了", + "在", + "人", + "有", + "我", + "他", + "这", + "个", + "们", + "中", + "来", + "上", + "大", + "为", + "和", + "国", + "地", + "到", + "以", + "说", + "时", + "要", + "就", + "出", + "会", + "可", + "也", + "你", + "对", + "生", + "能", + "而", + "子", + "那", + "得", + "于", + "着", + "下", + "自", + "之", + "年", + "过", + "发", + "后", + "作", + "里", + "用", + "道", + "行", + "所", + "然", + "家", + "种", + "事", + "成", + "方", + "多", + "经", + "么", + "去", + "法", + "学", + "如", + "都", + "同", + "现", + "当", + "没", + "动", + "面", + "起", + "看", + "定", + "天", + "分", + "还", + "进", + "好", + "小", + "部", + "其", + "些", + "主", + "样", + "理", + "心", + "她", + "本", + "前", + "开", + "但", + "因", + "只", + "从", + "想", + "实", + ], + "Ukrainian": [ + "о", + "а", + "н", + "і", + "и", + "р", + "в", + "т", + "е", + "с", + "к", + "л", + "у", + "д", + "м", + "п", + "з", + "я", + "ь", + "б", + "г", + "й", + "ч", + "х", + "ц", + "ї", + ], + "Norwegian": [ + "e", + "r", + "n", + "t", + "a", + "s", + "i", + "o", + "l", + "d", + "g", + "k", + "m", + "v", + "f", + "p", + "u", + "b", + "h", + "å", + "y", + "j", + "ø", + "c", + "æ", + "w", + ], + "Finnish": [ + "a", + "i", + "n", + "t", + "e", + "s", + "l", + "o", + "u", + "k", + "ä", + "m", + "r", + "v", + "j", + "h", + "p", + "y", + "d", + "ö", + "g", + "c", + "b", + "f", + "w", + "z", + ], + "Vietnamese": [ + "n", + "h", + "t", + "i", + "c", + "g", + "a", + "o", + "u", + "m", + "l", + "r", + "à", + "đ", + "s", + "e", + "v", + "p", + "b", + "y", + "ư", + "d", + "á", + "k", + "ộ", + "ế", + ], + "Czech": [ + "o", + "e", + "a", + "n", + "t", + "s", + "i", + "l", + "v", + "r", + "k", + "d", + "u", + "m", + "p", + "í", + "c", + "h", + "z", + "á", + "y", + "j", + "b", + "ě", + "é", + "ř", + ], + "Hungarian": [ + "e", + "a", + "t", + "l", + "s", + "n", + "k", + "r", + "i", + "o", + "z", + "á", + "é", + "g", + "m", + "b", + "y", + "v", + "d", + "h", + "u", + "p", + "j", + "ö", + "f", + "c", + ], + "Korean": [ + "이", + "다", + "에", + "의", + "는", + "로", + "하", + "을", + "가", + "고", + "지", + "서", + "한", + "은", + "기", + "으", + "년", + "대", + "사", + "시", + "를", + "리", + "도", + "인", + "스", + "일", + ], + "Indonesian": [ + "a", + "n", + "e", + "i", + "r", + "t", + "u", + "s", + "d", + "k", + "m", + "l", + "g", + "p", + "b", + "o", + "h", + "y", + "j", + "c", + "w", + "f", + "v", + "z", + "x", + "q", + ], + "Turkish": [ + "a", + "e", + "i", + "n", + "r", + "l", + "ı", + "k", + "d", + "t", + "s", + "m", + "y", + "u", + "o", + "b", + "ü", + "ş", + "v", + "g", + "z", + "h", + "c", + "p", + "ç", + "ğ", + ], + "Romanian": [ + "e", + "i", + "a", + "r", + "n", + "t", + "u", + "l", + "o", + "c", + "s", + "d", + "p", + "m", + "ă", + "f", + "v", + "î", + "g", + "b", + "ș", + "ț", + "z", + "h", + "â", + "j", + ], + "Farsi": [ + "ا", + "ی", + "ر", + "د", + "ن", + "ه", + "و", + "م", + "ت", + "ب", + "س", + "ل", + "ک", + "ش", + "ز", + "ف", + "گ", + "ع", + "خ", + "ق", + "ج", + "آ", + "پ", + "ح", + "ط", + "ص", + ], + "Arabic": [ + "ا", + "ل", + "ي", + "م", + "و", + "ن", + "ر", + "ت", + "ب", + "ة", + "ع", + "د", + "س", + "ف", + "ه", + "ك", + "ق", + "أ", + "ح", + "ج", + "ش", + "ط", + "ص", + "ى", + "خ", + "إ", + ], + "Danish": [ + "e", + "r", + "n", + "t", + "a", + "i", + "s", + "d", + "l", + "o", + "g", + "m", + "k", + "f", + "v", + "u", + "b", + "h", + "p", + "å", + "y", + "ø", + "æ", + "c", + "j", + "w", + ], + "Serbian": [ + "а", + "и", + "о", + "е", + "н", + "р", + "с", + "у", + "т", + "к", + "ј", + "в", + "д", + "м", + "п", + "л", + "г", + "з", + "б", + "a", + "i", + "e", + "o", + "n", + "ц", + "ш", + ], + "Lithuanian": [ + "i", + "a", + "s", + "o", + "r", + "e", + "t", + "n", + "u", + "k", + "m", + "l", + "p", + "v", + "d", + "j", + "g", + "ė", + "b", + "y", + "ų", + "š", + "ž", + "c", + "ą", + "į", + ], + "Slovene": [ + "e", + "a", + "i", + "o", + "n", + "r", + "s", + "l", + "t", + "j", + "v", + "k", + "d", + "p", + "m", + "u", + "z", + "b", + "g", + "h", + "č", + "c", + "š", + "ž", + "f", + "y", + ], + "Slovak": [ + "o", + "a", + "e", + "n", + "i", + "r", + "v", + "t", + "s", + "l", + "k", + "d", + "m", + "p", + "u", + "c", + "h", + "j", + "b", + "z", + "á", + "y", + "ý", + "í", + "č", + "é", + ], + "Hebrew": [ + "י", + "ו", + "ה", + "ל", + "ר", + "ב", + "ת", + "מ", + "א", + "ש", + "נ", + "ע", + "ם", + "ד", + "ק", + "ח", + "פ", + "ס", + "כ", + "ג", + "ט", + "צ", + "ן", + "ז", + "ך", + ], + "Bulgarian": [ + "а", + "и", + "о", + "е", + "н", + "т", + "р", + "с", + "в", + "л", + "к", + "д", + "п", + "м", + "з", + "г", + "я", + "ъ", + "у", + "б", + "ч", + "ц", + "й", + "ж", + "щ", + "х", + ], + "Croatian": [ + "a", + "i", + "o", + "e", + "n", + "r", + "j", + "s", + "t", + "u", + "k", + "l", + "v", + "d", + "m", + "p", + "g", + "z", + "b", + "c", + "č", + "h", + "š", + "ž", + "ć", + "f", + ], + "Hindi": [ + "क", + "र", + "स", + "न", + "त", + "म", + "ह", + "प", + "य", + "ल", + "व", + "ज", + "द", + "ग", + "ब", + "श", + "ट", + "अ", + "ए", + "थ", + "भ", + "ड", + "च", + "ध", + "ष", + "इ", + ], + "Estonian": [ + "a", + "i", + "e", + "s", + "t", + "l", + "u", + "n", + "o", + "k", + "r", + "d", + "m", + "v", + "g", + "p", + "j", + "h", + "ä", + "b", + "õ", + "ü", + "f", + "c", + "ö", + "y", + ], + "Thai": [ + "า", + "น", + "ร", + "อ", + "ก", + "เ", + "ง", + "ม", + "ย", + "ล", + "ว", + "ด", + "ท", + "ส", + "ต", + "ะ", + "ป", + "บ", + "ค", + "ห", + "แ", + "จ", + "พ", + "ช", + "ข", + "ใ", + ], + "Greek": [ + "α", + "τ", + "ο", + "ι", + "ε", + "ν", + "ρ", + "σ", + "κ", + "η", + "π", + "ς", + "υ", + "μ", + "λ", + "ί", + "ό", + "ά", + "γ", + "έ", + "δ", + "ή", + "ω", + "χ", + "θ", + "ύ", + ], + "Tamil": [ + "க", + "த", + "ப", + "ட", + "ர", + "ம", + "ல", + "ன", + "வ", + "ற", + "ய", + "ள", + "ச", + "ந", + "இ", + "ண", + "அ", + "ஆ", + "ழ", + "ங", + "எ", + "உ", + "ஒ", + "ஸ", + ], + "Kazakh": [ + "а", + "ы", + "е", + "н", + "т", + "р", + "л", + "і", + "д", + "с", + "м", + "қ", + "к", + "о", + "б", + "и", + "у", + "ғ", + "ж", + "ң", + "з", + "ш", + "й", + "п", + "г", + "ө", + ], +} + +LANGUAGE_SUPPORTED_COUNT: int = len(FREQUENCIES) diff --git a/backend/venv/Lib/site-packages/charset_normalizer/legacy.py b/backend/venv/Lib/site-packages/charset_normalizer/legacy.py new file mode 100644 index 0000000..360a310 --- /dev/null +++ b/backend/venv/Lib/site-packages/charset_normalizer/legacy.py @@ -0,0 +1,80 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING, Any +from warnings import warn + +from .api import from_bytes +from .constant import CHARDET_CORRESPONDENCE, TOO_SMALL_SEQUENCE + +# TODO: remove this check when dropping Python 3.7 support +if TYPE_CHECKING: + from typing_extensions import TypedDict + + class ResultDict(TypedDict): + encoding: str | None + language: str + confidence: float | None + + +def detect( + byte_str: bytes, should_rename_legacy: bool = False, **kwargs: Any +) -> ResultDict: + """ + chardet legacy method + Detect the encoding of the given byte string. It should be mostly backward-compatible. + Encoding name will match Chardet own writing whenever possible. (Not on encoding name unsupported by it) + This function is deprecated and should be used to migrate your project easily, consult the documentation for + further information. Not planned for removal. + + :param byte_str: The byte sequence to examine. + :param should_rename_legacy: Should we rename legacy encodings + to their more modern equivalents? + """ + if len(kwargs): + warn( + f"charset-normalizer disregard arguments '{','.join(list(kwargs.keys()))}' in legacy function detect()" + ) + + if not isinstance(byte_str, (bytearray, bytes)): + raise TypeError( # pragma: nocover + f"Expected object of type bytes or bytearray, got: {type(byte_str)}" + ) + + if isinstance(byte_str, bytearray): + byte_str = bytes(byte_str) + + r = from_bytes(byte_str).best() + + encoding = r.encoding if r is not None else None + language = r.language if r is not None and r.language != "Unknown" else "" + confidence = 1.0 - r.chaos if r is not None else None + + # automatically lower confidence + # on small bytes samples. + # https://github.com/jawah/charset_normalizer/issues/391 + if ( + confidence is not None + and confidence >= 0.9 + and encoding + not in { + "utf_8", + "ascii", + } + and r.bom is False # type: ignore[union-attr] + and len(byte_str) < TOO_SMALL_SEQUENCE + ): + confidence -= 0.2 + + # Note: CharsetNormalizer does not return 'UTF-8-SIG' as the sig get stripped in the detection/normalization process + # but chardet does return 'utf-8-sig' and it is a valid codec name. + if r is not None and encoding == "utf_8" and r.bom: + encoding += "_sig" + + if should_rename_legacy is False and encoding in CHARDET_CORRESPONDENCE: + encoding = CHARDET_CORRESPONDENCE[encoding] + + return { + "encoding": encoding, + "language": language, + "confidence": confidence, + } diff --git a/backend/venv/Lib/site-packages/charset_normalizer/md.cp312-win_amd64.pyd b/backend/venv/Lib/site-packages/charset_normalizer/md.cp312-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..439122d55f70a69ba314747a25a275046f661225 GIT binary patch literal 10752 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 a-tC?pD|R&RXx|at(Xrzz9i{)bga1$ekRe|H literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/charset_normalizer/md.py b/backend/venv/Lib/site-packages/charset_normalizer/md.py new file mode 100644 index 0000000..12ce024 --- /dev/null +++ b/backend/venv/Lib/site-packages/charset_normalizer/md.py @@ -0,0 +1,635 @@ +from __future__ import annotations + +from functools import lru_cache +from logging import getLogger + +from .constant import ( + COMMON_SAFE_ASCII_CHARACTERS, + TRACE, + UNICODE_SECONDARY_RANGE_KEYWORD, +) +from .utils import ( + is_accentuated, + is_arabic, + is_arabic_isolated_form, + is_case_variable, + is_cjk, + is_emoticon, + is_hangul, + is_hiragana, + is_katakana, + is_latin, + is_punctuation, + is_separator, + is_symbol, + is_thai, + is_unprintable, + remove_accent, + unicode_range, + is_cjk_uncommon, +) + + +class MessDetectorPlugin: + """ + Base abstract class used for mess detection plugins. + All detectors MUST extend and implement given methods. + """ + + def eligible(self, character: str) -> bool: + """ + Determine if given character should be fed in. + """ + raise NotImplementedError # pragma: nocover + + def feed(self, character: str) -> None: + """ + The main routine to be executed upon character. + Insert the logic in witch the text would be considered chaotic. + """ + raise NotImplementedError # pragma: nocover + + def reset(self) -> None: # pragma: no cover + """ + Permit to reset the plugin to the initial state. + """ + raise NotImplementedError + + @property + def ratio(self) -> float: + """ + Compute the chaos ratio based on what your feed() has seen. + Must NOT be lower than 0.; No restriction gt 0. + """ + raise NotImplementedError # pragma: nocover + + +class TooManySymbolOrPunctuationPlugin(MessDetectorPlugin): + def __init__(self) -> None: + self._punctuation_count: int = 0 + self._symbol_count: int = 0 + self._character_count: int = 0 + + self._last_printable_char: str | None = None + self._frenzy_symbol_in_word: bool = False + + def eligible(self, character: str) -> bool: + return character.isprintable() + + def feed(self, character: str) -> None: + self._character_count += 1 + + if ( + character != self._last_printable_char + and character not in COMMON_SAFE_ASCII_CHARACTERS + ): + if is_punctuation(character): + self._punctuation_count += 1 + elif ( + character.isdigit() is False + and is_symbol(character) + and is_emoticon(character) is False + ): + self._symbol_count += 2 + + self._last_printable_char = character + + def reset(self) -> None: # Abstract + self._punctuation_count = 0 + self._character_count = 0 + self._symbol_count = 0 + + @property + def ratio(self) -> float: + if self._character_count == 0: + return 0.0 + + ratio_of_punctuation: float = ( + self._punctuation_count + self._symbol_count + ) / self._character_count + + return ratio_of_punctuation if ratio_of_punctuation >= 0.3 else 0.0 + + +class TooManyAccentuatedPlugin(MessDetectorPlugin): + def __init__(self) -> None: + self._character_count: int = 0 + self._accentuated_count: int = 0 + + def eligible(self, character: str) -> bool: + return character.isalpha() + + def feed(self, character: str) -> None: + self._character_count += 1 + + if is_accentuated(character): + self._accentuated_count += 1 + + def reset(self) -> None: # Abstract + self._character_count = 0 + self._accentuated_count = 0 + + @property + def ratio(self) -> float: + if self._character_count < 8: + return 0.0 + + ratio_of_accentuation: float = self._accentuated_count / self._character_count + return ratio_of_accentuation if ratio_of_accentuation >= 0.35 else 0.0 + + +class UnprintablePlugin(MessDetectorPlugin): + def __init__(self) -> None: + self._unprintable_count: int = 0 + self._character_count: int = 0 + + def eligible(self, character: str) -> bool: + return True + + def feed(self, character: str) -> None: + if is_unprintable(character): + self._unprintable_count += 1 + self._character_count += 1 + + def reset(self) -> None: # Abstract + self._unprintable_count = 0 + + @property + def ratio(self) -> float: + if self._character_count == 0: + return 0.0 + + return (self._unprintable_count * 8) / self._character_count + + +class SuspiciousDuplicateAccentPlugin(MessDetectorPlugin): + def __init__(self) -> None: + self._successive_count: int = 0 + self._character_count: int = 0 + + self._last_latin_character: str | None = None + + def eligible(self, character: str) -> bool: + return character.isalpha() and is_latin(character) + + def feed(self, character: str) -> None: + self._character_count += 1 + if ( + self._last_latin_character is not None + and is_accentuated(character) + and is_accentuated(self._last_latin_character) + ): + if character.isupper() and self._last_latin_character.isupper(): + self._successive_count += 1 + # Worse if its the same char duplicated with different accent. + if remove_accent(character) == remove_accent(self._last_latin_character): + self._successive_count += 1 + self._last_latin_character = character + + def reset(self) -> None: # Abstract + self._successive_count = 0 + self._character_count = 0 + self._last_latin_character = None + + @property + def ratio(self) -> float: + if self._character_count == 0: + return 0.0 + + return (self._successive_count * 2) / self._character_count + + +class SuspiciousRange(MessDetectorPlugin): + def __init__(self) -> None: + self._suspicious_successive_range_count: int = 0 + self._character_count: int = 0 + self._last_printable_seen: str | None = None + + def eligible(self, character: str) -> bool: + return character.isprintable() + + def feed(self, character: str) -> None: + self._character_count += 1 + + if ( + character.isspace() + or is_punctuation(character) + or character in COMMON_SAFE_ASCII_CHARACTERS + ): + self._last_printable_seen = None + return + + if self._last_printable_seen is None: + self._last_printable_seen = character + return + + unicode_range_a: str | None = unicode_range(self._last_printable_seen) + unicode_range_b: str | None = unicode_range(character) + + if is_suspiciously_successive_range(unicode_range_a, unicode_range_b): + self._suspicious_successive_range_count += 1 + + self._last_printable_seen = character + + def reset(self) -> None: # Abstract + self._character_count = 0 + self._suspicious_successive_range_count = 0 + self._last_printable_seen = None + + @property + def ratio(self) -> float: + if self._character_count <= 13: + return 0.0 + + ratio_of_suspicious_range_usage: float = ( + self._suspicious_successive_range_count * 2 + ) / self._character_count + + return ratio_of_suspicious_range_usage + + +class SuperWeirdWordPlugin(MessDetectorPlugin): + def __init__(self) -> None: + self._word_count: int = 0 + self._bad_word_count: int = 0 + self._foreign_long_count: int = 0 + + self._is_current_word_bad: bool = False + self._foreign_long_watch: bool = False + + self._character_count: int = 0 + self._bad_character_count: int = 0 + + self._buffer: str = "" + self._buffer_accent_count: int = 0 + self._buffer_glyph_count: int = 0 + + def eligible(self, character: str) -> bool: + return True + + def feed(self, character: str) -> None: + if character.isalpha(): + self._buffer += character + if is_accentuated(character): + self._buffer_accent_count += 1 + if ( + self._foreign_long_watch is False + and (is_latin(character) is False or is_accentuated(character)) + and is_cjk(character) is False + and is_hangul(character) is False + and is_katakana(character) is False + and is_hiragana(character) is False + and is_thai(character) is False + ): + self._foreign_long_watch = True + if ( + is_cjk(character) + or is_hangul(character) + or is_katakana(character) + or is_hiragana(character) + or is_thai(character) + ): + self._buffer_glyph_count += 1 + return + if not self._buffer: + return + if ( + character.isspace() or is_punctuation(character) or is_separator(character) + ) and self._buffer: + self._word_count += 1 + buffer_length: int = len(self._buffer) + + self._character_count += buffer_length + + if buffer_length >= 4: + if self._buffer_accent_count / buffer_length >= 0.5: + self._is_current_word_bad = True + # Word/Buffer ending with an upper case accentuated letter are so rare, + # that we will consider them all as suspicious. Same weight as foreign_long suspicious. + elif ( + is_accentuated(self._buffer[-1]) + and self._buffer[-1].isupper() + and all(_.isupper() for _ in self._buffer) is False + ): + self._foreign_long_count += 1 + self._is_current_word_bad = True + elif self._buffer_glyph_count == 1: + self._is_current_word_bad = True + self._foreign_long_count += 1 + if buffer_length >= 24 and self._foreign_long_watch: + camel_case_dst = [ + i + for c, i in zip(self._buffer, range(0, buffer_length)) + if c.isupper() + ] + probable_camel_cased: bool = False + + if camel_case_dst and (len(camel_case_dst) / buffer_length <= 0.3): + probable_camel_cased = True + + if not probable_camel_cased: + self._foreign_long_count += 1 + self._is_current_word_bad = True + + if self._is_current_word_bad: + self._bad_word_count += 1 + self._bad_character_count += len(self._buffer) + self._is_current_word_bad = False + + self._foreign_long_watch = False + self._buffer = "" + self._buffer_accent_count = 0 + self._buffer_glyph_count = 0 + elif ( + character not in {"<", ">", "-", "=", "~", "|", "_"} + and character.isdigit() is False + and is_symbol(character) + ): + self._is_current_word_bad = True + self._buffer += character + + def reset(self) -> None: # Abstract + self._buffer = "" + self._is_current_word_bad = False + self._foreign_long_watch = False + self._bad_word_count = 0 + self._word_count = 0 + self._character_count = 0 + self._bad_character_count = 0 + self._foreign_long_count = 0 + + @property + def ratio(self) -> float: + if self._word_count <= 10 and self._foreign_long_count == 0: + return 0.0 + + return self._bad_character_count / self._character_count + + +class CjkUncommonPlugin(MessDetectorPlugin): + """ + Detect messy CJK text that probably means nothing. + """ + + def __init__(self) -> None: + self._character_count: int = 0 + self._uncommon_count: int = 0 + + def eligible(self, character: str) -> bool: + return is_cjk(character) + + def feed(self, character: str) -> None: + self._character_count += 1 + + if is_cjk_uncommon(character): + self._uncommon_count += 1 + return + + def reset(self) -> None: # Abstract + self._character_count = 0 + self._uncommon_count = 0 + + @property + def ratio(self) -> float: + if self._character_count < 8: + return 0.0 + + uncommon_form_usage: float = self._uncommon_count / self._character_count + + # we can be pretty sure it's garbage when uncommon characters are widely + # used. otherwise it could just be traditional chinese for example. + return uncommon_form_usage / 10 if uncommon_form_usage > 0.5 else 0.0 + + +class ArchaicUpperLowerPlugin(MessDetectorPlugin): + def __init__(self) -> None: + self._buf: bool = False + + self._character_count_since_last_sep: int = 0 + + self._successive_upper_lower_count: int = 0 + self._successive_upper_lower_count_final: int = 0 + + self._character_count: int = 0 + + self._last_alpha_seen: str | None = None + self._current_ascii_only: bool = True + + def eligible(self, character: str) -> bool: + return True + + def feed(self, character: str) -> None: + is_concerned = character.isalpha() and is_case_variable(character) + chunk_sep = is_concerned is False + + if chunk_sep and self._character_count_since_last_sep > 0: + if ( + self._character_count_since_last_sep <= 64 + and character.isdigit() is False + and self._current_ascii_only is False + ): + self._successive_upper_lower_count_final += ( + self._successive_upper_lower_count + ) + + self._successive_upper_lower_count = 0 + self._character_count_since_last_sep = 0 + self._last_alpha_seen = None + self._buf = False + self._character_count += 1 + self._current_ascii_only = True + + return + + if self._current_ascii_only is True and character.isascii() is False: + self._current_ascii_only = False + + if self._last_alpha_seen is not None: + if (character.isupper() and self._last_alpha_seen.islower()) or ( + character.islower() and self._last_alpha_seen.isupper() + ): + if self._buf is True: + self._successive_upper_lower_count += 2 + self._buf = False + else: + self._buf = True + else: + self._buf = False + + self._character_count += 1 + self._character_count_since_last_sep += 1 + self._last_alpha_seen = character + + def reset(self) -> None: # Abstract + self._character_count = 0 + self._character_count_since_last_sep = 0 + self._successive_upper_lower_count = 0 + self._successive_upper_lower_count_final = 0 + self._last_alpha_seen = None + self._buf = False + self._current_ascii_only = True + + @property + def ratio(self) -> float: + if self._character_count == 0: + return 0.0 + + return self._successive_upper_lower_count_final / self._character_count + + +class ArabicIsolatedFormPlugin(MessDetectorPlugin): + def __init__(self) -> None: + self._character_count: int = 0 + self._isolated_form_count: int = 0 + + def reset(self) -> None: # Abstract + self._character_count = 0 + self._isolated_form_count = 0 + + def eligible(self, character: str) -> bool: + return is_arabic(character) + + def feed(self, character: str) -> None: + self._character_count += 1 + + if is_arabic_isolated_form(character): + self._isolated_form_count += 1 + + @property + def ratio(self) -> float: + if self._character_count < 8: + return 0.0 + + isolated_form_usage: float = self._isolated_form_count / self._character_count + + return isolated_form_usage + + +@lru_cache(maxsize=1024) +def is_suspiciously_successive_range( + unicode_range_a: str | None, unicode_range_b: str | None +) -> bool: + """ + Determine if two Unicode range seen next to each other can be considered as suspicious. + """ + if unicode_range_a is None or unicode_range_b is None: + return True + + if unicode_range_a == unicode_range_b: + return False + + if "Latin" in unicode_range_a and "Latin" in unicode_range_b: + return False + + if "Emoticons" in unicode_range_a or "Emoticons" in unicode_range_b: + return False + + # Latin characters can be accompanied with a combining diacritical mark + # eg. Vietnamese. + if ("Latin" in unicode_range_a or "Latin" in unicode_range_b) and ( + "Combining" in unicode_range_a or "Combining" in unicode_range_b + ): + return False + + keywords_range_a, keywords_range_b = ( + unicode_range_a.split(" "), + unicode_range_b.split(" "), + ) + + for el in keywords_range_a: + if el in UNICODE_SECONDARY_RANGE_KEYWORD: + continue + if el in keywords_range_b: + return False + + # Japanese Exception + range_a_jp_chars, range_b_jp_chars = ( + unicode_range_a + in ( + "Hiragana", + "Katakana", + ), + unicode_range_b in ("Hiragana", "Katakana"), + ) + if (range_a_jp_chars or range_b_jp_chars) and ( + "CJK" in unicode_range_a or "CJK" in unicode_range_b + ): + return False + if range_a_jp_chars and range_b_jp_chars: + return False + + if "Hangul" in unicode_range_a or "Hangul" in unicode_range_b: + if "CJK" in unicode_range_a or "CJK" in unicode_range_b: + return False + if unicode_range_a == "Basic Latin" or unicode_range_b == "Basic Latin": + return False + + # Chinese/Japanese use dedicated range for punctuation and/or separators. + if ("CJK" in unicode_range_a or "CJK" in unicode_range_b) or ( + unicode_range_a in ["Katakana", "Hiragana"] + and unicode_range_b in ["Katakana", "Hiragana"] + ): + if "Punctuation" in unicode_range_a or "Punctuation" in unicode_range_b: + return False + if "Forms" in unicode_range_a or "Forms" in unicode_range_b: + return False + if unicode_range_a == "Basic Latin" or unicode_range_b == "Basic Latin": + return False + + return True + + +@lru_cache(maxsize=2048) +def mess_ratio( + decoded_sequence: str, maximum_threshold: float = 0.2, debug: bool = False +) -> float: + """ + Compute a mess ratio given a decoded bytes sequence. The maximum threshold does stop the computation earlier. + """ + + detectors: list[MessDetectorPlugin] = [ + md_class() for md_class in MessDetectorPlugin.__subclasses__() + ] + + length: int = len(decoded_sequence) + 1 + + mean_mess_ratio: float = 0.0 + + if length < 512: + intermediary_mean_mess_ratio_calc: int = 32 + elif length <= 1024: + intermediary_mean_mess_ratio_calc = 64 + else: + intermediary_mean_mess_ratio_calc = 128 + + for character, index in zip(decoded_sequence + "\n", range(length)): + for detector in detectors: + if detector.eligible(character): + detector.feed(character) + + if ( + index > 0 and index % intermediary_mean_mess_ratio_calc == 0 + ) or index == length - 1: + mean_mess_ratio = sum(dt.ratio for dt in detectors) + + if mean_mess_ratio >= maximum_threshold: + break + + if debug: + logger = getLogger("charset_normalizer") + + logger.log( + TRACE, + "Mess-detector extended-analysis start. " + f"intermediary_mean_mess_ratio_calc={intermediary_mean_mess_ratio_calc} mean_mess_ratio={mean_mess_ratio} " + f"maximum_threshold={maximum_threshold}", + ) + + if len(decoded_sequence) > 16: + logger.log(TRACE, f"Starting with: {decoded_sequence[:16]}") + logger.log(TRACE, f"Ending with: {decoded_sequence[-16::]}") + + for dt in detectors: + logger.log(TRACE, f"{dt.__class__}: {dt.ratio}") + + return round(mean_mess_ratio, 3) diff --git a/backend/venv/Lib/site-packages/charset_normalizer/md__mypyc.cp312-win_amd64.pyd b/backend/venv/Lib/site-packages/charset_normalizer/md__mypyc.cp312-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..40b7262086ef55e28bcea503722a4f6eeb417659 GIT binary patch literal 128512 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 OsYji0&ba;^`1>D%W~bBu literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/charset_normalizer/models.py b/backend/venv/Lib/site-packages/charset_normalizer/models.py new file mode 100644 index 0000000..1042758 --- /dev/null +++ b/backend/venv/Lib/site-packages/charset_normalizer/models.py @@ -0,0 +1,360 @@ +from __future__ import annotations + +from encodings.aliases import aliases +from hashlib import sha256 +from json import dumps +from re import sub +from typing import Any, Iterator, List, Tuple + +from .constant import RE_POSSIBLE_ENCODING_INDICATION, TOO_BIG_SEQUENCE +from .utils import iana_name, is_multi_byte_encoding, unicode_range + + +class CharsetMatch: + def __init__( + self, + payload: bytes, + guessed_encoding: str, + mean_mess_ratio: float, + has_sig_or_bom: bool, + languages: CoherenceMatches, + decoded_payload: str | None = None, + preemptive_declaration: str | None = None, + ): + self._payload: bytes = payload + + self._encoding: str = guessed_encoding + self._mean_mess_ratio: float = mean_mess_ratio + self._languages: CoherenceMatches = languages + self._has_sig_or_bom: bool = has_sig_or_bom + self._unicode_ranges: list[str] | None = None + + self._leaves: list[CharsetMatch] = [] + self._mean_coherence_ratio: float = 0.0 + + self._output_payload: bytes | None = None + self._output_encoding: str | None = None + + self._string: str | None = decoded_payload + + self._preemptive_declaration: str | None = preemptive_declaration + + def __eq__(self, other: object) -> bool: + if not isinstance(other, CharsetMatch): + if isinstance(other, str): + return iana_name(other) == self.encoding + return False + return self.encoding == other.encoding and self.fingerprint == other.fingerprint + + def __lt__(self, other: object) -> bool: + """ + Implemented to make sorted available upon CharsetMatches items. + """ + if not isinstance(other, CharsetMatch): + raise ValueError + + chaos_difference: float = abs(self.chaos - other.chaos) + coherence_difference: float = abs(self.coherence - other.coherence) + + # Below 1% difference --> Use Coherence + if chaos_difference < 0.01 and coherence_difference > 0.02: + return self.coherence > other.coherence + elif chaos_difference < 0.01 and coherence_difference <= 0.02: + # When having a difficult decision, use the result that decoded as many multi-byte as possible. + # preserve RAM usage! + if len(self._payload) >= TOO_BIG_SEQUENCE: + return self.chaos < other.chaos + return self.multi_byte_usage > other.multi_byte_usage + + return self.chaos < other.chaos + + @property + def multi_byte_usage(self) -> float: + return 1.0 - (len(str(self)) / len(self.raw)) + + def __str__(self) -> str: + # Lazy Str Loading + if self._string is None: + self._string = str(self._payload, self._encoding, "strict") + return self._string + + def __repr__(self) -> str: + return f"" + + def add_submatch(self, other: CharsetMatch) -> None: + if not isinstance(other, CharsetMatch) or other == self: + raise ValueError( + "Unable to add instance <{}> as a submatch of a CharsetMatch".format( + other.__class__ + ) + ) + + other._string = None # Unload RAM usage; dirty trick. + self._leaves.append(other) + + @property + def encoding(self) -> str: + return self._encoding + + @property + def encoding_aliases(self) -> list[str]: + """ + Encoding name are known by many name, using this could help when searching for IBM855 when it's listed as CP855. + """ + also_known_as: list[str] = [] + for u, p in aliases.items(): + if self.encoding == u: + also_known_as.append(p) + elif self.encoding == p: + also_known_as.append(u) + return also_known_as + + @property + def bom(self) -> bool: + return self._has_sig_or_bom + + @property + def byte_order_mark(self) -> bool: + return self._has_sig_or_bom + + @property + def languages(self) -> list[str]: + """ + Return the complete list of possible languages found in decoded sequence. + Usually not really useful. Returned list may be empty even if 'language' property return something != 'Unknown'. + """ + return [e[0] for e in self._languages] + + @property + def language(self) -> str: + """ + Most probable language found in decoded sequence. If none were detected or inferred, the property will return + "Unknown". + """ + if not self._languages: + # Trying to infer the language based on the given encoding + # Its either English or we should not pronounce ourselves in certain cases. + if "ascii" in self.could_be_from_charset: + return "English" + + # doing it there to avoid circular import + from charset_normalizer.cd import encoding_languages, mb_encoding_languages + + languages = ( + mb_encoding_languages(self.encoding) + if is_multi_byte_encoding(self.encoding) + else encoding_languages(self.encoding) + ) + + if len(languages) == 0 or "Latin Based" in languages: + return "Unknown" + + return languages[0] + + return self._languages[0][0] + + @property + def chaos(self) -> float: + return self._mean_mess_ratio + + @property + def coherence(self) -> float: + if not self._languages: + return 0.0 + return self._languages[0][1] + + @property + def percent_chaos(self) -> float: + return round(self.chaos * 100, ndigits=3) + + @property + def percent_coherence(self) -> float: + return round(self.coherence * 100, ndigits=3) + + @property + def raw(self) -> bytes: + """ + Original untouched bytes. + """ + return self._payload + + @property + def submatch(self) -> list[CharsetMatch]: + return self._leaves + + @property + def has_submatch(self) -> bool: + return len(self._leaves) > 0 + + @property + def alphabets(self) -> list[str]: + if self._unicode_ranges is not None: + return self._unicode_ranges + # list detected ranges + detected_ranges: list[str | None] = [unicode_range(char) for char in str(self)] + # filter and sort + self._unicode_ranges = sorted(list({r for r in detected_ranges if r})) + return self._unicode_ranges + + @property + def could_be_from_charset(self) -> list[str]: + """ + The complete list of encoding that output the exact SAME str result and therefore could be the originating + encoding. + This list does include the encoding available in property 'encoding'. + """ + return [self._encoding] + [m.encoding for m in self._leaves] + + def output(self, encoding: str = "utf_8") -> bytes: + """ + Method to get re-encoded bytes payload using given target encoding. Default to UTF-8. + Any errors will be simply ignored by the encoder NOT replaced. + """ + if self._output_encoding is None or self._output_encoding != encoding: + self._output_encoding = encoding + decoded_string = str(self) + if ( + self._preemptive_declaration is not None + and self._preemptive_declaration.lower() + not in ["utf-8", "utf8", "utf_8"] + ): + patched_header = sub( + RE_POSSIBLE_ENCODING_INDICATION, + lambda m: m.string[m.span()[0] : m.span()[1]].replace( + m.groups()[0], + iana_name(self._output_encoding).replace("_", "-"), # type: ignore[arg-type] + ), + decoded_string[:8192], + count=1, + ) + + decoded_string = patched_header + decoded_string[8192:] + + self._output_payload = decoded_string.encode(encoding, "replace") + + return self._output_payload # type: ignore + + @property + def fingerprint(self) -> str: + """ + Retrieve the unique SHA256 computed using the transformed (re-encoded) payload. Not the original one. + """ + return sha256(self.output()).hexdigest() + + +class CharsetMatches: + """ + Container with every CharsetMatch items ordered by default from most probable to the less one. + Act like a list(iterable) but does not implements all related methods. + """ + + def __init__(self, results: list[CharsetMatch] | None = None): + self._results: list[CharsetMatch] = sorted(results) if results else [] + + def __iter__(self) -> Iterator[CharsetMatch]: + yield from self._results + + def __getitem__(self, item: int | str) -> CharsetMatch: + """ + Retrieve a single item either by its position or encoding name (alias may be used here). + Raise KeyError upon invalid index or encoding not present in results. + """ + if isinstance(item, int): + return self._results[item] + if isinstance(item, str): + item = iana_name(item, False) + for result in self._results: + if item in result.could_be_from_charset: + return result + raise KeyError + + def __len__(self) -> int: + return len(self._results) + + def __bool__(self) -> bool: + return len(self._results) > 0 + + def append(self, item: CharsetMatch) -> None: + """ + Insert a single match. Will be inserted accordingly to preserve sort. + Can be inserted as a submatch. + """ + if not isinstance(item, CharsetMatch): + raise ValueError( + "Cannot append instance '{}' to CharsetMatches".format( + str(item.__class__) + ) + ) + # We should disable the submatch factoring when the input file is too heavy (conserve RAM usage) + if len(item.raw) < TOO_BIG_SEQUENCE: + for match in self._results: + if match.fingerprint == item.fingerprint and match.chaos == item.chaos: + match.add_submatch(item) + return + self._results.append(item) + self._results = sorted(self._results) + + def best(self) -> CharsetMatch | None: + """ + Simply return the first match. Strict equivalent to matches[0]. + """ + if not self._results: + return None + return self._results[0] + + def first(self) -> CharsetMatch | None: + """ + Redundant method, call the method best(). Kept for BC reasons. + """ + return self.best() + + +CoherenceMatch = Tuple[str, float] +CoherenceMatches = List[CoherenceMatch] + + +class CliDetectionResult: + def __init__( + self, + path: str, + encoding: str | None, + encoding_aliases: list[str], + alternative_encodings: list[str], + language: str, + alphabets: list[str], + has_sig_or_bom: bool, + chaos: float, + coherence: float, + unicode_path: str | None, + is_preferred: bool, + ): + self.path: str = path + self.unicode_path: str | None = unicode_path + self.encoding: str | None = encoding + self.encoding_aliases: list[str] = encoding_aliases + self.alternative_encodings: list[str] = alternative_encodings + self.language: str = language + self.alphabets: list[str] = alphabets + self.has_sig_or_bom: bool = has_sig_or_bom + self.chaos: float = chaos + self.coherence: float = coherence + self.is_preferred: bool = is_preferred + + @property + def __dict__(self) -> dict[str, Any]: # type: ignore + return { + "path": self.path, + "encoding": self.encoding, + "encoding_aliases": self.encoding_aliases, + "alternative_encodings": self.alternative_encodings, + "language": self.language, + "alphabets": self.alphabets, + "has_sig_or_bom": self.has_sig_or_bom, + "chaos": self.chaos, + "coherence": self.coherence, + "unicode_path": self.unicode_path, + "is_preferred": self.is_preferred, + } + + def to_json(self) -> str: + return dumps(self.__dict__, ensure_ascii=True, indent=4) diff --git a/backend/venv/Lib/site-packages/charset_normalizer/py.typed b/backend/venv/Lib/site-packages/charset_normalizer/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/backend/venv/Lib/site-packages/charset_normalizer/utils.py b/backend/venv/Lib/site-packages/charset_normalizer/utils.py new file mode 100644 index 0000000..6bf0384 --- /dev/null +++ b/backend/venv/Lib/site-packages/charset_normalizer/utils.py @@ -0,0 +1,414 @@ +from __future__ import annotations + +import importlib +import logging +import unicodedata +from codecs import IncrementalDecoder +from encodings.aliases import aliases +from functools import lru_cache +from re import findall +from typing import Generator + +from _multibytecodec import ( # type: ignore[import-not-found,import] + MultibyteIncrementalDecoder, +) + +from .constant import ( + ENCODING_MARKS, + IANA_SUPPORTED_SIMILAR, + RE_POSSIBLE_ENCODING_INDICATION, + UNICODE_RANGES_COMBINED, + UNICODE_SECONDARY_RANGE_KEYWORD, + UTF8_MAXIMAL_ALLOCATION, + COMMON_CJK_CHARACTERS, +) + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_accentuated(character: str) -> bool: + try: + description: str = unicodedata.name(character) + except ValueError: # Defensive: unicode database outdated? + return False + return ( + "WITH GRAVE" in description + or "WITH ACUTE" in description + or "WITH CEDILLA" in description + or "WITH DIAERESIS" in description + or "WITH CIRCUMFLEX" in description + or "WITH TILDE" in description + or "WITH MACRON" in description + or "WITH RING ABOVE" in description + ) + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def remove_accent(character: str) -> str: + decomposed: str = unicodedata.decomposition(character) + if not decomposed: + return character + + codes: list[str] = decomposed.split(" ") + + return chr(int(codes[0], 16)) + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def unicode_range(character: str) -> str | None: + """ + Retrieve the Unicode range official name from a single character. + """ + character_ord: int = ord(character) + + for range_name, ord_range in UNICODE_RANGES_COMBINED.items(): + if character_ord in ord_range: + return range_name + + return None + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_latin(character: str) -> bool: + try: + description: str = unicodedata.name(character) + except ValueError: # Defensive: unicode database outdated? + return False + return "LATIN" in description + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_punctuation(character: str) -> bool: + character_category: str = unicodedata.category(character) + + if "P" in character_category: + return True + + character_range: str | None = unicode_range(character) + + if character_range is None: + return False + + return "Punctuation" in character_range + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_symbol(character: str) -> bool: + character_category: str = unicodedata.category(character) + + if "S" in character_category or "N" in character_category: + return True + + character_range: str | None = unicode_range(character) + + if character_range is None: + return False + + return "Forms" in character_range and character_category != "Lo" + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_emoticon(character: str) -> bool: + character_range: str | None = unicode_range(character) + + if character_range is None: + return False + + return "Emoticons" in character_range or "Pictographs" in character_range + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_separator(character: str) -> bool: + if character.isspace() or character in {"|", "+", "<", ">"}: + return True + + character_category: str = unicodedata.category(character) + + return "Z" in character_category or character_category in {"Po", "Pd", "Pc"} + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_case_variable(character: str) -> bool: + return character.islower() != character.isupper() + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_cjk(character: str) -> bool: + try: + character_name = unicodedata.name(character) + except ValueError: # Defensive: unicode database outdated? + return False + + return "CJK" in character_name + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_hiragana(character: str) -> bool: + try: + character_name = unicodedata.name(character) + except ValueError: # Defensive: unicode database outdated? + return False + + return "HIRAGANA" in character_name + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_katakana(character: str) -> bool: + try: + character_name = unicodedata.name(character) + except ValueError: # Defensive: unicode database outdated? + return False + + return "KATAKANA" in character_name + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_hangul(character: str) -> bool: + try: + character_name = unicodedata.name(character) + except ValueError: # Defensive: unicode database outdated? + return False + + return "HANGUL" in character_name + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_thai(character: str) -> bool: + try: + character_name = unicodedata.name(character) + except ValueError: # Defensive: unicode database outdated? + return False + + return "THAI" in character_name + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_arabic(character: str) -> bool: + try: + character_name = unicodedata.name(character) + except ValueError: # Defensive: unicode database outdated? + return False + + return "ARABIC" in character_name + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_arabic_isolated_form(character: str) -> bool: + try: + character_name = unicodedata.name(character) + except ValueError: # Defensive: unicode database outdated? + return False + + return "ARABIC" in character_name and "ISOLATED FORM" in character_name + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_cjk_uncommon(character: str) -> bool: + return character not in COMMON_CJK_CHARACTERS + + +@lru_cache(maxsize=len(UNICODE_RANGES_COMBINED)) +def is_unicode_range_secondary(range_name: str) -> bool: + return any(keyword in range_name for keyword in UNICODE_SECONDARY_RANGE_KEYWORD) + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_unprintable(character: str) -> bool: + return ( + character.isspace() is False # includes \n \t \r \v + and character.isprintable() is False + and character != "\x1a" # Why? Its the ASCII substitute character. + and character != "\ufeff" # bug discovered in Python, + # Zero Width No-Break Space located in Arabic Presentation Forms-B, Unicode 1.1 not acknowledged as space. + ) + + +def any_specified_encoding(sequence: bytes, search_zone: int = 8192) -> str | None: + """ + Extract using ASCII-only decoder any specified encoding in the first n-bytes. + """ + if not isinstance(sequence, bytes): + raise TypeError + + seq_len: int = len(sequence) + + results: list[str] = findall( + RE_POSSIBLE_ENCODING_INDICATION, + sequence[: min(seq_len, search_zone)].decode("ascii", errors="ignore"), + ) + + if len(results) == 0: + return None + + for specified_encoding in results: + specified_encoding = specified_encoding.lower().replace("-", "_") + + encoding_alias: str + encoding_iana: str + + for encoding_alias, encoding_iana in aliases.items(): + if encoding_alias == specified_encoding: + return encoding_iana + if encoding_iana == specified_encoding: + return encoding_iana + + return None + + +@lru_cache(maxsize=128) +def is_multi_byte_encoding(name: str) -> bool: + """ + Verify is a specific encoding is a multi byte one based on it IANA name + """ + return name in { + "utf_8", + "utf_8_sig", + "utf_16", + "utf_16_be", + "utf_16_le", + "utf_32", + "utf_32_le", + "utf_32_be", + "utf_7", + } or issubclass( + importlib.import_module(f"encodings.{name}").IncrementalDecoder, + MultibyteIncrementalDecoder, + ) + + +def identify_sig_or_bom(sequence: bytes) -> tuple[str | None, bytes]: + """ + Identify and extract SIG/BOM in given sequence. + """ + + for iana_encoding in ENCODING_MARKS: + marks: bytes | list[bytes] = ENCODING_MARKS[iana_encoding] + + if isinstance(marks, bytes): + marks = [marks] + + for mark in marks: + if sequence.startswith(mark): + return iana_encoding, mark + + return None, b"" + + +def should_strip_sig_or_bom(iana_encoding: str) -> bool: + return iana_encoding not in {"utf_16", "utf_32"} + + +def iana_name(cp_name: str, strict: bool = True) -> str: + """Returns the Python normalized encoding name (Not the IANA official name).""" + cp_name = cp_name.lower().replace("-", "_") + + encoding_alias: str + encoding_iana: str + + for encoding_alias, encoding_iana in aliases.items(): + if cp_name in [encoding_alias, encoding_iana]: + return encoding_iana + + if strict: + raise ValueError(f"Unable to retrieve IANA for '{cp_name}'") + + return cp_name + + +def cp_similarity(iana_name_a: str, iana_name_b: str) -> float: + if is_multi_byte_encoding(iana_name_a) or is_multi_byte_encoding(iana_name_b): + return 0.0 + + decoder_a = importlib.import_module(f"encodings.{iana_name_a}").IncrementalDecoder + decoder_b = importlib.import_module(f"encodings.{iana_name_b}").IncrementalDecoder + + id_a: IncrementalDecoder = decoder_a(errors="ignore") + id_b: IncrementalDecoder = decoder_b(errors="ignore") + + character_match_count: int = 0 + + for i in range(255): + to_be_decoded: bytes = bytes([i]) + if id_a.decode(to_be_decoded) == id_b.decode(to_be_decoded): + character_match_count += 1 + + return character_match_count / 254 + + +def is_cp_similar(iana_name_a: str, iana_name_b: str) -> bool: + """ + Determine if two code page are at least 80% similar. IANA_SUPPORTED_SIMILAR dict was generated using + the function cp_similarity. + """ + return ( + iana_name_a in IANA_SUPPORTED_SIMILAR + and iana_name_b in IANA_SUPPORTED_SIMILAR[iana_name_a] + ) + + +def set_logging_handler( + name: str = "charset_normalizer", + level: int = logging.INFO, + format_string: str = "%(asctime)s | %(levelname)s | %(message)s", +) -> None: + logger = logging.getLogger(name) + logger.setLevel(level) + + handler = logging.StreamHandler() + handler.setFormatter(logging.Formatter(format_string)) + logger.addHandler(handler) + + +def cut_sequence_chunks( + sequences: bytes, + encoding_iana: str, + offsets: range, + chunk_size: int, + bom_or_sig_available: bool, + strip_sig_or_bom: bool, + sig_payload: bytes, + is_multi_byte_decoder: bool, + decoded_payload: str | None = None, +) -> Generator[str, None, None]: + if decoded_payload and is_multi_byte_decoder is False: + for i in offsets: + chunk = decoded_payload[i : i + chunk_size] + if not chunk: + break + yield chunk + else: + for i in offsets: + chunk_end = i + chunk_size + if chunk_end > len(sequences) + 8: + continue + + cut_sequence = sequences[i : i + chunk_size] + + if bom_or_sig_available and strip_sig_or_bom is False: + cut_sequence = sig_payload + cut_sequence + + chunk = cut_sequence.decode( + encoding_iana, + errors="ignore" if is_multi_byte_decoder else "strict", + ) + + # multi-byte bad cutting detector and adjustment + # not the cleanest way to perform that fix but clever enough for now. + if is_multi_byte_decoder and i > 0: + chunk_partial_size_chk: int = min(chunk_size, 16) + + if ( + decoded_payload + and chunk[:chunk_partial_size_chk] not in decoded_payload + ): + for j in range(i, i - 4, -1): + cut_sequence = sequences[j:chunk_end] + + if bom_or_sig_available and strip_sig_or_bom is False: + cut_sequence = sig_payload + cut_sequence + + chunk = cut_sequence.decode(encoding_iana, errors="ignore") + + if chunk[:chunk_partial_size_chk] in decoded_payload: + break + + yield chunk diff --git a/backend/venv/Lib/site-packages/charset_normalizer/version.py b/backend/venv/Lib/site-packages/charset_normalizer/version.py new file mode 100644 index 0000000..71350e5 --- /dev/null +++ b/backend/venv/Lib/site-packages/charset_normalizer/version.py @@ -0,0 +1,8 @@ +""" +Expose version +""" + +from __future__ import annotations + +__version__ = "3.4.3" +VERSION = __version__.split(".") diff --git a/backend/venv/Lib/site-packages/click-8.3.0.dist-info/INSTALLER b/backend/venv/Lib/site-packages/click-8.3.0.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/backend/venv/Lib/site-packages/click-8.3.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/backend/venv/Lib/site-packages/click-8.3.0.dist-info/METADATA b/backend/venv/Lib/site-packages/click-8.3.0.dist-info/METADATA new file mode 100644 index 0000000..534eb57 --- /dev/null +++ b/backend/venv/Lib/site-packages/click-8.3.0.dist-info/METADATA @@ -0,0 +1,84 @@ +Metadata-Version: 2.4 +Name: click +Version: 8.3.0 +Summary: Composable command line interface toolkit +Maintainer-email: Pallets +Requires-Python: >=3.10 +Description-Content-Type: text/markdown +License-Expression: BSD-3-Clause +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Typing :: Typed +License-File: LICENSE.txt +Requires-Dist: colorama; platform_system == 'Windows' +Project-URL: Changes, https://click.palletsprojects.com/page/changes/ +Project-URL: Chat, https://discord.gg/pallets +Project-URL: Documentation, https://click.palletsprojects.com/ +Project-URL: Donate, https://palletsprojects.com/donate +Project-URL: Source, https://github.com/pallets/click/ + +
+ +# Click + +Click is a Python package for creating beautiful command line interfaces +in a composable way with as little code as necessary. It's the "Command +Line Interface Creation Kit". It's highly configurable but comes with +sensible defaults out of the box. + +It aims to make the process of writing command line tools quick and fun +while also preventing any frustration caused by the inability to +implement an intended CLI API. + +Click in three points: + +- Arbitrary nesting of commands +- Automatic help page generation +- Supports lazy loading of subcommands at runtime + + +## A Simple Example + +```python +import click + +@click.command() +@click.option("--count", default=1, help="Number of greetings.") +@click.option("--name", prompt="Your name", help="The person to greet.") +def hello(count, name): + """Simple program that greets NAME for a total of COUNT times.""" + for _ in range(count): + click.echo(f"Hello, {name}!") + +if __name__ == '__main__': + hello() +``` + +``` +$ python hello.py --count=3 +Your name: Click +Hello, Click! +Hello, Click! +Hello, Click! +``` + + +## Donate + +The Pallets organization develops and supports Click and other popular +packages. In order to grow the community of contributors and users, and +allow the maintainers to devote more time to the projects, [please +donate today][]. + +[please donate today]: https://palletsprojects.com/donate + +## Contributing + +See our [detailed contributing documentation][contrib] for many ways to +contribute, including reporting issues, requesting features, asking or answering +questions, and making PRs. + +[contrib]: https://palletsprojects.com/contributing/ + diff --git a/backend/venv/Lib/site-packages/click-8.3.0.dist-info/RECORD b/backend/venv/Lib/site-packages/click-8.3.0.dist-info/RECORD new file mode 100644 index 0000000..d3927d9 --- /dev/null +++ b/backend/venv/Lib/site-packages/click-8.3.0.dist-info/RECORD @@ -0,0 +1,40 @@ +click-8.3.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +click-8.3.0.dist-info/METADATA,sha256=P6vpEHZ_MLBt4SO2eB-QaadcOdiznkzaZtJImRo7_V4,2621 +click-8.3.0.dist-info/RECORD,, +click-8.3.0.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82 +click-8.3.0.dist-info/licenses/LICENSE.txt,sha256=morRBqOU6FO_4h9C9OctWSgZoigF2ZG18ydQKSkrZY0,1475 +click/__init__.py,sha256=6YyS1aeyknZ0LYweWozNZy0A9nZ_11wmYIhv3cbQrYo,4473 +click/__pycache__/__init__.cpython-312.pyc,, +click/__pycache__/_compat.cpython-312.pyc,, +click/__pycache__/_termui_impl.cpython-312.pyc,, +click/__pycache__/_textwrap.cpython-312.pyc,, +click/__pycache__/_utils.cpython-312.pyc,, +click/__pycache__/_winconsole.cpython-312.pyc,, +click/__pycache__/core.cpython-312.pyc,, +click/__pycache__/decorators.cpython-312.pyc,, +click/__pycache__/exceptions.cpython-312.pyc,, +click/__pycache__/formatting.cpython-312.pyc,, +click/__pycache__/globals.cpython-312.pyc,, +click/__pycache__/parser.cpython-312.pyc,, +click/__pycache__/shell_completion.cpython-312.pyc,, +click/__pycache__/termui.cpython-312.pyc,, +click/__pycache__/testing.cpython-312.pyc,, +click/__pycache__/types.cpython-312.pyc,, +click/__pycache__/utils.cpython-312.pyc,, +click/_compat.py,sha256=v3xBZkFbvA1BXPRkFfBJc6-pIwPI7345m-kQEnpVAs4,18693 +click/_termui_impl.py,sha256=ktpAHyJtNkhyR-x64CQFD6xJQI11fTA3qg2AV3iCToU,26799 +click/_textwrap.py,sha256=BOae0RQ6vg3FkNgSJyOoGzG1meGMxJ_ukWVZKx_v-0o,1400 +click/_utils.py,sha256=kZwtTf5gMuCilJJceS2iTCvRvCY-0aN5rJq8gKw7p8g,943 +click/_winconsole.py,sha256=_vxUuUaxwBhoR0vUWCNuHY8VUefiMdCIyU2SXPqoF-A,8465 +click/core.py,sha256=1A5T8UoAXklIGPTJ83_DJbVi35ehtJS2FTkP_wQ7es0,128855 +click/decorators.py,sha256=5P7abhJtAQYp_KHgjUvhMv464ERwOzrv2enNknlwHyQ,18461 +click/exceptions.py,sha256=8utf8w6V5hJXMnO_ic1FNrtbwuEn1NUu1aDwV8UqnG4,9954 +click/formatting.py,sha256=RVfwwr0rwWNpgGr8NaHodPzkIr7_tUyVh_nDdanLMNc,9730 +click/globals.py,sha256=gM-Nh6A4M0HB_SgkaF5M4ncGGMDHc_flHXu9_oh4GEU,1923 +click/parser.py,sha256=Q31pH0FlQZEq-UXE_ABRzlygEfvxPTuZbWNh4xfXmzw,19010 +click/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +click/shell_completion.py,sha256=Cc4GQUFuWpfQBa9sF5qXeeYI7n3tI_1k6ZdSn4BZbT0,20994 +click/termui.py,sha256=vAYrKC2a7f_NfEIhAThEVYfa__ib5XQbTSCGtJlABRA,30847 +click/testing.py,sha256=EERbzcl1br0mW0qBS9EqkknfNfXB9WQEW0ELIpkvuSs,19102 +click/types.py,sha256=ek54BNSFwPKsqtfT7jsqcc4WHui8AIFVMKM4oVZIXhc,39927 +click/utils.py,sha256=gCUoewdAhA-QLBUUHxrLh4uj6m7T1WjZZMNPvR0I7YA,20257 diff --git a/backend/venv/Lib/site-packages/click-8.3.0.dist-info/WHEEL b/backend/venv/Lib/site-packages/click-8.3.0.dist-info/WHEEL new file mode 100644 index 0000000..d8b9936 --- /dev/null +++ b/backend/venv/Lib/site-packages/click-8.3.0.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: flit 3.12.0 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/backend/venv/Lib/site-packages/click-8.3.0.dist-info/licenses/LICENSE.txt b/backend/venv/Lib/site-packages/click-8.3.0.dist-info/licenses/LICENSE.txt new file mode 100644 index 0000000..d12a849 --- /dev/null +++ b/backend/venv/Lib/site-packages/click-8.3.0.dist-info/licenses/LICENSE.txt @@ -0,0 +1,28 @@ +Copyright 2014 Pallets + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/backend/venv/Lib/site-packages/click/__init__.py b/backend/venv/Lib/site-packages/click/__init__.py new file mode 100644 index 0000000..1aa547c --- /dev/null +++ b/backend/venv/Lib/site-packages/click/__init__.py @@ -0,0 +1,123 @@ +""" +Click is a simple Python module inspired by the stdlib optparse to make +writing command line scripts fun. Unlike other modules, it's based +around a simple API that does not come with too much magic and is +composable. +""" + +from __future__ import annotations + +from .core import Argument as Argument +from .core import Command as Command +from .core import CommandCollection as CommandCollection +from .core import Context as Context +from .core import Group as Group +from .core import Option as Option +from .core import Parameter as Parameter +from .decorators import argument as argument +from .decorators import command as command +from .decorators import confirmation_option as confirmation_option +from .decorators import group as group +from .decorators import help_option as help_option +from .decorators import make_pass_decorator as make_pass_decorator +from .decorators import option as option +from .decorators import pass_context as pass_context +from .decorators import pass_obj as pass_obj +from .decorators import password_option as password_option +from .decorators import version_option as version_option +from .exceptions import Abort as Abort +from .exceptions import BadArgumentUsage as BadArgumentUsage +from .exceptions import BadOptionUsage as BadOptionUsage +from .exceptions import BadParameter as BadParameter +from .exceptions import ClickException as ClickException +from .exceptions import FileError as FileError +from .exceptions import MissingParameter as MissingParameter +from .exceptions import NoSuchOption as NoSuchOption +from .exceptions import UsageError as UsageError +from .formatting import HelpFormatter as HelpFormatter +from .formatting import wrap_text as wrap_text +from .globals import get_current_context as get_current_context +from .termui import clear as clear +from .termui import confirm as confirm +from .termui import echo_via_pager as echo_via_pager +from .termui import edit as edit +from .termui import getchar as getchar +from .termui import launch as launch +from .termui import pause as pause +from .termui import progressbar as progressbar +from .termui import prompt as prompt +from .termui import secho as secho +from .termui import style as style +from .termui import unstyle as unstyle +from .types import BOOL as BOOL +from .types import Choice as Choice +from .types import DateTime as DateTime +from .types import File as File +from .types import FLOAT as FLOAT +from .types import FloatRange as FloatRange +from .types import INT as INT +from .types import IntRange as IntRange +from .types import ParamType as ParamType +from .types import Path as Path +from .types import STRING as STRING +from .types import Tuple as Tuple +from .types import UNPROCESSED as UNPROCESSED +from .types import UUID as UUID +from .utils import echo as echo +from .utils import format_filename as format_filename +from .utils import get_app_dir as get_app_dir +from .utils import get_binary_stream as get_binary_stream +from .utils import get_text_stream as get_text_stream +from .utils import open_file as open_file + + +def __getattr__(name: str) -> object: + import warnings + + if name == "BaseCommand": + from .core import _BaseCommand + + warnings.warn( + "'BaseCommand' is deprecated and will be removed in Click 9.0. Use" + " 'Command' instead.", + DeprecationWarning, + stacklevel=2, + ) + return _BaseCommand + + if name == "MultiCommand": + from .core import _MultiCommand + + warnings.warn( + "'MultiCommand' is deprecated and will be removed in Click 9.0. Use" + " 'Group' instead.", + DeprecationWarning, + stacklevel=2, + ) + return _MultiCommand + + if name == "OptionParser": + from .parser import _OptionParser + + warnings.warn( + "'OptionParser' is deprecated and will be removed in Click 9.0. The" + " old parser is available in 'optparse'.", + DeprecationWarning, + stacklevel=2, + ) + return _OptionParser + + if name == "__version__": + import importlib.metadata + import warnings + + warnings.warn( + "The '__version__' attribute is deprecated and will be removed in" + " Click 9.1. Use feature detection or" + " 'importlib.metadata.version(\"click\")' instead.", + DeprecationWarning, + stacklevel=2, + ) + return importlib.metadata.version("click") + + raise AttributeError(name) diff --git a/backend/venv/Lib/site-packages/click/__pycache__/__init__.cpython-312.pyc b/backend/venv/Lib/site-packages/click/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2f9cebbb78c98df77320d47a9038e89e736b6cfe GIT binary patch literal 4082 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 NOz_Zc%3?C-{{sI)jSc_+ literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/click/__pycache__/_termui_impl.cpython-312.pyc b/backend/venv/Lib/site-packages/click/__pycache__/_termui_impl.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b50e7193eed9b9d5d1014658279049edfc623695 GIT binary patch literal 31565 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 M`uqPvFsTOl7gJ|FwEzGB literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/click/__pycache__/_utils.cpython-312.pyc b/backend/venv/Lib/site-packages/click/__pycache__/_utils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..523b98f049ba25664185232aa57b4eea6a5611be GIT binary patch literal 1210 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 br7oU7%4c6*;^@5O^Yh)=-Jfzev4#I%A*rLT literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/click/__pycache__/formatting.cpython-312.pyc b/backend/venv/Lib/site-packages/click/__pycache__/formatting.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a092c41d54070252ad5905f70febbabe557387bc GIT binary patch literal 13608 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 literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/click/__pycache__/globals.cpython-312.pyc b/backend/venv/Lib/site-packages/click/__pycache__/globals.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2c967b48a1ec95ff250430da0ea7d08219f79c8e GIT binary patch literal 2975 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 S@GYNnD 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 IAH2N(U-WG^4gdfE literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/click/__pycache__/utils.cpython-312.pyc b/backend/venv/Lib/site-packages/click/__pycache__/utils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b0743b60020607eeb4915933e2ed819549150132 GIT binary patch literal 24879 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 t.TextIO: + if encoding is None: + encoding = get_best_encoding(stream) + if errors is None: + errors = "replace" + return _NonClosingTextIOWrapper( + stream, + encoding, + errors, + line_buffering=True, + force_readable=force_readable, + force_writable=force_writable, + ) + + +def is_ascii_encoding(encoding: str) -> bool: + """Checks if a given encoding is ascii.""" + try: + return codecs.lookup(encoding).name == "ascii" + except LookupError: + return False + + +def get_best_encoding(stream: t.IO[t.Any]) -> str: + """Returns the default stream encoding if not found.""" + rv = getattr(stream, "encoding", None) or sys.getdefaultencoding() + if is_ascii_encoding(rv): + return "utf-8" + return rv + + +class _NonClosingTextIOWrapper(io.TextIOWrapper): + def __init__( + self, + stream: t.BinaryIO, + encoding: str | None, + errors: str | None, + force_readable: bool = False, + force_writable: bool = False, + **extra: t.Any, + ) -> None: + self._stream = stream = t.cast( + t.BinaryIO, _FixupStream(stream, force_readable, force_writable) + ) + super().__init__(stream, encoding, errors, **extra) + + def __del__(self) -> None: + try: + self.detach() + except Exception: + pass + + def isatty(self) -> bool: + # https://bitbucket.org/pypy/pypy/issue/1803 + return self._stream.isatty() + + +class _FixupStream: + """The new io interface needs more from streams than streams + traditionally implement. As such, this fix-up code is necessary in + some circumstances. + + The forcing of readable and writable flags are there because some tools + put badly patched objects on sys (one such offender are certain version + of jupyter notebook). + """ + + def __init__( + self, + stream: t.BinaryIO, + force_readable: bool = False, + force_writable: bool = False, + ): + self._stream = stream + self._force_readable = force_readable + self._force_writable = force_writable + + def __getattr__(self, name: str) -> t.Any: + return getattr(self._stream, name) + + def read1(self, size: int) -> bytes: + f = getattr(self._stream, "read1", None) + + if f is not None: + return t.cast(bytes, f(size)) + + return self._stream.read(size) + + def readable(self) -> bool: + if self._force_readable: + return True + x = getattr(self._stream, "readable", None) + if x is not None: + return t.cast(bool, x()) + try: + self._stream.read(0) + except Exception: + return False + return True + + def writable(self) -> bool: + if self._force_writable: + return True + x = getattr(self._stream, "writable", None) + if x is not None: + return t.cast(bool, x()) + try: + self._stream.write(b"") + except Exception: + try: + self._stream.write(b"") + except Exception: + return False + return True + + def seekable(self) -> bool: + x = getattr(self._stream, "seekable", None) + if x is not None: + return t.cast(bool, x()) + try: + self._stream.seek(self._stream.tell()) + except Exception: + return False + return True + + +def _is_binary_reader(stream: t.IO[t.Any], default: bool = False) -> bool: + try: + return isinstance(stream.read(0), bytes) + except Exception: + return default + # This happens in some cases where the stream was already + # closed. In this case, we assume the default. + + +def _is_binary_writer(stream: t.IO[t.Any], default: bool = False) -> bool: + try: + stream.write(b"") + except Exception: + try: + stream.write("") + return False + except Exception: + pass + return default + return True + + +def _find_binary_reader(stream: t.IO[t.Any]) -> t.BinaryIO | None: + # We need to figure out if the given stream is already binary. + # This can happen because the official docs recommend detaching + # the streams to get binary streams. Some code might do this, so + # we need to deal with this case explicitly. + if _is_binary_reader(stream, False): + return t.cast(t.BinaryIO, stream) + + buf = getattr(stream, "buffer", None) + + # Same situation here; this time we assume that the buffer is + # actually binary in case it's closed. + if buf is not None and _is_binary_reader(buf, True): + return t.cast(t.BinaryIO, buf) + + return None + + +def _find_binary_writer(stream: t.IO[t.Any]) -> t.BinaryIO | None: + # We need to figure out if the given stream is already binary. + # This can happen because the official docs recommend detaching + # the streams to get binary streams. Some code might do this, so + # we need to deal with this case explicitly. + if _is_binary_writer(stream, False): + return t.cast(t.BinaryIO, stream) + + buf = getattr(stream, "buffer", None) + + # Same situation here; this time we assume that the buffer is + # actually binary in case it's closed. + if buf is not None and _is_binary_writer(buf, True): + return t.cast(t.BinaryIO, buf) + + return None + + +def _stream_is_misconfigured(stream: t.TextIO) -> bool: + """A stream is misconfigured if its encoding is ASCII.""" + # If the stream does not have an encoding set, we assume it's set + # to ASCII. This appears to happen in certain unittest + # environments. It's not quite clear what the correct behavior is + # but this at least will force Click to recover somehow. + return is_ascii_encoding(getattr(stream, "encoding", None) or "ascii") + + +def _is_compat_stream_attr(stream: t.TextIO, attr: str, value: str | None) -> bool: + """A stream attribute is compatible if it is equal to the + desired value or the desired value is unset and the attribute + has a value. + """ + stream_value = getattr(stream, attr, None) + return stream_value == value or (value is None and stream_value is not None) + + +def _is_compatible_text_stream( + stream: t.TextIO, encoding: str | None, errors: str | None +) -> bool: + """Check if a stream's encoding and errors attributes are + compatible with the desired values. + """ + return _is_compat_stream_attr( + stream, "encoding", encoding + ) and _is_compat_stream_attr(stream, "errors", errors) + + +def _force_correct_text_stream( + text_stream: t.IO[t.Any], + encoding: str | None, + errors: str | None, + is_binary: t.Callable[[t.IO[t.Any], bool], bool], + find_binary: t.Callable[[t.IO[t.Any]], t.BinaryIO | None], + force_readable: bool = False, + force_writable: bool = False, +) -> t.TextIO: + if is_binary(text_stream, False): + binary_reader = t.cast(t.BinaryIO, text_stream) + else: + text_stream = t.cast(t.TextIO, text_stream) + # If the stream looks compatible, and won't default to a + # misconfigured ascii encoding, return it as-is. + if _is_compatible_text_stream(text_stream, encoding, errors) and not ( + encoding is None and _stream_is_misconfigured(text_stream) + ): + return text_stream + + # Otherwise, get the underlying binary reader. + possible_binary_reader = find_binary(text_stream) + + # If that's not possible, silently use the original reader + # and get mojibake instead of exceptions. + if possible_binary_reader is None: + return text_stream + + binary_reader = possible_binary_reader + + # Default errors to replace instead of strict in order to get + # something that works. + if errors is None: + errors = "replace" + + # Wrap the binary stream in a text stream with the correct + # encoding parameters. + return _make_text_stream( + binary_reader, + encoding, + errors, + force_readable=force_readable, + force_writable=force_writable, + ) + + +def _force_correct_text_reader( + text_reader: t.IO[t.Any], + encoding: str | None, + errors: str | None, + force_readable: bool = False, +) -> t.TextIO: + return _force_correct_text_stream( + text_reader, + encoding, + errors, + _is_binary_reader, + _find_binary_reader, + force_readable=force_readable, + ) + + +def _force_correct_text_writer( + text_writer: t.IO[t.Any], + encoding: str | None, + errors: str | None, + force_writable: bool = False, +) -> t.TextIO: + return _force_correct_text_stream( + text_writer, + encoding, + errors, + _is_binary_writer, + _find_binary_writer, + force_writable=force_writable, + ) + + +def get_binary_stdin() -> t.BinaryIO: + reader = _find_binary_reader(sys.stdin) + if reader is None: + raise RuntimeError("Was not able to determine binary stream for sys.stdin.") + return reader + + +def get_binary_stdout() -> t.BinaryIO: + writer = _find_binary_writer(sys.stdout) + if writer is None: + raise RuntimeError("Was not able to determine binary stream for sys.stdout.") + return writer + + +def get_binary_stderr() -> t.BinaryIO: + writer = _find_binary_writer(sys.stderr) + if writer is None: + raise RuntimeError("Was not able to determine binary stream for sys.stderr.") + return writer + + +def get_text_stdin(encoding: str | None = None, errors: str | None = None) -> t.TextIO: + rv = _get_windows_console_stream(sys.stdin, encoding, errors) + if rv is not None: + return rv + return _force_correct_text_reader(sys.stdin, encoding, errors, force_readable=True) + + +def get_text_stdout(encoding: str | None = None, errors: str | None = None) -> t.TextIO: + rv = _get_windows_console_stream(sys.stdout, encoding, errors) + if rv is not None: + return rv + return _force_correct_text_writer(sys.stdout, encoding, errors, force_writable=True) + + +def get_text_stderr(encoding: str | None = None, errors: str | None = None) -> t.TextIO: + rv = _get_windows_console_stream(sys.stderr, encoding, errors) + if rv is not None: + return rv + return _force_correct_text_writer(sys.stderr, encoding, errors, force_writable=True) + + +def _wrap_io_open( + file: str | os.PathLike[str] | int, + mode: str, + encoding: str | None, + errors: str | None, +) -> t.IO[t.Any]: + """Handles not passing ``encoding`` and ``errors`` in binary mode.""" + if "b" in mode: + return open(file, mode) + + return open(file, mode, encoding=encoding, errors=errors) + + +def open_stream( + filename: str | os.PathLike[str], + mode: str = "r", + encoding: str | None = None, + errors: str | None = "strict", + atomic: bool = False, +) -> tuple[t.IO[t.Any], bool]: + binary = "b" in mode + filename = os.fspath(filename) + + # Standard streams first. These are simple because they ignore the + # atomic flag. Use fsdecode to handle Path("-"). + if os.fsdecode(filename) == "-": + if any(m in mode for m in ["w", "a", "x"]): + if binary: + return get_binary_stdout(), False + return get_text_stdout(encoding=encoding, errors=errors), False + if binary: + return get_binary_stdin(), False + return get_text_stdin(encoding=encoding, errors=errors), False + + # Non-atomic writes directly go out through the regular open functions. + if not atomic: + return _wrap_io_open(filename, mode, encoding, errors), True + + # Some usability stuff for atomic writes + if "a" in mode: + raise ValueError( + "Appending to an existing file is not supported, because that" + " would involve an expensive `copy`-operation to a temporary" + " file. Open the file in normal `w`-mode and copy explicitly" + " if that's what you're after." + ) + if "x" in mode: + raise ValueError("Use the `overwrite`-parameter instead.") + if "w" not in mode: + raise ValueError("Atomic writes only make sense with `w`-mode.") + + # Atomic writes are more complicated. They work by opening a file + # as a proxy in the same folder and then using the fdopen + # functionality to wrap it in a Python file. Then we wrap it in an + # atomic file that moves the file over on close. + import errno + import random + + try: + perm: int | None = os.stat(filename).st_mode + except OSError: + perm = None + + flags = os.O_RDWR | os.O_CREAT | os.O_EXCL + + if binary: + flags |= getattr(os, "O_BINARY", 0) + + while True: + tmp_filename = os.path.join( + os.path.dirname(filename), + f".__atomic-write{random.randrange(1 << 32):08x}", + ) + try: + fd = os.open(tmp_filename, flags, 0o666 if perm is None else perm) + break + except OSError as e: + if e.errno == errno.EEXIST or ( + os.name == "nt" + and e.errno == errno.EACCES + and os.path.isdir(e.filename) + and os.access(e.filename, os.W_OK) + ): + continue + raise + + if perm is not None: + os.chmod(tmp_filename, perm) # in case perm includes bits in umask + + f = _wrap_io_open(fd, mode, encoding, errors) + af = _AtomicFile(f, tmp_filename, os.path.realpath(filename)) + return t.cast(t.IO[t.Any], af), True + + +class _AtomicFile: + def __init__(self, f: t.IO[t.Any], tmp_filename: str, real_filename: str) -> None: + self._f = f + self._tmp_filename = tmp_filename + self._real_filename = real_filename + self.closed = False + + @property + def name(self) -> str: + return self._real_filename + + def close(self, delete: bool = False) -> None: + if self.closed: + return + self._f.close() + os.replace(self._tmp_filename, self._real_filename) + self.closed = True + + def __getattr__(self, name: str) -> t.Any: + return getattr(self._f, name) + + def __enter__(self) -> _AtomicFile: + return self + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_value: BaseException | None, + tb: TracebackType | None, + ) -> None: + self.close(delete=exc_type is not None) + + def __repr__(self) -> str: + return repr(self._f) + + +def strip_ansi(value: str) -> str: + return _ansi_re.sub("", value) + + +def _is_jupyter_kernel_output(stream: t.IO[t.Any]) -> bool: + while isinstance(stream, (_FixupStream, _NonClosingTextIOWrapper)): + stream = stream._stream + + return stream.__class__.__module__.startswith("ipykernel.") + + +def should_strip_ansi( + stream: t.IO[t.Any] | None = None, color: bool | None = None +) -> bool: + if color is None: + if stream is None: + stream = sys.stdin + return not isatty(stream) and not _is_jupyter_kernel_output(stream) + return not color + + +# On Windows, wrap the output streams with colorama to support ANSI +# color codes. +# NOTE: double check is needed so mypy does not analyze this on Linux +if sys.platform.startswith("win") and WIN: + from ._winconsole import _get_windows_console_stream + + def _get_argv_encoding() -> str: + import locale + + return locale.getpreferredencoding() + + _ansi_stream_wrappers: cabc.MutableMapping[t.TextIO, t.TextIO] = WeakKeyDictionary() + + def auto_wrap_for_ansi(stream: t.TextIO, color: bool | None = None) -> t.TextIO: + """Support ANSI color and style codes on Windows by wrapping a + stream with colorama. + """ + try: + cached = _ansi_stream_wrappers.get(stream) + except Exception: + cached = None + + if cached is not None: + return cached + + import colorama + + strip = should_strip_ansi(stream, color) + ansi_wrapper = colorama.AnsiToWin32(stream, strip=strip) + rv = t.cast(t.TextIO, ansi_wrapper.stream) + _write = rv.write + + def _safe_write(s: str) -> int: + try: + return _write(s) + except BaseException: + ansi_wrapper.reset_all() + raise + + rv.write = _safe_write # type: ignore[method-assign] + + try: + _ansi_stream_wrappers[stream] = rv + except Exception: + pass + + return rv + +else: + + def _get_argv_encoding() -> str: + return getattr(sys.stdin, "encoding", None) or sys.getfilesystemencoding() + + def _get_windows_console_stream( + f: t.TextIO, encoding: str | None, errors: str | None + ) -> t.TextIO | None: + return None + + +def term_len(x: str) -> int: + return len(strip_ansi(x)) + + +def isatty(stream: t.IO[t.Any]) -> bool: + try: + return stream.isatty() + except Exception: + return False + + +def _make_cached_stream_func( + src_func: t.Callable[[], t.TextIO | None], + wrapper_func: t.Callable[[], t.TextIO], +) -> t.Callable[[], t.TextIO | None]: + cache: cabc.MutableMapping[t.TextIO, t.TextIO] = WeakKeyDictionary() + + def func() -> t.TextIO | None: + stream = src_func() + + if stream is None: + return None + + try: + rv = cache.get(stream) + except Exception: + rv = None + if rv is not None: + return rv + rv = wrapper_func() + try: + cache[stream] = rv + except Exception: + pass + return rv + + return func + + +_default_text_stdin = _make_cached_stream_func(lambda: sys.stdin, get_text_stdin) +_default_text_stdout = _make_cached_stream_func(lambda: sys.stdout, get_text_stdout) +_default_text_stderr = _make_cached_stream_func(lambda: sys.stderr, get_text_stderr) + + +binary_streams: cabc.Mapping[str, t.Callable[[], t.BinaryIO]] = { + "stdin": get_binary_stdin, + "stdout": get_binary_stdout, + "stderr": get_binary_stderr, +} + +text_streams: cabc.Mapping[str, t.Callable[[str | None, str | None], t.TextIO]] = { + "stdin": get_text_stdin, + "stdout": get_text_stdout, + "stderr": get_text_stderr, +} diff --git a/backend/venv/Lib/site-packages/click/_termui_impl.py b/backend/venv/Lib/site-packages/click/_termui_impl.py new file mode 100644 index 0000000..47f87b8 --- /dev/null +++ b/backend/venv/Lib/site-packages/click/_termui_impl.py @@ -0,0 +1,847 @@ +""" +This module contains implementations for the termui module. To keep the +import time of Click down, some infrequently used functionality is +placed in this module and only imported as needed. +""" + +from __future__ import annotations + +import collections.abc as cabc +import contextlib +import math +import os +import shlex +import sys +import time +import typing as t +from gettext import gettext as _ +from io import StringIO +from pathlib import Path +from types import TracebackType + +from ._compat import _default_text_stdout +from ._compat import CYGWIN +from ._compat import get_best_encoding +from ._compat import isatty +from ._compat import open_stream +from ._compat import strip_ansi +from ._compat import term_len +from ._compat import WIN +from .exceptions import ClickException +from .utils import echo + +V = t.TypeVar("V") + +if os.name == "nt": + BEFORE_BAR = "\r" + AFTER_BAR = "\n" +else: + BEFORE_BAR = "\r\033[?25l" + AFTER_BAR = "\033[?25h\n" + + +class ProgressBar(t.Generic[V]): + def __init__( + self, + iterable: cabc.Iterable[V] | None, + length: int | None = None, + fill_char: str = "#", + empty_char: str = " ", + bar_template: str = "%(bar)s", + info_sep: str = " ", + hidden: bool = False, + show_eta: bool = True, + show_percent: bool | None = None, + show_pos: bool = False, + item_show_func: t.Callable[[V | None], str | None] | None = None, + label: str | None = None, + file: t.TextIO | None = None, + color: bool | None = None, + update_min_steps: int = 1, + width: int = 30, + ) -> None: + self.fill_char = fill_char + self.empty_char = empty_char + self.bar_template = bar_template + self.info_sep = info_sep + self.hidden = hidden + self.show_eta = show_eta + self.show_percent = show_percent + self.show_pos = show_pos + self.item_show_func = item_show_func + self.label: str = label or "" + + if file is None: + file = _default_text_stdout() + + # There are no standard streams attached to write to. For example, + # pythonw on Windows. + if file is None: + file = StringIO() + + self.file = file + self.color = color + self.update_min_steps = update_min_steps + self._completed_intervals = 0 + self.width: int = width + self.autowidth: bool = width == 0 + + if length is None: + from operator import length_hint + + length = length_hint(iterable, -1) + + if length == -1: + length = None + if iterable is None: + if length is None: + raise TypeError("iterable or length is required") + iterable = t.cast("cabc.Iterable[V]", range(length)) + self.iter: cabc.Iterable[V] = iter(iterable) + self.length = length + self.pos: int = 0 + self.avg: list[float] = [] + self.last_eta: float + self.start: float + self.start = self.last_eta = time.time() + self.eta_known: bool = False + self.finished: bool = False + self.max_width: int | None = None + self.entered: bool = False + self.current_item: V | None = None + self._is_atty = isatty(self.file) + self._last_line: str | None = None + + def __enter__(self) -> ProgressBar[V]: + self.entered = True + self.render_progress() + return self + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_value: BaseException | None, + tb: TracebackType | None, + ) -> None: + self.render_finish() + + def __iter__(self) -> cabc.Iterator[V]: + if not self.entered: + raise RuntimeError("You need to use progress bars in a with block.") + self.render_progress() + return self.generator() + + def __next__(self) -> V: + # Iteration is defined in terms of a generator function, + # returned by iter(self); use that to define next(). This works + # because `self.iter` is an iterable consumed by that generator, + # so it is re-entry safe. Calling `next(self.generator())` + # twice works and does "what you want". + return next(iter(self)) + + def render_finish(self) -> None: + if self.hidden or not self._is_atty: + return + self.file.write(AFTER_BAR) + self.file.flush() + + @property + def pct(self) -> float: + if self.finished: + return 1.0 + return min(self.pos / (float(self.length or 1) or 1), 1.0) + + @property + def time_per_iteration(self) -> float: + if not self.avg: + return 0.0 + return sum(self.avg) / float(len(self.avg)) + + @property + def eta(self) -> float: + if self.length is not None and not self.finished: + return self.time_per_iteration * (self.length - self.pos) + return 0.0 + + def format_eta(self) -> str: + if self.eta_known: + t = int(self.eta) + seconds = t % 60 + t //= 60 + minutes = t % 60 + t //= 60 + hours = t % 24 + t //= 24 + if t > 0: + return f"{t}d {hours:02}:{minutes:02}:{seconds:02}" + else: + return f"{hours:02}:{minutes:02}:{seconds:02}" + return "" + + def format_pos(self) -> str: + pos = str(self.pos) + if self.length is not None: + pos += f"/{self.length}" + return pos + + def format_pct(self) -> str: + return f"{int(self.pct * 100): 4}%"[1:] + + def format_bar(self) -> str: + if self.length is not None: + bar_length = int(self.pct * self.width) + bar = self.fill_char * bar_length + bar += self.empty_char * (self.width - bar_length) + elif self.finished: + bar = self.fill_char * self.width + else: + chars = list(self.empty_char * (self.width or 1)) + if self.time_per_iteration != 0: + chars[ + int( + (math.cos(self.pos * self.time_per_iteration) / 2.0 + 0.5) + * self.width + ) + ] = self.fill_char + bar = "".join(chars) + return bar + + def format_progress_line(self) -> str: + show_percent = self.show_percent + + info_bits = [] + if self.length is not None and show_percent is None: + show_percent = not self.show_pos + + if self.show_pos: + info_bits.append(self.format_pos()) + if show_percent: + info_bits.append(self.format_pct()) + if self.show_eta and self.eta_known and not self.finished: + info_bits.append(self.format_eta()) + if self.item_show_func is not None: + item_info = self.item_show_func(self.current_item) + if item_info is not None: + info_bits.append(item_info) + + return ( + self.bar_template + % { + "label": self.label, + "bar": self.format_bar(), + "info": self.info_sep.join(info_bits), + } + ).rstrip() + + def render_progress(self) -> None: + if self.hidden: + return + + if not self._is_atty: + # Only output the label once if the output is not a TTY. + if self._last_line != self.label: + self._last_line = self.label + echo(self.label, file=self.file, color=self.color) + return + + buf = [] + # Update width in case the terminal has been resized + if self.autowidth: + import shutil + + old_width = self.width + self.width = 0 + clutter_length = term_len(self.format_progress_line()) + new_width = max(0, shutil.get_terminal_size().columns - clutter_length) + if new_width < old_width and self.max_width is not None: + buf.append(BEFORE_BAR) + buf.append(" " * self.max_width) + self.max_width = new_width + self.width = new_width + + clear_width = self.width + if self.max_width is not None: + clear_width = self.max_width + + buf.append(BEFORE_BAR) + line = self.format_progress_line() + line_len = term_len(line) + if self.max_width is None or self.max_width < line_len: + self.max_width = line_len + + buf.append(line) + buf.append(" " * (clear_width - line_len)) + line = "".join(buf) + # Render the line only if it changed. + + if line != self._last_line: + self._last_line = line + echo(line, file=self.file, color=self.color, nl=False) + self.file.flush() + + def make_step(self, n_steps: int) -> None: + self.pos += n_steps + if self.length is not None and self.pos >= self.length: + self.finished = True + + if (time.time() - self.last_eta) < 1.0: + return + + self.last_eta = time.time() + + # self.avg is a rolling list of length <= 7 of steps where steps are + # defined as time elapsed divided by the total progress through + # self.length. + if self.pos: + step = (time.time() - self.start) / self.pos + else: + step = time.time() - self.start + + self.avg = self.avg[-6:] + [step] + + self.eta_known = self.length is not None + + def update(self, n_steps: int, current_item: V | None = None) -> None: + """Update the progress bar by advancing a specified number of + steps, and optionally set the ``current_item`` for this new + position. + + :param n_steps: Number of steps to advance. + :param current_item: Optional item to set as ``current_item`` + for the updated position. + + .. versionchanged:: 8.0 + Added the ``current_item`` optional parameter. + + .. versionchanged:: 8.0 + Only render when the number of steps meets the + ``update_min_steps`` threshold. + """ + if current_item is not None: + self.current_item = current_item + + self._completed_intervals += n_steps + + if self._completed_intervals >= self.update_min_steps: + self.make_step(self._completed_intervals) + self.render_progress() + self._completed_intervals = 0 + + def finish(self) -> None: + self.eta_known = False + self.current_item = None + self.finished = True + + def generator(self) -> cabc.Iterator[V]: + """Return a generator which yields the items added to the bar + during construction, and updates the progress bar *after* the + yielded block returns. + """ + # WARNING: the iterator interface for `ProgressBar` relies on + # this and only works because this is a simple generator which + # doesn't create or manage additional state. If this function + # changes, the impact should be evaluated both against + # `iter(bar)` and `next(bar)`. `next()` in particular may call + # `self.generator()` repeatedly, and this must remain safe in + # order for that interface to work. + if not self.entered: + raise RuntimeError("You need to use progress bars in a with block.") + + if not self._is_atty: + yield from self.iter + else: + for rv in self.iter: + self.current_item = rv + + # This allows show_item_func to be updated before the + # item is processed. Only trigger at the beginning of + # the update interval. + if self._completed_intervals == 0: + self.render_progress() + + yield rv + self.update(1) + + self.finish() + self.render_progress() + + +def pager(generator: cabc.Iterable[str], color: bool | None = None) -> None: + """Decide what method to use for paging through text.""" + stdout = _default_text_stdout() + + # There are no standard streams attached to write to. For example, + # pythonw on Windows. + if stdout is None: + stdout = StringIO() + + if not isatty(sys.stdin) or not isatty(stdout): + return _nullpager(stdout, generator, color) + + # Split and normalize the pager command into parts. + pager_cmd_parts = shlex.split(os.environ.get("PAGER", ""), posix=False) + if pager_cmd_parts: + if WIN: + if _tempfilepager(generator, pager_cmd_parts, color): + return + elif _pipepager(generator, pager_cmd_parts, color): + return + + if os.environ.get("TERM") in ("dumb", "emacs"): + return _nullpager(stdout, generator, color) + if (WIN or sys.platform.startswith("os2")) and _tempfilepager( + generator, ["more"], color + ): + return + if _pipepager(generator, ["less"], color): + return + + import tempfile + + fd, filename = tempfile.mkstemp() + os.close(fd) + try: + if _pipepager(generator, ["more"], color): + return + return _nullpager(stdout, generator, color) + finally: + os.unlink(filename) + + +def _pipepager( + generator: cabc.Iterable[str], cmd_parts: list[str], color: bool | None +) -> bool: + """Page through text by feeding it to another program. Invoking a + pager through this might support colors. + + Returns `True` if the command was found, `False` otherwise and thus another + pager should be attempted. + """ + # Split the command into the invoked CLI and its parameters. + if not cmd_parts: + return False + + import shutil + + cmd = cmd_parts[0] + cmd_params = cmd_parts[1:] + + cmd_filepath = shutil.which(cmd) + if not cmd_filepath: + return False + # Resolves symlinks and produces a normalized absolute path string. + cmd_path = Path(cmd_filepath).resolve() + cmd_name = cmd_path.name + + import subprocess + + # Make a local copy of the environment to not affect the global one. + env = dict(os.environ) + + # If we're piping to less and the user hasn't decided on colors, we enable + # them by default we find the -R flag in the command line arguments. + if color is None and cmd_name == "less": + less_flags = f"{os.environ.get('LESS', '')}{' '.join(cmd_params)}" + if not less_flags: + env["LESS"] = "-R" + color = True + elif "r" in less_flags or "R" in less_flags: + color = True + + c = subprocess.Popen( + [str(cmd_path)] + cmd_params, + shell=True, + stdin=subprocess.PIPE, + env=env, + errors="replace", + text=True, + ) + assert c.stdin is not None + try: + for text in generator: + if not color: + text = strip_ansi(text) + + c.stdin.write(text) + except BrokenPipeError: + # In case the pager exited unexpectedly, ignore the broken pipe error. + pass + except Exception as e: + # In case there is an exception we want to close the pager immediately + # and let the caller handle it. + # Otherwise the pager will keep running, and the user may not notice + # the error message, or worse yet it may leave the terminal in a broken state. + c.terminate() + raise e + finally: + # We must close stdin and wait for the pager to exit before we continue + try: + c.stdin.close() + # Close implies flush, so it might throw a BrokenPipeError if the pager + # process exited already. + except BrokenPipeError: + pass + + # Less doesn't respect ^C, but catches it for its own UI purposes (aborting + # search or other commands inside less). + # + # That means when the user hits ^C, the parent process (click) terminates, + # but less is still alive, paging the output and messing up the terminal. + # + # If the user wants to make the pager exit on ^C, they should set + # `LESS='-K'`. It's not our decision to make. + while True: + try: + c.wait() + except KeyboardInterrupt: + pass + else: + break + + return True + + +def _tempfilepager( + generator: cabc.Iterable[str], cmd_parts: list[str], color: bool | None +) -> bool: + """Page through text by invoking a program on a temporary file. + + Returns `True` if the command was found, `False` otherwise and thus another + pager should be attempted. + """ + # Split the command into the invoked CLI and its parameters. + if not cmd_parts: + return False + + import shutil + + cmd = cmd_parts[0] + + cmd_filepath = shutil.which(cmd) + if not cmd_filepath: + return False + # Resolves symlinks and produces a normalized absolute path string. + cmd_path = Path(cmd_filepath).resolve() + + import subprocess + import tempfile + + fd, filename = tempfile.mkstemp() + # TODO: This never terminates if the passed generator never terminates. + text = "".join(generator) + if not color: + text = strip_ansi(text) + encoding = get_best_encoding(sys.stdout) + with open_stream(filename, "wb")[0] as f: + f.write(text.encode(encoding)) + try: + subprocess.call([str(cmd_path), filename]) + except OSError: + # Command not found + pass + finally: + os.close(fd) + os.unlink(filename) + + return True + + +def _nullpager( + stream: t.TextIO, generator: cabc.Iterable[str], color: bool | None +) -> None: + """Simply print unformatted text. This is the ultimate fallback.""" + for text in generator: + if not color: + text = strip_ansi(text) + stream.write(text) + + +class Editor: + def __init__( + self, + editor: str | None = None, + env: cabc.Mapping[str, str] | None = None, + require_save: bool = True, + extension: str = ".txt", + ) -> None: + self.editor = editor + self.env = env + self.require_save = require_save + self.extension = extension + + def get_editor(self) -> str: + if self.editor is not None: + return self.editor + for key in "VISUAL", "EDITOR": + rv = os.environ.get(key) + if rv: + return rv + if WIN: + return "notepad" + + from shutil import which + + for editor in "sensible-editor", "vim", "nano": + if which(editor) is not None: + return editor + return "vi" + + def edit_files(self, filenames: cabc.Iterable[str]) -> None: + import subprocess + + editor = self.get_editor() + environ: dict[str, str] | None = None + + if self.env: + environ = os.environ.copy() + environ.update(self.env) + + exc_filename = " ".join(f'"{filename}"' for filename in filenames) + + try: + c = subprocess.Popen( + args=f"{editor} {exc_filename}", env=environ, shell=True + ) + exit_code = c.wait() + if exit_code != 0: + raise ClickException( + _("{editor}: Editing failed").format(editor=editor) + ) + except OSError as e: + raise ClickException( + _("{editor}: Editing failed: {e}").format(editor=editor, e=e) + ) from e + + @t.overload + def edit(self, text: bytes | bytearray) -> bytes | None: ... + + # We cannot know whether or not the type expected is str or bytes when None + # is passed, so str is returned as that was what was done before. + @t.overload + def edit(self, text: str | None) -> str | None: ... + + def edit(self, text: str | bytes | bytearray | None) -> str | bytes | None: + import tempfile + + if text is None: + data: bytes | bytearray = b"" + elif isinstance(text, (bytes, bytearray)): + data = text + else: + if text and not text.endswith("\n"): + text += "\n" + + if WIN: + data = text.replace("\n", "\r\n").encode("utf-8-sig") + else: + data = text.encode("utf-8") + + fd, name = tempfile.mkstemp(prefix="editor-", suffix=self.extension) + f: t.BinaryIO + + try: + with os.fdopen(fd, "wb") as f: + f.write(data) + + # If the filesystem resolution is 1 second, like Mac OS + # 10.12 Extended, or 2 seconds, like FAT32, and the editor + # closes very fast, require_save can fail. Set the modified + # time to be 2 seconds in the past to work around this. + os.utime(name, (os.path.getatime(name), os.path.getmtime(name) - 2)) + # Depending on the resolution, the exact value might not be + # recorded, so get the new recorded value. + timestamp = os.path.getmtime(name) + + self.edit_files((name,)) + + if self.require_save and os.path.getmtime(name) == timestamp: + return None + + with open(name, "rb") as f: + rv = f.read() + + if isinstance(text, (bytes, bytearray)): + return rv + + return rv.decode("utf-8-sig").replace("\r\n", "\n") + finally: + os.unlink(name) + + +def open_url(url: str, wait: bool = False, locate: bool = False) -> int: + import subprocess + + def _unquote_file(url: str) -> str: + from urllib.parse import unquote + + if url.startswith("file://"): + url = unquote(url[7:]) + + return url + + if sys.platform == "darwin": + args = ["open"] + if wait: + args.append("-W") + if locate: + args.append("-R") + args.append(_unquote_file(url)) + null = open("/dev/null", "w") + try: + return subprocess.Popen(args, stderr=null).wait() + finally: + null.close() + elif WIN: + if locate: + url = _unquote_file(url) + args = ["explorer", f"/select,{url}"] + else: + args = ["start"] + if wait: + args.append("/WAIT") + args.append("") + args.append(url) + try: + return subprocess.call(args) + except OSError: + # Command not found + return 127 + elif CYGWIN: + if locate: + url = _unquote_file(url) + args = ["cygstart", os.path.dirname(url)] + else: + args = ["cygstart"] + if wait: + args.append("-w") + args.append(url) + try: + return subprocess.call(args) + except OSError: + # Command not found + return 127 + + try: + if locate: + url = os.path.dirname(_unquote_file(url)) or "." + else: + url = _unquote_file(url) + c = subprocess.Popen(["xdg-open", url]) + if wait: + return c.wait() + return 0 + except OSError: + if url.startswith(("http://", "https://")) and not locate and not wait: + import webbrowser + + webbrowser.open(url) + return 0 + return 1 + + +def _translate_ch_to_exc(ch: str) -> None: + if ch == "\x03": + raise KeyboardInterrupt() + + if ch == "\x04" and not WIN: # Unix-like, Ctrl+D + raise EOFError() + + if ch == "\x1a" and WIN: # Windows, Ctrl+Z + raise EOFError() + + return None + + +if sys.platform == "win32": + import msvcrt + + @contextlib.contextmanager + def raw_terminal() -> cabc.Iterator[int]: + yield -1 + + def getchar(echo: bool) -> str: + # The function `getch` will return a bytes object corresponding to + # the pressed character. Since Windows 10 build 1803, it will also + # return \x00 when called a second time after pressing a regular key. + # + # `getwch` does not share this probably-bugged behavior. Moreover, it + # returns a Unicode object by default, which is what we want. + # + # Either of these functions will return \x00 or \xe0 to indicate + # a special key, and you need to call the same function again to get + # the "rest" of the code. The fun part is that \u00e0 is + # "latin small letter a with grave", so if you type that on a French + # keyboard, you _also_ get a \xe0. + # E.g., consider the Up arrow. This returns \xe0 and then \x48. The + # resulting Unicode string reads as "a with grave" + "capital H". + # This is indistinguishable from when the user actually types + # "a with grave" and then "capital H". + # + # When \xe0 is returned, we assume it's part of a special-key sequence + # and call `getwch` again, but that means that when the user types + # the \u00e0 character, `getchar` doesn't return until a second + # character is typed. + # The alternative is returning immediately, but that would mess up + # cross-platform handling of arrow keys and others that start with + # \xe0. Another option is using `getch`, but then we can't reliably + # read non-ASCII characters, because return values of `getch` are + # limited to the current 8-bit codepage. + # + # Anyway, Click doesn't claim to do this Right(tm), and using `getwch` + # is doing the right thing in more situations than with `getch`. + + if echo: + func = t.cast(t.Callable[[], str], msvcrt.getwche) + else: + func = t.cast(t.Callable[[], str], msvcrt.getwch) + + rv = func() + + if rv in ("\x00", "\xe0"): + # \x00 and \xe0 are control characters that indicate special key, + # see above. + rv += func() + + _translate_ch_to_exc(rv) + return rv + +else: + import termios + import tty + + @contextlib.contextmanager + def raw_terminal() -> cabc.Iterator[int]: + f: t.TextIO | None + fd: int + + if not isatty(sys.stdin): + f = open("/dev/tty") + fd = f.fileno() + else: + fd = sys.stdin.fileno() + f = None + + try: + old_settings = termios.tcgetattr(fd) + + try: + tty.setraw(fd) + yield fd + finally: + termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) + sys.stdout.flush() + + if f is not None: + f.close() + except termios.error: + pass + + def getchar(echo: bool) -> str: + with raw_terminal() as fd: + ch = os.read(fd, 32).decode(get_best_encoding(sys.stdin), "replace") + + if echo and isatty(sys.stdout): + sys.stdout.write(ch) + + _translate_ch_to_exc(ch) + return ch diff --git a/backend/venv/Lib/site-packages/click/_textwrap.py b/backend/venv/Lib/site-packages/click/_textwrap.py new file mode 100644 index 0000000..97fbee3 --- /dev/null +++ b/backend/venv/Lib/site-packages/click/_textwrap.py @@ -0,0 +1,51 @@ +from __future__ import annotations + +import collections.abc as cabc +import textwrap +from contextlib import contextmanager + + +class TextWrapper(textwrap.TextWrapper): + def _handle_long_word( + self, + reversed_chunks: list[str], + cur_line: list[str], + cur_len: int, + width: int, + ) -> None: + space_left = max(width - cur_len, 1) + + if self.break_long_words: + last = reversed_chunks[-1] + cut = last[:space_left] + res = last[space_left:] + cur_line.append(cut) + reversed_chunks[-1] = res + elif not cur_line: + cur_line.append(reversed_chunks.pop()) + + @contextmanager + def extra_indent(self, indent: str) -> cabc.Iterator[None]: + old_initial_indent = self.initial_indent + old_subsequent_indent = self.subsequent_indent + self.initial_indent += indent + self.subsequent_indent += indent + + try: + yield + finally: + self.initial_indent = old_initial_indent + self.subsequent_indent = old_subsequent_indent + + def indent_only(self, text: str) -> str: + rv = [] + + for idx, line in enumerate(text.splitlines()): + indent = self.initial_indent + + if idx > 0: + indent = self.subsequent_indent + + rv.append(f"{indent}{line}") + + return "\n".join(rv) diff --git a/backend/venv/Lib/site-packages/click/_utils.py b/backend/venv/Lib/site-packages/click/_utils.py new file mode 100644 index 0000000..09fb008 --- /dev/null +++ b/backend/venv/Lib/site-packages/click/_utils.py @@ -0,0 +1,36 @@ +from __future__ import annotations + +import enum +import typing as t + + +class Sentinel(enum.Enum): + """Enum used to define sentinel values. + + .. seealso:: + + `PEP 661 - Sentinel Values `_. + """ + + UNSET = object() + FLAG_NEEDS_VALUE = object() + + def __repr__(self) -> str: + return f"{self.__class__.__name__}.{self.name}" + + +UNSET = Sentinel.UNSET +"""Sentinel used to indicate that a value is not set.""" + +FLAG_NEEDS_VALUE = Sentinel.FLAG_NEEDS_VALUE +"""Sentinel used to indicate an option was passed as a flag without a +value but is not a flag option. + +``Option.consume_value`` uses this to prompt or use the ``flag_value``. +""" + +T_UNSET = t.Literal[UNSET] # type: ignore[valid-type] +"""Type hint for the :data:`UNSET` sentinel value.""" + +T_FLAG_NEEDS_VALUE = t.Literal[FLAG_NEEDS_VALUE] # type: ignore[valid-type] +"""Type hint for the :data:`FLAG_NEEDS_VALUE` sentinel value.""" diff --git a/backend/venv/Lib/site-packages/click/_winconsole.py b/backend/venv/Lib/site-packages/click/_winconsole.py new file mode 100644 index 0000000..e56c7c6 --- /dev/null +++ b/backend/venv/Lib/site-packages/click/_winconsole.py @@ -0,0 +1,296 @@ +# This module is based on the excellent work by Adam Bartoš who +# provided a lot of what went into the implementation here in +# the discussion to issue1602 in the Python bug tracker. +# +# There are some general differences in regards to how this works +# compared to the original patches as we do not need to patch +# the entire interpreter but just work in our little world of +# echo and prompt. +from __future__ import annotations + +import collections.abc as cabc +import io +import sys +import time +import typing as t +from ctypes import Array +from ctypes import byref +from ctypes import c_char +from ctypes import c_char_p +from ctypes import c_int +from ctypes import c_ssize_t +from ctypes import c_ulong +from ctypes import c_void_p +from ctypes import POINTER +from ctypes import py_object +from ctypes import Structure +from ctypes.wintypes import DWORD +from ctypes.wintypes import HANDLE +from ctypes.wintypes import LPCWSTR +from ctypes.wintypes import LPWSTR + +from ._compat import _NonClosingTextIOWrapper + +assert sys.platform == "win32" +import msvcrt # noqa: E402 +from ctypes import windll # noqa: E402 +from ctypes import WINFUNCTYPE # noqa: E402 + +c_ssize_p = POINTER(c_ssize_t) + +kernel32 = windll.kernel32 +GetStdHandle = kernel32.GetStdHandle +ReadConsoleW = kernel32.ReadConsoleW +WriteConsoleW = kernel32.WriteConsoleW +GetConsoleMode = kernel32.GetConsoleMode +GetLastError = kernel32.GetLastError +GetCommandLineW = WINFUNCTYPE(LPWSTR)(("GetCommandLineW", windll.kernel32)) +CommandLineToArgvW = WINFUNCTYPE(POINTER(LPWSTR), LPCWSTR, POINTER(c_int))( + ("CommandLineToArgvW", windll.shell32) +) +LocalFree = WINFUNCTYPE(c_void_p, c_void_p)(("LocalFree", windll.kernel32)) + +STDIN_HANDLE = GetStdHandle(-10) +STDOUT_HANDLE = GetStdHandle(-11) +STDERR_HANDLE = GetStdHandle(-12) + +PyBUF_SIMPLE = 0 +PyBUF_WRITABLE = 1 + +ERROR_SUCCESS = 0 +ERROR_NOT_ENOUGH_MEMORY = 8 +ERROR_OPERATION_ABORTED = 995 + +STDIN_FILENO = 0 +STDOUT_FILENO = 1 +STDERR_FILENO = 2 + +EOF = b"\x1a" +MAX_BYTES_WRITTEN = 32767 + +if t.TYPE_CHECKING: + try: + # Using `typing_extensions.Buffer` instead of `collections.abc` + # on Windows for some reason does not have `Sized` implemented. + from collections.abc import Buffer # type: ignore + except ImportError: + from typing_extensions import Buffer + +try: + from ctypes import pythonapi +except ImportError: + # On PyPy we cannot get buffers so our ability to operate here is + # severely limited. + get_buffer = None +else: + + class Py_buffer(Structure): + _fields_ = [ # noqa: RUF012 + ("buf", c_void_p), + ("obj", py_object), + ("len", c_ssize_t), + ("itemsize", c_ssize_t), + ("readonly", c_int), + ("ndim", c_int), + ("format", c_char_p), + ("shape", c_ssize_p), + ("strides", c_ssize_p), + ("suboffsets", c_ssize_p), + ("internal", c_void_p), + ] + + PyObject_GetBuffer = pythonapi.PyObject_GetBuffer + PyBuffer_Release = pythonapi.PyBuffer_Release + + def get_buffer(obj: Buffer, writable: bool = False) -> Array[c_char]: + buf = Py_buffer() + flags: int = PyBUF_WRITABLE if writable else PyBUF_SIMPLE + PyObject_GetBuffer(py_object(obj), byref(buf), flags) + + try: + buffer_type = c_char * buf.len + out: Array[c_char] = buffer_type.from_address(buf.buf) + return out + finally: + PyBuffer_Release(byref(buf)) + + +class _WindowsConsoleRawIOBase(io.RawIOBase): + def __init__(self, handle: int | None) -> None: + self.handle = handle + + def isatty(self) -> t.Literal[True]: + super().isatty() + return True + + +class _WindowsConsoleReader(_WindowsConsoleRawIOBase): + def readable(self) -> t.Literal[True]: + return True + + def readinto(self, b: Buffer) -> int: + bytes_to_be_read = len(b) + if not bytes_to_be_read: + return 0 + elif bytes_to_be_read % 2: + raise ValueError( + "cannot read odd number of bytes from UTF-16-LE encoded console" + ) + + buffer = get_buffer(b, writable=True) + code_units_to_be_read = bytes_to_be_read // 2 + code_units_read = c_ulong() + + rv = ReadConsoleW( + HANDLE(self.handle), + buffer, + code_units_to_be_read, + byref(code_units_read), + None, + ) + if GetLastError() == ERROR_OPERATION_ABORTED: + # wait for KeyboardInterrupt + time.sleep(0.1) + if not rv: + raise OSError(f"Windows error: {GetLastError()}") + + if buffer[0] == EOF: + return 0 + return 2 * code_units_read.value + + +class _WindowsConsoleWriter(_WindowsConsoleRawIOBase): + def writable(self) -> t.Literal[True]: + return True + + @staticmethod + def _get_error_message(errno: int) -> str: + if errno == ERROR_SUCCESS: + return "ERROR_SUCCESS" + elif errno == ERROR_NOT_ENOUGH_MEMORY: + return "ERROR_NOT_ENOUGH_MEMORY" + return f"Windows error {errno}" + + def write(self, b: Buffer) -> int: + bytes_to_be_written = len(b) + buf = get_buffer(b) + code_units_to_be_written = min(bytes_to_be_written, MAX_BYTES_WRITTEN) // 2 + code_units_written = c_ulong() + + WriteConsoleW( + HANDLE(self.handle), + buf, + code_units_to_be_written, + byref(code_units_written), + None, + ) + bytes_written = 2 * code_units_written.value + + if bytes_written == 0 and bytes_to_be_written > 0: + raise OSError(self._get_error_message(GetLastError())) + return bytes_written + + +class ConsoleStream: + def __init__(self, text_stream: t.TextIO, byte_stream: t.BinaryIO) -> None: + self._text_stream = text_stream + self.buffer = byte_stream + + @property + def name(self) -> str: + return self.buffer.name + + def write(self, x: t.AnyStr) -> int: + if isinstance(x, str): + return self._text_stream.write(x) + try: + self.flush() + except Exception: + pass + return self.buffer.write(x) + + def writelines(self, lines: cabc.Iterable[t.AnyStr]) -> None: + for line in lines: + self.write(line) + + def __getattr__(self, name: str) -> t.Any: + return getattr(self._text_stream, name) + + def isatty(self) -> bool: + return self.buffer.isatty() + + def __repr__(self) -> str: + return f"" + + +def _get_text_stdin(buffer_stream: t.BinaryIO) -> t.TextIO: + text_stream = _NonClosingTextIOWrapper( + io.BufferedReader(_WindowsConsoleReader(STDIN_HANDLE)), + "utf-16-le", + "strict", + line_buffering=True, + ) + return t.cast(t.TextIO, ConsoleStream(text_stream, buffer_stream)) + + +def _get_text_stdout(buffer_stream: t.BinaryIO) -> t.TextIO: + text_stream = _NonClosingTextIOWrapper( + io.BufferedWriter(_WindowsConsoleWriter(STDOUT_HANDLE)), + "utf-16-le", + "strict", + line_buffering=True, + ) + return t.cast(t.TextIO, ConsoleStream(text_stream, buffer_stream)) + + +def _get_text_stderr(buffer_stream: t.BinaryIO) -> t.TextIO: + text_stream = _NonClosingTextIOWrapper( + io.BufferedWriter(_WindowsConsoleWriter(STDERR_HANDLE)), + "utf-16-le", + "strict", + line_buffering=True, + ) + return t.cast(t.TextIO, ConsoleStream(text_stream, buffer_stream)) + + +_stream_factories: cabc.Mapping[int, t.Callable[[t.BinaryIO], t.TextIO]] = { + 0: _get_text_stdin, + 1: _get_text_stdout, + 2: _get_text_stderr, +} + + +def _is_console(f: t.TextIO) -> bool: + if not hasattr(f, "fileno"): + return False + + try: + fileno = f.fileno() + except (OSError, io.UnsupportedOperation): + return False + + handle = msvcrt.get_osfhandle(fileno) + return bool(GetConsoleMode(handle, byref(DWORD()))) + + +def _get_windows_console_stream( + f: t.TextIO, encoding: str | None, errors: str | None +) -> t.TextIO | None: + if ( + get_buffer is None + or encoding not in {"utf-16-le", None} + or errors not in {"strict", None} + or not _is_console(f) + ): + return None + + func = _stream_factories.get(f.fileno()) + if func is None: + return None + + b = getattr(f, "buffer", None) + + if b is None: + return None + + return func(b) diff --git a/backend/venv/Lib/site-packages/click/core.py b/backend/venv/Lib/site-packages/click/core.py new file mode 100644 index 0000000..ff2f74a --- /dev/null +++ b/backend/venv/Lib/site-packages/click/core.py @@ -0,0 +1,3347 @@ +from __future__ import annotations + +import collections.abc as cabc +import enum +import errno +import inspect +import os +import sys +import typing as t +from collections import abc +from collections import Counter +from contextlib import AbstractContextManager +from contextlib import contextmanager +from contextlib import ExitStack +from functools import update_wrapper +from gettext import gettext as _ +from gettext import ngettext +from itertools import repeat +from types import TracebackType + +from . import types +from ._utils import FLAG_NEEDS_VALUE +from ._utils import UNSET +from .exceptions import Abort +from .exceptions import BadParameter +from .exceptions import ClickException +from .exceptions import Exit +from .exceptions import MissingParameter +from .exceptions import NoArgsIsHelpError +from .exceptions import UsageError +from .formatting import HelpFormatter +from .formatting import join_options +from .globals import pop_context +from .globals import push_context +from .parser import _OptionParser +from .parser import _split_opt +from .termui import confirm +from .termui import prompt +from .termui import style +from .utils import _detect_program_name +from .utils import _expand_args +from .utils import echo +from .utils import make_default_short_help +from .utils import make_str +from .utils import PacifyFlushWrapper + +if t.TYPE_CHECKING: + from .shell_completion import CompletionItem + +F = t.TypeVar("F", bound="t.Callable[..., t.Any]") +V = t.TypeVar("V") + + +def _complete_visible_commands( + ctx: Context, incomplete: str +) -> cabc.Iterator[tuple[str, Command]]: + """List all the subcommands of a group that start with the + incomplete value and aren't hidden. + + :param ctx: Invocation context for the group. + :param incomplete: Value being completed. May be empty. + """ + multi = t.cast(Group, ctx.command) + + for name in multi.list_commands(ctx): + if name.startswith(incomplete): + command = multi.get_command(ctx, name) + + if command is not None and not command.hidden: + yield name, command + + +def _check_nested_chain( + base_command: Group, cmd_name: str, cmd: Command, register: bool = False +) -> None: + if not base_command.chain or not isinstance(cmd, Group): + return + + if register: + message = ( + f"It is not possible to add the group {cmd_name!r} to another" + f" group {base_command.name!r} that is in chain mode." + ) + else: + message = ( + f"Found the group {cmd_name!r} as subcommand to another group " + f" {base_command.name!r} that is in chain mode. This is not supported." + ) + + raise RuntimeError(message) + + +def batch(iterable: cabc.Iterable[V], batch_size: int) -> list[tuple[V, ...]]: + return list(zip(*repeat(iter(iterable), batch_size), strict=False)) + + +@contextmanager +def augment_usage_errors( + ctx: Context, param: Parameter | None = None +) -> cabc.Iterator[None]: + """Context manager that attaches extra information to exceptions.""" + try: + yield + except BadParameter as e: + if e.ctx is None: + e.ctx = ctx + if param is not None and e.param is None: + e.param = param + raise + except UsageError as e: + if e.ctx is None: + e.ctx = ctx + raise + + +def iter_params_for_processing( + invocation_order: cabc.Sequence[Parameter], + declaration_order: cabc.Sequence[Parameter], +) -> list[Parameter]: + """Returns all declared parameters in the order they should be processed. + + The declared parameters are re-shuffled depending on the order in which + they were invoked, as well as the eagerness of each parameters. + + The invocation order takes precedence over the declaration order. I.e. the + order in which the user provided them to the CLI is respected. + + This behavior and its effect on callback evaluation is detailed at: + https://click.palletsprojects.com/en/stable/advanced/#callback-evaluation-order + """ + + def sort_key(item: Parameter) -> tuple[bool, float]: + try: + idx: float = invocation_order.index(item) + except ValueError: + idx = float("inf") + + return not item.is_eager, idx + + return sorted(declaration_order, key=sort_key) + + +class ParameterSource(enum.Enum): + """This is an :class:`~enum.Enum` that indicates the source of a + parameter's value. + + Use :meth:`click.Context.get_parameter_source` to get the + source for a parameter by name. + + .. versionchanged:: 8.0 + Use :class:`~enum.Enum` and drop the ``validate`` method. + + .. versionchanged:: 8.0 + Added the ``PROMPT`` value. + """ + + COMMANDLINE = enum.auto() + """The value was provided by the command line args.""" + ENVIRONMENT = enum.auto() + """The value was provided with an environment variable.""" + DEFAULT = enum.auto() + """Used the default specified by the parameter.""" + DEFAULT_MAP = enum.auto() + """Used a default provided by :attr:`Context.default_map`.""" + PROMPT = enum.auto() + """Used a prompt to confirm a default or provide a value.""" + + +class Context: + """The context is a special internal object that holds state relevant + for the script execution at every single level. It's normally invisible + to commands unless they opt-in to getting access to it. + + The context is useful as it can pass internal objects around and can + control special execution features such as reading data from + environment variables. + + A context can be used as context manager in which case it will call + :meth:`close` on teardown. + + :param command: the command class for this context. + :param parent: the parent context. + :param info_name: the info name for this invocation. Generally this + is the most descriptive name for the script or + command. For the toplevel script it is usually + the name of the script, for commands below it it's + the name of the script. + :param obj: an arbitrary object of user data. + :param auto_envvar_prefix: the prefix to use for automatic environment + variables. If this is `None` then reading + from environment variables is disabled. This + does not affect manually set environment + variables which are always read. + :param default_map: a dictionary (like object) with default values + for parameters. + :param terminal_width: the width of the terminal. The default is + inherit from parent context. If no context + defines the terminal width then auto + detection will be applied. + :param max_content_width: the maximum width for content rendered by + Click (this currently only affects help + pages). This defaults to 80 characters if + not overridden. In other words: even if the + terminal is larger than that, Click will not + format things wider than 80 characters by + default. In addition to that, formatters might + add some safety mapping on the right. + :param resilient_parsing: if this flag is enabled then Click will + parse without any interactivity or callback + invocation. Default values will also be + ignored. This is useful for implementing + things such as completion support. + :param allow_extra_args: if this is set to `True` then extra arguments + at the end will not raise an error and will be + kept on the context. The default is to inherit + from the command. + :param allow_interspersed_args: if this is set to `False` then options + and arguments cannot be mixed. The + default is to inherit from the command. + :param ignore_unknown_options: instructs click to ignore options it does + not know and keeps them for later + processing. + :param help_option_names: optionally a list of strings that define how + the default help parameter is named. The + default is ``['--help']``. + :param token_normalize_func: an optional function that is used to + normalize tokens (options, choices, + etc.). This for instance can be used to + implement case insensitive behavior. + :param color: controls if the terminal supports ANSI colors or not. The + default is autodetection. This is only needed if ANSI + codes are used in texts that Click prints which is by + default not the case. This for instance would affect + help output. + :param show_default: Show the default value for commands. If this + value is not set, it defaults to the value from the parent + context. ``Command.show_default`` overrides this default for the + specific command. + + .. versionchanged:: 8.2 + The ``protected_args`` attribute is deprecated and will be removed in + Click 9.0. ``args`` will contain remaining unparsed tokens. + + .. versionchanged:: 8.1 + The ``show_default`` parameter is overridden by + ``Command.show_default``, instead of the other way around. + + .. versionchanged:: 8.0 + The ``show_default`` parameter defaults to the value from the + parent context. + + .. versionchanged:: 7.1 + Added the ``show_default`` parameter. + + .. versionchanged:: 4.0 + Added the ``color``, ``ignore_unknown_options``, and + ``max_content_width`` parameters. + + .. versionchanged:: 3.0 + Added the ``allow_extra_args`` and ``allow_interspersed_args`` + parameters. + + .. versionchanged:: 2.0 + Added the ``resilient_parsing``, ``help_option_names``, and + ``token_normalize_func`` parameters. + """ + + #: The formatter class to create with :meth:`make_formatter`. + #: + #: .. versionadded:: 8.0 + formatter_class: type[HelpFormatter] = HelpFormatter + + def __init__( + self, + command: Command, + parent: Context | None = None, + info_name: str | None = None, + obj: t.Any | None = None, + auto_envvar_prefix: str | None = None, + default_map: cabc.MutableMapping[str, t.Any] | None = None, + terminal_width: int | None = None, + max_content_width: int | None = None, + resilient_parsing: bool = False, + allow_extra_args: bool | None = None, + allow_interspersed_args: bool | None = None, + ignore_unknown_options: bool | None = None, + help_option_names: list[str] | None = None, + token_normalize_func: t.Callable[[str], str] | None = None, + color: bool | None = None, + show_default: bool | None = None, + ) -> None: + #: the parent context or `None` if none exists. + self.parent = parent + #: the :class:`Command` for this context. + self.command = command + #: the descriptive information name + self.info_name = info_name + #: Map of parameter names to their parsed values. Parameters + #: with ``expose_value=False`` are not stored. + self.params: dict[str, t.Any] = {} + #: the leftover arguments. + self.args: list[str] = [] + #: protected arguments. These are arguments that are prepended + #: to `args` when certain parsing scenarios are encountered but + #: must be never propagated to another arguments. This is used + #: to implement nested parsing. + self._protected_args: list[str] = [] + #: the collected prefixes of the command's options. + self._opt_prefixes: set[str] = set(parent._opt_prefixes) if parent else set() + + if obj is None and parent is not None: + obj = parent.obj + + #: the user object stored. + self.obj: t.Any = obj + self._meta: dict[str, t.Any] = getattr(parent, "meta", {}) + + #: A dictionary (-like object) with defaults for parameters. + if ( + default_map is None + and info_name is not None + and parent is not None + and parent.default_map is not None + ): + default_map = parent.default_map.get(info_name) + + self.default_map: cabc.MutableMapping[str, t.Any] | None = default_map + + #: This flag indicates if a subcommand is going to be executed. A + #: group callback can use this information to figure out if it's + #: being executed directly or because the execution flow passes + #: onwards to a subcommand. By default it's None, but it can be + #: the name of the subcommand to execute. + #: + #: If chaining is enabled this will be set to ``'*'`` in case + #: any commands are executed. It is however not possible to + #: figure out which ones. If you require this knowledge you + #: should use a :func:`result_callback`. + self.invoked_subcommand: str | None = None + + if terminal_width is None and parent is not None: + terminal_width = parent.terminal_width + + #: The width of the terminal (None is autodetection). + self.terminal_width: int | None = terminal_width + + if max_content_width is None and parent is not None: + max_content_width = parent.max_content_width + + #: The maximum width of formatted content (None implies a sensible + #: default which is 80 for most things). + self.max_content_width: int | None = max_content_width + + if allow_extra_args is None: + allow_extra_args = command.allow_extra_args + + #: Indicates if the context allows extra args or if it should + #: fail on parsing. + #: + #: .. versionadded:: 3.0 + self.allow_extra_args = allow_extra_args + + if allow_interspersed_args is None: + allow_interspersed_args = command.allow_interspersed_args + + #: Indicates if the context allows mixing of arguments and + #: options or not. + #: + #: .. versionadded:: 3.0 + self.allow_interspersed_args: bool = allow_interspersed_args + + if ignore_unknown_options is None: + ignore_unknown_options = command.ignore_unknown_options + + #: Instructs click to ignore options that a command does not + #: understand and will store it on the context for later + #: processing. This is primarily useful for situations where you + #: want to call into external programs. Generally this pattern is + #: strongly discouraged because it's not possibly to losslessly + #: forward all arguments. + #: + #: .. versionadded:: 4.0 + self.ignore_unknown_options: bool = ignore_unknown_options + + if help_option_names is None: + if parent is not None: + help_option_names = parent.help_option_names + else: + help_option_names = ["--help"] + + #: The names for the help options. + self.help_option_names: list[str] = help_option_names + + if token_normalize_func is None and parent is not None: + token_normalize_func = parent.token_normalize_func + + #: An optional normalization function for tokens. This is + #: options, choices, commands etc. + self.token_normalize_func: t.Callable[[str], str] | None = token_normalize_func + + #: Indicates if resilient parsing is enabled. In that case Click + #: will do its best to not cause any failures and default values + #: will be ignored. Useful for completion. + self.resilient_parsing: bool = resilient_parsing + + # If there is no envvar prefix yet, but the parent has one and + # the command on this level has a name, we can expand the envvar + # prefix automatically. + if auto_envvar_prefix is None: + if ( + parent is not None + and parent.auto_envvar_prefix is not None + and self.info_name is not None + ): + auto_envvar_prefix = ( + f"{parent.auto_envvar_prefix}_{self.info_name.upper()}" + ) + else: + auto_envvar_prefix = auto_envvar_prefix.upper() + + if auto_envvar_prefix is not None: + auto_envvar_prefix = auto_envvar_prefix.replace("-", "_") + + self.auto_envvar_prefix: str | None = auto_envvar_prefix + + if color is None and parent is not None: + color = parent.color + + #: Controls if styling output is wanted or not. + self.color: bool | None = color + + if show_default is None and parent is not None: + show_default = parent.show_default + + #: Show option default values when formatting help text. + self.show_default: bool | None = show_default + + self._close_callbacks: list[t.Callable[[], t.Any]] = [] + self._depth = 0 + self._parameter_source: dict[str, ParameterSource] = {} + self._exit_stack = ExitStack() + + @property + def protected_args(self) -> list[str]: + import warnings + + warnings.warn( + "'protected_args' is deprecated and will be removed in Click 9.0." + " 'args' will contain remaining unparsed tokens.", + DeprecationWarning, + stacklevel=2, + ) + return self._protected_args + + def to_info_dict(self) -> dict[str, t.Any]: + """Gather information that could be useful for a tool generating + user-facing documentation. This traverses the entire CLI + structure. + + .. code-block:: python + + with Context(cli) as ctx: + info = ctx.to_info_dict() + + .. versionadded:: 8.0 + """ + return { + "command": self.command.to_info_dict(self), + "info_name": self.info_name, + "allow_extra_args": self.allow_extra_args, + "allow_interspersed_args": self.allow_interspersed_args, + "ignore_unknown_options": self.ignore_unknown_options, + "auto_envvar_prefix": self.auto_envvar_prefix, + } + + def __enter__(self) -> Context: + self._depth += 1 + push_context(self) + return self + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_value: BaseException | None, + tb: TracebackType | None, + ) -> bool | None: + self._depth -= 1 + exit_result: bool | None = None + if self._depth == 0: + exit_result = self._close_with_exception_info(exc_type, exc_value, tb) + pop_context() + + return exit_result + + @contextmanager + def scope(self, cleanup: bool = True) -> cabc.Iterator[Context]: + """This helper method can be used with the context object to promote + it to the current thread local (see :func:`get_current_context`). + The default behavior of this is to invoke the cleanup functions which + can be disabled by setting `cleanup` to `False`. The cleanup + functions are typically used for things such as closing file handles. + + If the cleanup is intended the context object can also be directly + used as a context manager. + + Example usage:: + + with ctx.scope(): + assert get_current_context() is ctx + + This is equivalent:: + + with ctx: + assert get_current_context() is ctx + + .. versionadded:: 5.0 + + :param cleanup: controls if the cleanup functions should be run or + not. The default is to run these functions. In + some situations the context only wants to be + temporarily pushed in which case this can be disabled. + Nested pushes automatically defer the cleanup. + """ + if not cleanup: + self._depth += 1 + try: + with self as rv: + yield rv + finally: + if not cleanup: + self._depth -= 1 + + @property + def meta(self) -> dict[str, t.Any]: + """This is a dictionary which is shared with all the contexts + that are nested. It exists so that click utilities can store some + state here if they need to. It is however the responsibility of + that code to manage this dictionary well. + + The keys are supposed to be unique dotted strings. For instance + module paths are a good choice for it. What is stored in there is + irrelevant for the operation of click. However what is important is + that code that places data here adheres to the general semantics of + the system. + + Example usage:: + + LANG_KEY = f'{__name__}.lang' + + def set_language(value): + ctx = get_current_context() + ctx.meta[LANG_KEY] = value + + def get_language(): + return get_current_context().meta.get(LANG_KEY, 'en_US') + + .. versionadded:: 5.0 + """ + return self._meta + + def make_formatter(self) -> HelpFormatter: + """Creates the :class:`~click.HelpFormatter` for the help and + usage output. + + To quickly customize the formatter class used without overriding + this method, set the :attr:`formatter_class` attribute. + + .. versionchanged:: 8.0 + Added the :attr:`formatter_class` attribute. + """ + return self.formatter_class( + width=self.terminal_width, max_width=self.max_content_width + ) + + def with_resource(self, context_manager: AbstractContextManager[V]) -> V: + """Register a resource as if it were used in a ``with`` + statement. The resource will be cleaned up when the context is + popped. + + Uses :meth:`contextlib.ExitStack.enter_context`. It calls the + resource's ``__enter__()`` method and returns the result. When + the context is popped, it closes the stack, which calls the + resource's ``__exit__()`` method. + + To register a cleanup function for something that isn't a + context manager, use :meth:`call_on_close`. Or use something + from :mod:`contextlib` to turn it into a context manager first. + + .. code-block:: python + + @click.group() + @click.option("--name") + @click.pass_context + def cli(ctx): + ctx.obj = ctx.with_resource(connect_db(name)) + + :param context_manager: The context manager to enter. + :return: Whatever ``context_manager.__enter__()`` returns. + + .. versionadded:: 8.0 + """ + return self._exit_stack.enter_context(context_manager) + + def call_on_close(self, f: t.Callable[..., t.Any]) -> t.Callable[..., t.Any]: + """Register a function to be called when the context tears down. + + This can be used to close resources opened during the script + execution. Resources that support Python's context manager + protocol which would be used in a ``with`` statement should be + registered with :meth:`with_resource` instead. + + :param f: The function to execute on teardown. + """ + return self._exit_stack.callback(f) + + def close(self) -> None: + """Invoke all close callbacks registered with + :meth:`call_on_close`, and exit all context managers entered + with :meth:`with_resource`. + """ + self._close_with_exception_info(None, None, None) + + def _close_with_exception_info( + self, + exc_type: type[BaseException] | None, + exc_value: BaseException | None, + tb: TracebackType | None, + ) -> bool | None: + """Unwind the exit stack by calling its :meth:`__exit__` providing the exception + information to allow for exception handling by the various resources registered + using :meth;`with_resource` + + :return: Whatever ``exit_stack.__exit__()`` returns. + """ + exit_result = self._exit_stack.__exit__(exc_type, exc_value, tb) + # In case the context is reused, create a new exit stack. + self._exit_stack = ExitStack() + + return exit_result + + @property + def command_path(self) -> str: + """The computed command path. This is used for the ``usage`` + information on the help page. It's automatically created by + combining the info names of the chain of contexts to the root. + """ + rv = "" + if self.info_name is not None: + rv = self.info_name + if self.parent is not None: + parent_command_path = [self.parent.command_path] + + if isinstance(self.parent.command, Command): + for param in self.parent.command.get_params(self): + parent_command_path.extend(param.get_usage_pieces(self)) + + rv = f"{' '.join(parent_command_path)} {rv}" + return rv.lstrip() + + def find_root(self) -> Context: + """Finds the outermost context.""" + node = self + while node.parent is not None: + node = node.parent + return node + + def find_object(self, object_type: type[V]) -> V | None: + """Finds the closest object of a given type.""" + node: Context | None = self + + while node is not None: + if isinstance(node.obj, object_type): + return node.obj + + node = node.parent + + return None + + def ensure_object(self, object_type: type[V]) -> V: + """Like :meth:`find_object` but sets the innermost object to a + new instance of `object_type` if it does not exist. + """ + rv = self.find_object(object_type) + if rv is None: + self.obj = rv = object_type() + return rv + + @t.overload + def lookup_default( + self, name: str, call: t.Literal[True] = True + ) -> t.Any | None: ... + + @t.overload + def lookup_default( + self, name: str, call: t.Literal[False] = ... + ) -> t.Any | t.Callable[[], t.Any] | None: ... + + def lookup_default(self, name: str, call: bool = True) -> t.Any | None: + """Get the default for a parameter from :attr:`default_map`. + + :param name: Name of the parameter. + :param call: If the default is a callable, call it. Disable to + return the callable instead. + + .. versionchanged:: 8.0 + Added the ``call`` parameter. + """ + if self.default_map is not None: + value = self.default_map.get(name, UNSET) + + if call and callable(value): + return value() + + return value + + return UNSET + + def fail(self, message: str) -> t.NoReturn: + """Aborts the execution of the program with a specific error + message. + + :param message: the error message to fail with. + """ + raise UsageError(message, self) + + def abort(self) -> t.NoReturn: + """Aborts the script.""" + raise Abort() + + def exit(self, code: int = 0) -> t.NoReturn: + """Exits the application with a given exit code. + + .. versionchanged:: 8.2 + Callbacks and context managers registered with :meth:`call_on_close` + and :meth:`with_resource` are closed before exiting. + """ + self.close() + raise Exit(code) + + def get_usage(self) -> str: + """Helper method to get formatted usage string for the current + context and command. + """ + return self.command.get_usage(self) + + def get_help(self) -> str: + """Helper method to get formatted help page for the current + context and command. + """ + return self.command.get_help(self) + + def _make_sub_context(self, command: Command) -> Context: + """Create a new context of the same type as this context, but + for a new command. + + :meta private: + """ + return type(self)(command, info_name=command.name, parent=self) + + @t.overload + def invoke( + self, callback: t.Callable[..., V], /, *args: t.Any, **kwargs: t.Any + ) -> V: ... + + @t.overload + def invoke(self, callback: Command, /, *args: t.Any, **kwargs: t.Any) -> t.Any: ... + + def invoke( + self, callback: Command | t.Callable[..., V], /, *args: t.Any, **kwargs: t.Any + ) -> t.Any | V: + """Invokes a command callback in exactly the way it expects. There + are two ways to invoke this method: + + 1. the first argument can be a callback and all other arguments and + keyword arguments are forwarded directly to the function. + 2. the first argument is a click command object. In that case all + arguments are forwarded as well but proper click parameters + (options and click arguments) must be keyword arguments and Click + will fill in defaults. + + .. versionchanged:: 8.0 + All ``kwargs`` are tracked in :attr:`params` so they will be + passed if :meth:`forward` is called at multiple levels. + + .. versionchanged:: 3.2 + A new context is created, and missing arguments use default values. + """ + if isinstance(callback, Command): + other_cmd = callback + + if other_cmd.callback is None: + raise TypeError( + "The given command does not have a callback that can be invoked." + ) + else: + callback = t.cast("t.Callable[..., V]", other_cmd.callback) + + ctx = self._make_sub_context(other_cmd) + + for param in other_cmd.params: + if param.name not in kwargs and param.expose_value: + kwargs[param.name] = param.type_cast_value( # type: ignore + ctx, param.get_default(ctx) + ) + + # Track all kwargs as params, so that forward() will pass + # them on in subsequent calls. + ctx.params.update(kwargs) + else: + ctx = self + + with augment_usage_errors(self): + with ctx: + return callback(*args, **kwargs) + + def forward(self, cmd: Command, /, *args: t.Any, **kwargs: t.Any) -> t.Any: + """Similar to :meth:`invoke` but fills in default keyword + arguments from the current context if the other command expects + it. This cannot invoke callbacks directly, only other commands. + + .. versionchanged:: 8.0 + All ``kwargs`` are tracked in :attr:`params` so they will be + passed if ``forward`` is called at multiple levels. + """ + # Can only forward to other commands, not direct callbacks. + if not isinstance(cmd, Command): + raise TypeError("Callback is not a command.") + + for param in self.params: + if param not in kwargs: + kwargs[param] = self.params[param] + + return self.invoke(cmd, *args, **kwargs) + + def set_parameter_source(self, name: str, source: ParameterSource) -> None: + """Set the source of a parameter. This indicates the location + from which the value of the parameter was obtained. + + :param name: The name of the parameter. + :param source: A member of :class:`~click.core.ParameterSource`. + """ + self._parameter_source[name] = source + + def get_parameter_source(self, name: str) -> ParameterSource | None: + """Get the source of a parameter. This indicates the location + from which the value of the parameter was obtained. + + This can be useful for determining when a user specified a value + on the command line that is the same as the default value. It + will be :attr:`~click.core.ParameterSource.DEFAULT` only if the + value was actually taken from the default. + + :param name: The name of the parameter. + :rtype: ParameterSource + + .. versionchanged:: 8.0 + Returns ``None`` if the parameter was not provided from any + source. + """ + return self._parameter_source.get(name) + + +class Command: + """Commands are the basic building block of command line interfaces in + Click. A basic command handles command line parsing and might dispatch + more parsing to commands nested below it. + + :param name: the name of the command to use unless a group overrides it. + :param context_settings: an optional dictionary with defaults that are + passed to the context object. + :param callback: the callback to invoke. This is optional. + :param params: the parameters to register with this command. This can + be either :class:`Option` or :class:`Argument` objects. + :param help: the help string to use for this command. + :param epilog: like the help string but it's printed at the end of the + help page after everything else. + :param short_help: the short help to use for this command. This is + shown on the command listing of the parent command. + :param add_help_option: by default each command registers a ``--help`` + option. This can be disabled by this parameter. + :param no_args_is_help: this controls what happens if no arguments are + provided. This option is disabled by default. + If enabled this will add ``--help`` as argument + if no arguments are passed + :param hidden: hide this command from help outputs. + :param deprecated: If ``True`` or non-empty string, issues a message + indicating that the command is deprecated and highlights + its deprecation in --help. The message can be customized + by using a string as the value. + + .. versionchanged:: 8.2 + This is the base class for all commands, not ``BaseCommand``. + ``deprecated`` can be set to a string as well to customize the + deprecation message. + + .. versionchanged:: 8.1 + ``help``, ``epilog``, and ``short_help`` are stored unprocessed, + all formatting is done when outputting help text, not at init, + and is done even if not using the ``@command`` decorator. + + .. versionchanged:: 8.0 + Added a ``repr`` showing the command name. + + .. versionchanged:: 7.1 + Added the ``no_args_is_help`` parameter. + + .. versionchanged:: 2.0 + Added the ``context_settings`` parameter. + """ + + #: The context class to create with :meth:`make_context`. + #: + #: .. versionadded:: 8.0 + context_class: type[Context] = Context + + #: the default for the :attr:`Context.allow_extra_args` flag. + allow_extra_args = False + + #: the default for the :attr:`Context.allow_interspersed_args` flag. + allow_interspersed_args = True + + #: the default for the :attr:`Context.ignore_unknown_options` flag. + ignore_unknown_options = False + + def __init__( + self, + name: str | None, + context_settings: cabc.MutableMapping[str, t.Any] | None = None, + callback: t.Callable[..., t.Any] | None = None, + params: list[Parameter] | None = None, + help: str | None = None, + epilog: str | None = None, + short_help: str | None = None, + options_metavar: str | None = "[OPTIONS]", + add_help_option: bool = True, + no_args_is_help: bool = False, + hidden: bool = False, + deprecated: bool | str = False, + ) -> None: + #: the name the command thinks it has. Upon registering a command + #: on a :class:`Group` the group will default the command name + #: with this information. You should instead use the + #: :class:`Context`\'s :attr:`~Context.info_name` attribute. + self.name = name + + if context_settings is None: + context_settings = {} + + #: an optional dictionary with defaults passed to the context. + self.context_settings: cabc.MutableMapping[str, t.Any] = context_settings + + #: the callback to execute when the command fires. This might be + #: `None` in which case nothing happens. + self.callback = callback + #: the list of parameters for this command in the order they + #: should show up in the help page and execute. Eager parameters + #: will automatically be handled before non eager ones. + self.params: list[Parameter] = params or [] + self.help = help + self.epilog = epilog + self.options_metavar = options_metavar + self.short_help = short_help + self.add_help_option = add_help_option + self._help_option = None + self.no_args_is_help = no_args_is_help + self.hidden = hidden + self.deprecated = deprecated + + def to_info_dict(self, ctx: Context) -> dict[str, t.Any]: + return { + "name": self.name, + "params": [param.to_info_dict() for param in self.get_params(ctx)], + "help": self.help, + "epilog": self.epilog, + "short_help": self.short_help, + "hidden": self.hidden, + "deprecated": self.deprecated, + } + + def __repr__(self) -> str: + return f"<{self.__class__.__name__} {self.name}>" + + def get_usage(self, ctx: Context) -> str: + """Formats the usage line into a string and returns it. + + Calls :meth:`format_usage` internally. + """ + formatter = ctx.make_formatter() + self.format_usage(ctx, formatter) + return formatter.getvalue().rstrip("\n") + + def get_params(self, ctx: Context) -> list[Parameter]: + params = self.params + help_option = self.get_help_option(ctx) + + if help_option is not None: + params = [*params, help_option] + + if __debug__: + import warnings + + opts = [opt for param in params for opt in param.opts] + opts_counter = Counter(opts) + duplicate_opts = (opt for opt, count in opts_counter.items() if count > 1) + + for duplicate_opt in duplicate_opts: + warnings.warn( + ( + f"The parameter {duplicate_opt} is used more than once. " + "Remove its duplicate as parameters should be unique." + ), + stacklevel=3, + ) + + return params + + def format_usage(self, ctx: Context, formatter: HelpFormatter) -> None: + """Writes the usage line into the formatter. + + This is a low-level method called by :meth:`get_usage`. + """ + pieces = self.collect_usage_pieces(ctx) + formatter.write_usage(ctx.command_path, " ".join(pieces)) + + def collect_usage_pieces(self, ctx: Context) -> list[str]: + """Returns all the pieces that go into the usage line and returns + it as a list of strings. + """ + rv = [self.options_metavar] if self.options_metavar else [] + + for param in self.get_params(ctx): + rv.extend(param.get_usage_pieces(ctx)) + + return rv + + def get_help_option_names(self, ctx: Context) -> list[str]: + """Returns the names for the help option.""" + all_names = set(ctx.help_option_names) + for param in self.params: + all_names.difference_update(param.opts) + all_names.difference_update(param.secondary_opts) + return list(all_names) + + def get_help_option(self, ctx: Context) -> Option | None: + """Returns the help option object. + + Skipped if :attr:`add_help_option` is ``False``. + + .. versionchanged:: 8.1.8 + The help option is now cached to avoid creating it multiple times. + """ + help_option_names = self.get_help_option_names(ctx) + + if not help_option_names or not self.add_help_option: + return None + + # Cache the help option object in private _help_option attribute to + # avoid creating it multiple times. Not doing this will break the + # callback odering by iter_params_for_processing(), which relies on + # object comparison. + if self._help_option is None: + # Avoid circular import. + from .decorators import help_option + + # Apply help_option decorator and pop resulting option + help_option(*help_option_names)(self) + self._help_option = self.params.pop() # type: ignore[assignment] + + return self._help_option + + def make_parser(self, ctx: Context) -> _OptionParser: + """Creates the underlying option parser for this command.""" + parser = _OptionParser(ctx) + for param in self.get_params(ctx): + param.add_to_parser(parser, ctx) + return parser + + def get_help(self, ctx: Context) -> str: + """Formats the help into a string and returns it. + + Calls :meth:`format_help` internally. + """ + formatter = ctx.make_formatter() + self.format_help(ctx, formatter) + return formatter.getvalue().rstrip("\n") + + def get_short_help_str(self, limit: int = 45) -> str: + """Gets short help for the command or makes it by shortening the + long help string. + """ + if self.short_help: + text = inspect.cleandoc(self.short_help) + elif self.help: + text = make_default_short_help(self.help, limit) + else: + text = "" + + if self.deprecated: + deprecated_message = ( + f"(DEPRECATED: {self.deprecated})" + if isinstance(self.deprecated, str) + else "(DEPRECATED)" + ) + text = _("{text} {deprecated_message}").format( + text=text, deprecated_message=deprecated_message + ) + + return text.strip() + + def format_help(self, ctx: Context, formatter: HelpFormatter) -> None: + """Writes the help into the formatter if it exists. + + This is a low-level method called by :meth:`get_help`. + + This calls the following methods: + + - :meth:`format_usage` + - :meth:`format_help_text` + - :meth:`format_options` + - :meth:`format_epilog` + """ + self.format_usage(ctx, formatter) + self.format_help_text(ctx, formatter) + self.format_options(ctx, formatter) + self.format_epilog(ctx, formatter) + + def format_help_text(self, ctx: Context, formatter: HelpFormatter) -> None: + """Writes the help text to the formatter if it exists.""" + if self.help is not None: + # truncate the help text to the first form feed + text = inspect.cleandoc(self.help).partition("\f")[0] + else: + text = "" + + if self.deprecated: + deprecated_message = ( + f"(DEPRECATED: {self.deprecated})" + if isinstance(self.deprecated, str) + else "(DEPRECATED)" + ) + text = _("{text} {deprecated_message}").format( + text=text, deprecated_message=deprecated_message + ) + + if text: + formatter.write_paragraph() + + with formatter.indentation(): + formatter.write_text(text) + + def format_options(self, ctx: Context, formatter: HelpFormatter) -> None: + """Writes all the options into the formatter if they exist.""" + opts = [] + for param in self.get_params(ctx): + rv = param.get_help_record(ctx) + if rv is not None: + opts.append(rv) + + if opts: + with formatter.section(_("Options")): + formatter.write_dl(opts) + + def format_epilog(self, ctx: Context, formatter: HelpFormatter) -> None: + """Writes the epilog into the formatter if it exists.""" + if self.epilog: + epilog = inspect.cleandoc(self.epilog) + formatter.write_paragraph() + + with formatter.indentation(): + formatter.write_text(epilog) + + def make_context( + self, + info_name: str | None, + args: list[str], + parent: Context | None = None, + **extra: t.Any, + ) -> Context: + """This function when given an info name and arguments will kick + off the parsing and create a new :class:`Context`. It does not + invoke the actual command callback though. + + To quickly customize the context class used without overriding + this method, set the :attr:`context_class` attribute. + + :param info_name: the info name for this invocation. Generally this + is the most descriptive name for the script or + command. For the toplevel script it's usually + the name of the script, for commands below it's + the name of the command. + :param args: the arguments to parse as list of strings. + :param parent: the parent context if available. + :param extra: extra keyword arguments forwarded to the context + constructor. + + .. versionchanged:: 8.0 + Added the :attr:`context_class` attribute. + """ + for key, value in self.context_settings.items(): + if key not in extra: + extra[key] = value + + ctx = self.context_class(self, info_name=info_name, parent=parent, **extra) + + with ctx.scope(cleanup=False): + self.parse_args(ctx, args) + return ctx + + def parse_args(self, ctx: Context, args: list[str]) -> list[str]: + if not args and self.no_args_is_help and not ctx.resilient_parsing: + raise NoArgsIsHelpError(ctx) + + parser = self.make_parser(ctx) + opts, args, param_order = parser.parse_args(args=args) + + for param in iter_params_for_processing(param_order, self.get_params(ctx)): + _, args = param.handle_parse_result(ctx, opts, args) + + if args and not ctx.allow_extra_args and not ctx.resilient_parsing: + ctx.fail( + ngettext( + "Got unexpected extra argument ({args})", + "Got unexpected extra arguments ({args})", + len(args), + ).format(args=" ".join(map(str, args))) + ) + + ctx.args = args + ctx._opt_prefixes.update(parser._opt_prefixes) + return args + + def invoke(self, ctx: Context) -> t.Any: + """Given a context, this invokes the attached callback (if it exists) + in the right way. + """ + if self.deprecated: + extra_message = ( + f" {self.deprecated}" if isinstance(self.deprecated, str) else "" + ) + message = _( + "DeprecationWarning: The command {name!r} is deprecated.{extra_message}" + ).format(name=self.name, extra_message=extra_message) + echo(style(message, fg="red"), err=True) + + if self.callback is not None: + return ctx.invoke(self.callback, **ctx.params) + + def shell_complete(self, ctx: Context, incomplete: str) -> list[CompletionItem]: + """Return a list of completions for the incomplete value. Looks + at the names of options and chained multi-commands. + + Any command could be part of a chained multi-command, so sibling + commands are valid at any point during command completion. + + :param ctx: Invocation context for this command. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + results: list[CompletionItem] = [] + + if incomplete and not incomplete[0].isalnum(): + for param in self.get_params(ctx): + if ( + not isinstance(param, Option) + or param.hidden + or ( + not param.multiple + and ctx.get_parameter_source(param.name) # type: ignore + is ParameterSource.COMMANDLINE + ) + ): + continue + + results.extend( + CompletionItem(name, help=param.help) + for name in [*param.opts, *param.secondary_opts] + if name.startswith(incomplete) + ) + + while ctx.parent is not None: + ctx = ctx.parent + + if isinstance(ctx.command, Group) and ctx.command.chain: + results.extend( + CompletionItem(name, help=command.get_short_help_str()) + for name, command in _complete_visible_commands(ctx, incomplete) + if name not in ctx._protected_args + ) + + return results + + @t.overload + def main( + self, + args: cabc.Sequence[str] | None = None, + prog_name: str | None = None, + complete_var: str | None = None, + standalone_mode: t.Literal[True] = True, + **extra: t.Any, + ) -> t.NoReturn: ... + + @t.overload + def main( + self, + args: cabc.Sequence[str] | None = None, + prog_name: str | None = None, + complete_var: str | None = None, + standalone_mode: bool = ..., + **extra: t.Any, + ) -> t.Any: ... + + def main( + self, + args: cabc.Sequence[str] | None = None, + prog_name: str | None = None, + complete_var: str | None = None, + standalone_mode: bool = True, + windows_expand_args: bool = True, + **extra: t.Any, + ) -> t.Any: + """This is the way to invoke a script with all the bells and + whistles as a command line application. This will always terminate + the application after a call. If this is not wanted, ``SystemExit`` + needs to be caught. + + This method is also available by directly calling the instance of + a :class:`Command`. + + :param args: the arguments that should be used for parsing. If not + provided, ``sys.argv[1:]`` is used. + :param prog_name: the program name that should be used. By default + the program name is constructed by taking the file + name from ``sys.argv[0]``. + :param complete_var: the environment variable that controls the + bash completion support. The default is + ``"__COMPLETE"`` with prog_name in + uppercase. + :param standalone_mode: the default behavior is to invoke the script + in standalone mode. Click will then + handle exceptions and convert them into + error messages and the function will never + return but shut down the interpreter. If + this is set to `False` they will be + propagated to the caller and the return + value of this function is the return value + of :meth:`invoke`. + :param windows_expand_args: Expand glob patterns, user dir, and + env vars in command line args on Windows. + :param extra: extra keyword arguments are forwarded to the context + constructor. See :class:`Context` for more information. + + .. versionchanged:: 8.0.1 + Added the ``windows_expand_args`` parameter to allow + disabling command line arg expansion on Windows. + + .. versionchanged:: 8.0 + When taking arguments from ``sys.argv`` on Windows, glob + patterns, user dir, and env vars are expanded. + + .. versionchanged:: 3.0 + Added the ``standalone_mode`` parameter. + """ + if args is None: + args = sys.argv[1:] + + if os.name == "nt" and windows_expand_args: + args = _expand_args(args) + else: + args = list(args) + + if prog_name is None: + prog_name = _detect_program_name() + + # Process shell completion requests and exit early. + self._main_shell_completion(extra, prog_name, complete_var) + + try: + try: + with self.make_context(prog_name, args, **extra) as ctx: + rv = self.invoke(ctx) + if not standalone_mode: + return rv + # it's not safe to `ctx.exit(rv)` here! + # note that `rv` may actually contain data like "1" which + # has obvious effects + # more subtle case: `rv=[None, None]` can come out of + # chained commands which all returned `None` -- so it's not + # even always obvious that `rv` indicates success/failure + # by its truthiness/falsiness + ctx.exit() + except (EOFError, KeyboardInterrupt) as e: + echo(file=sys.stderr) + raise Abort() from e + except ClickException as e: + if not standalone_mode: + raise + e.show() + sys.exit(e.exit_code) + except OSError as e: + if e.errno == errno.EPIPE: + sys.stdout = t.cast(t.TextIO, PacifyFlushWrapper(sys.stdout)) + sys.stderr = t.cast(t.TextIO, PacifyFlushWrapper(sys.stderr)) + sys.exit(1) + else: + raise + except Exit as e: + if standalone_mode: + sys.exit(e.exit_code) + else: + # in non-standalone mode, return the exit code + # note that this is only reached if `self.invoke` above raises + # an Exit explicitly -- thus bypassing the check there which + # would return its result + # the results of non-standalone execution may therefore be + # somewhat ambiguous: if there are codepaths which lead to + # `ctx.exit(1)` and to `return 1`, the caller won't be able to + # tell the difference between the two + return e.exit_code + except Abort: + if not standalone_mode: + raise + echo(_("Aborted!"), file=sys.stderr) + sys.exit(1) + + def _main_shell_completion( + self, + ctx_args: cabc.MutableMapping[str, t.Any], + prog_name: str, + complete_var: str | None = None, + ) -> None: + """Check if the shell is asking for tab completion, process + that, then exit early. Called from :meth:`main` before the + program is invoked. + + :param prog_name: Name of the executable in the shell. + :param complete_var: Name of the environment variable that holds + the completion instruction. Defaults to + ``_{PROG_NAME}_COMPLETE``. + + .. versionchanged:: 8.2.0 + Dots (``.``) in ``prog_name`` are replaced with underscores (``_``). + """ + if complete_var is None: + complete_name = prog_name.replace("-", "_").replace(".", "_") + complete_var = f"_{complete_name}_COMPLETE".upper() + + instruction = os.environ.get(complete_var) + + if not instruction: + return + + from .shell_completion import shell_complete + + rv = shell_complete(self, ctx_args, prog_name, complete_var, instruction) + sys.exit(rv) + + def __call__(self, *args: t.Any, **kwargs: t.Any) -> t.Any: + """Alias for :meth:`main`.""" + return self.main(*args, **kwargs) + + +class _FakeSubclassCheck(type): + def __subclasscheck__(cls, subclass: type) -> bool: + return issubclass(subclass, cls.__bases__[0]) + + def __instancecheck__(cls, instance: t.Any) -> bool: + return isinstance(instance, cls.__bases__[0]) + + +class _BaseCommand(Command, metaclass=_FakeSubclassCheck): + """ + .. deprecated:: 8.2 + Will be removed in Click 9.0. Use ``Command`` instead. + """ + + +class Group(Command): + """A group is a command that nests other commands (or more groups). + + :param name: The name of the group command. + :param commands: Map names to :class:`Command` objects. Can be a list, which + will use :attr:`Command.name` as the keys. + :param invoke_without_command: Invoke the group's callback even if a + subcommand is not given. + :param no_args_is_help: If no arguments are given, show the group's help and + exit. Defaults to the opposite of ``invoke_without_command``. + :param subcommand_metavar: How to represent the subcommand argument in help. + The default will represent whether ``chain`` is set or not. + :param chain: Allow passing more than one subcommand argument. After parsing + a command's arguments, if any arguments remain another command will be + matched, and so on. + :param result_callback: A function to call after the group's and + subcommand's callbacks. The value returned by the subcommand is passed. + If ``chain`` is enabled, the value will be a list of values returned by + all the commands. If ``invoke_without_command`` is enabled, the value + will be the value returned by the group's callback, or an empty list if + ``chain`` is enabled. + :param kwargs: Other arguments passed to :class:`Command`. + + .. versionchanged:: 8.0 + The ``commands`` argument can be a list of command objects. + + .. versionchanged:: 8.2 + Merged with and replaces the ``MultiCommand`` base class. + """ + + allow_extra_args = True + allow_interspersed_args = False + + #: If set, this is used by the group's :meth:`command` decorator + #: as the default :class:`Command` class. This is useful to make all + #: subcommands use a custom command class. + #: + #: .. versionadded:: 8.0 + command_class: type[Command] | None = None + + #: If set, this is used by the group's :meth:`group` decorator + #: as the default :class:`Group` class. This is useful to make all + #: subgroups use a custom group class. + #: + #: If set to the special value :class:`type` (literally + #: ``group_class = type``), this group's class will be used as the + #: default class. This makes a custom group class continue to make + #: custom groups. + #: + #: .. versionadded:: 8.0 + group_class: type[Group] | type[type] | None = None + # Literal[type] isn't valid, so use Type[type] + + def __init__( + self, + name: str | None = None, + commands: cabc.MutableMapping[str, Command] + | cabc.Sequence[Command] + | None = None, + invoke_without_command: bool = False, + no_args_is_help: bool | None = None, + subcommand_metavar: str | None = None, + chain: bool = False, + result_callback: t.Callable[..., t.Any] | None = None, + **kwargs: t.Any, + ) -> None: + super().__init__(name, **kwargs) + + if commands is None: + commands = {} + elif isinstance(commands, abc.Sequence): + commands = {c.name: c for c in commands if c.name is not None} + + #: The registered subcommands by their exported names. + self.commands: cabc.MutableMapping[str, Command] = commands + + if no_args_is_help is None: + no_args_is_help = not invoke_without_command + + self.no_args_is_help = no_args_is_help + self.invoke_without_command = invoke_without_command + + if subcommand_metavar is None: + if chain: + subcommand_metavar = "COMMAND1 [ARGS]... [COMMAND2 [ARGS]...]..." + else: + subcommand_metavar = "COMMAND [ARGS]..." + + self.subcommand_metavar = subcommand_metavar + self.chain = chain + # The result callback that is stored. This can be set or + # overridden with the :func:`result_callback` decorator. + self._result_callback = result_callback + + if self.chain: + for param in self.params: + if isinstance(param, Argument) and not param.required: + raise RuntimeError( + "A group in chain mode cannot have optional arguments." + ) + + def to_info_dict(self, ctx: Context) -> dict[str, t.Any]: + info_dict = super().to_info_dict(ctx) + commands = {} + + for name in self.list_commands(ctx): + command = self.get_command(ctx, name) + + if command is None: + continue + + sub_ctx = ctx._make_sub_context(command) + + with sub_ctx.scope(cleanup=False): + commands[name] = command.to_info_dict(sub_ctx) + + info_dict.update(commands=commands, chain=self.chain) + return info_dict + + def add_command(self, cmd: Command, name: str | None = None) -> None: + """Registers another :class:`Command` with this group. If the name + is not provided, the name of the command is used. + """ + name = name or cmd.name + if name is None: + raise TypeError("Command has no name.") + _check_nested_chain(self, name, cmd, register=True) + self.commands[name] = cmd + + @t.overload + def command(self, __func: t.Callable[..., t.Any]) -> Command: ... + + @t.overload + def command( + self, *args: t.Any, **kwargs: t.Any + ) -> t.Callable[[t.Callable[..., t.Any]], Command]: ... + + def command( + self, *args: t.Any, **kwargs: t.Any + ) -> t.Callable[[t.Callable[..., t.Any]], Command] | Command: + """A shortcut decorator for declaring and attaching a command to + the group. This takes the same arguments as :func:`command` and + immediately registers the created command with this group by + calling :meth:`add_command`. + + To customize the command class used, set the + :attr:`command_class` attribute. + + .. versionchanged:: 8.1 + This decorator can be applied without parentheses. + + .. versionchanged:: 8.0 + Added the :attr:`command_class` attribute. + """ + from .decorators import command + + func: t.Callable[..., t.Any] | None = None + + if args and callable(args[0]): + assert len(args) == 1 and not kwargs, ( + "Use 'command(**kwargs)(callable)' to provide arguments." + ) + (func,) = args + args = () + + if self.command_class and kwargs.get("cls") is None: + kwargs["cls"] = self.command_class + + def decorator(f: t.Callable[..., t.Any]) -> Command: + cmd: Command = command(*args, **kwargs)(f) + self.add_command(cmd) + return cmd + + if func is not None: + return decorator(func) + + return decorator + + @t.overload + def group(self, __func: t.Callable[..., t.Any]) -> Group: ... + + @t.overload + def group( + self, *args: t.Any, **kwargs: t.Any + ) -> t.Callable[[t.Callable[..., t.Any]], Group]: ... + + def group( + self, *args: t.Any, **kwargs: t.Any + ) -> t.Callable[[t.Callable[..., t.Any]], Group] | Group: + """A shortcut decorator for declaring and attaching a group to + the group. This takes the same arguments as :func:`group` and + immediately registers the created group with this group by + calling :meth:`add_command`. + + To customize the group class used, set the :attr:`group_class` + attribute. + + .. versionchanged:: 8.1 + This decorator can be applied without parentheses. + + .. versionchanged:: 8.0 + Added the :attr:`group_class` attribute. + """ + from .decorators import group + + func: t.Callable[..., t.Any] | None = None + + if args and callable(args[0]): + assert len(args) == 1 and not kwargs, ( + "Use 'group(**kwargs)(callable)' to provide arguments." + ) + (func,) = args + args = () + + if self.group_class is not None and kwargs.get("cls") is None: + if self.group_class is type: + kwargs["cls"] = type(self) + else: + kwargs["cls"] = self.group_class + + def decorator(f: t.Callable[..., t.Any]) -> Group: + cmd: Group = group(*args, **kwargs)(f) + self.add_command(cmd) + return cmd + + if func is not None: + return decorator(func) + + return decorator + + def result_callback(self, replace: bool = False) -> t.Callable[[F], F]: + """Adds a result callback to the command. By default if a + result callback is already registered this will chain them but + this can be disabled with the `replace` parameter. The result + callback is invoked with the return value of the subcommand + (or the list of return values from all subcommands if chaining + is enabled) as well as the parameters as they would be passed + to the main callback. + + Example:: + + @click.group() + @click.option('-i', '--input', default=23) + def cli(input): + return 42 + + @cli.result_callback() + def process_result(result, input): + return result + input + + :param replace: if set to `True` an already existing result + callback will be removed. + + .. versionchanged:: 8.0 + Renamed from ``resultcallback``. + + .. versionadded:: 3.0 + """ + + def decorator(f: F) -> F: + old_callback = self._result_callback + + if old_callback is None or replace: + self._result_callback = f + return f + + def function(value: t.Any, /, *args: t.Any, **kwargs: t.Any) -> t.Any: + inner = old_callback(value, *args, **kwargs) + return f(inner, *args, **kwargs) + + self._result_callback = rv = update_wrapper(t.cast(F, function), f) + return rv # type: ignore[return-value] + + return decorator + + def get_command(self, ctx: Context, cmd_name: str) -> Command | None: + """Given a context and a command name, this returns a :class:`Command` + object if it exists or returns ``None``. + """ + return self.commands.get(cmd_name) + + def list_commands(self, ctx: Context) -> list[str]: + """Returns a list of subcommand names in the order they should appear.""" + return sorted(self.commands) + + def collect_usage_pieces(self, ctx: Context) -> list[str]: + rv = super().collect_usage_pieces(ctx) + rv.append(self.subcommand_metavar) + return rv + + def format_options(self, ctx: Context, formatter: HelpFormatter) -> None: + super().format_options(ctx, formatter) + self.format_commands(ctx, formatter) + + def format_commands(self, ctx: Context, formatter: HelpFormatter) -> None: + """Extra format methods for multi methods that adds all the commands + after the options. + """ + commands = [] + for subcommand in self.list_commands(ctx): + cmd = self.get_command(ctx, subcommand) + # What is this, the tool lied about a command. Ignore it + if cmd is None: + continue + if cmd.hidden: + continue + + commands.append((subcommand, cmd)) + + # allow for 3 times the default spacing + if len(commands): + limit = formatter.width - 6 - max(len(cmd[0]) for cmd in commands) + + rows = [] + for subcommand, cmd in commands: + help = cmd.get_short_help_str(limit) + rows.append((subcommand, help)) + + if rows: + with formatter.section(_("Commands")): + formatter.write_dl(rows) + + def parse_args(self, ctx: Context, args: list[str]) -> list[str]: + if not args and self.no_args_is_help and not ctx.resilient_parsing: + raise NoArgsIsHelpError(ctx) + + rest = super().parse_args(ctx, args) + + if self.chain: + ctx._protected_args = rest + ctx.args = [] + elif rest: + ctx._protected_args, ctx.args = rest[:1], rest[1:] + + return ctx.args + + def invoke(self, ctx: Context) -> t.Any: + def _process_result(value: t.Any) -> t.Any: + if self._result_callback is not None: + value = ctx.invoke(self._result_callback, value, **ctx.params) + return value + + if not ctx._protected_args: + if self.invoke_without_command: + # No subcommand was invoked, so the result callback is + # invoked with the group return value for regular + # groups, or an empty list for chained groups. + with ctx: + rv = super().invoke(ctx) + return _process_result([] if self.chain else rv) + ctx.fail(_("Missing command.")) + + # Fetch args back out + args = [*ctx._protected_args, *ctx.args] + ctx.args = [] + ctx._protected_args = [] + + # If we're not in chain mode, we only allow the invocation of a + # single command but we also inform the current context about the + # name of the command to invoke. + if not self.chain: + # Make sure the context is entered so we do not clean up + # resources until the result processor has worked. + with ctx: + cmd_name, cmd, args = self.resolve_command(ctx, args) + assert cmd is not None + ctx.invoked_subcommand = cmd_name + super().invoke(ctx) + sub_ctx = cmd.make_context(cmd_name, args, parent=ctx) + with sub_ctx: + return _process_result(sub_ctx.command.invoke(sub_ctx)) + + # In chain mode we create the contexts step by step, but after the + # base command has been invoked. Because at that point we do not + # know the subcommands yet, the invoked subcommand attribute is + # set to ``*`` to inform the command that subcommands are executed + # but nothing else. + with ctx: + ctx.invoked_subcommand = "*" if args else None + super().invoke(ctx) + + # Otherwise we make every single context and invoke them in a + # chain. In that case the return value to the result processor + # is the list of all invoked subcommand's results. + contexts = [] + while args: + cmd_name, cmd, args = self.resolve_command(ctx, args) + assert cmd is not None + sub_ctx = cmd.make_context( + cmd_name, + args, + parent=ctx, + allow_extra_args=True, + allow_interspersed_args=False, + ) + contexts.append(sub_ctx) + args, sub_ctx.args = sub_ctx.args, [] + + rv = [] + for sub_ctx in contexts: + with sub_ctx: + rv.append(sub_ctx.command.invoke(sub_ctx)) + return _process_result(rv) + + def resolve_command( + self, ctx: Context, args: list[str] + ) -> tuple[str | None, Command | None, list[str]]: + cmd_name = make_str(args[0]) + original_cmd_name = cmd_name + + # Get the command + cmd = self.get_command(ctx, cmd_name) + + # If we can't find the command but there is a normalization + # function available, we try with that one. + if cmd is None and ctx.token_normalize_func is not None: + cmd_name = ctx.token_normalize_func(cmd_name) + cmd = self.get_command(ctx, cmd_name) + + # If we don't find the command we want to show an error message + # to the user that it was not provided. However, there is + # something else we should do: if the first argument looks like + # an option we want to kick off parsing again for arguments to + # resolve things like --help which now should go to the main + # place. + if cmd is None and not ctx.resilient_parsing: + if _split_opt(cmd_name)[0]: + self.parse_args(ctx, args) + ctx.fail(_("No such command {name!r}.").format(name=original_cmd_name)) + return cmd_name if cmd else None, cmd, args[1:] + + def shell_complete(self, ctx: Context, incomplete: str) -> list[CompletionItem]: + """Return a list of completions for the incomplete value. Looks + at the names of options, subcommands, and chained + multi-commands. + + :param ctx: Invocation context for this command. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + results = [ + CompletionItem(name, help=command.get_short_help_str()) + for name, command in _complete_visible_commands(ctx, incomplete) + ] + results.extend(super().shell_complete(ctx, incomplete)) + return results + + +class _MultiCommand(Group, metaclass=_FakeSubclassCheck): + """ + .. deprecated:: 8.2 + Will be removed in Click 9.0. Use ``Group`` instead. + """ + + +class CommandCollection(Group): + """A :class:`Group` that looks up subcommands on other groups. If a command + is not found on this group, each registered source is checked in order. + Parameters on a source are not added to this group, and a source's callback + is not invoked when invoking its commands. In other words, this "flattens" + commands in many groups into this one group. + + :param name: The name of the group command. + :param sources: A list of :class:`Group` objects to look up commands from. + :param kwargs: Other arguments passed to :class:`Group`. + + .. versionchanged:: 8.2 + This is a subclass of ``Group``. Commands are looked up first on this + group, then each of its sources. + """ + + def __init__( + self, + name: str | None = None, + sources: list[Group] | None = None, + **kwargs: t.Any, + ) -> None: + super().__init__(name, **kwargs) + #: The list of registered groups. + self.sources: list[Group] = sources or [] + + def add_source(self, group: Group) -> None: + """Add a group as a source of commands.""" + self.sources.append(group) + + def get_command(self, ctx: Context, cmd_name: str) -> Command | None: + rv = super().get_command(ctx, cmd_name) + + if rv is not None: + return rv + + for source in self.sources: + rv = source.get_command(ctx, cmd_name) + + if rv is not None: + if self.chain: + _check_nested_chain(self, cmd_name, rv) + + return rv + + return None + + def list_commands(self, ctx: Context) -> list[str]: + rv: set[str] = set(super().list_commands(ctx)) + + for source in self.sources: + rv.update(source.list_commands(ctx)) + + return sorted(rv) + + +def _check_iter(value: t.Any) -> cabc.Iterator[t.Any]: + """Check if the value is iterable but not a string. Raises a type + error, or return an iterator over the value. + """ + if isinstance(value, str): + raise TypeError + + return iter(value) + + +class Parameter: + r"""A parameter to a command comes in two versions: they are either + :class:`Option`\s or :class:`Argument`\s. Other subclasses are currently + not supported by design as some of the internals for parsing are + intentionally not finalized. + + Some settings are supported by both options and arguments. + + :param param_decls: the parameter declarations for this option or + argument. This is a list of flags or argument + names. + :param type: the type that should be used. Either a :class:`ParamType` + or a Python type. The latter is converted into the former + automatically if supported. + :param required: controls if this is optional or not. + :param default: the default value if omitted. This can also be a callable, + in which case it's invoked when the default is needed + without any arguments. + :param callback: A function to further process or validate the value + after type conversion. It is called as ``f(ctx, param, value)`` + and must return the value. It is called for all sources, + including prompts. + :param nargs: the number of arguments to match. If not ``1`` the return + value is a tuple instead of single value. The default for + nargs is ``1`` (except if the type is a tuple, then it's + the arity of the tuple). If ``nargs=-1``, all remaining + parameters are collected. + :param metavar: how the value is represented in the help page. + :param expose_value: if this is `True` then the value is passed onwards + to the command callback and stored on the context, + otherwise it's skipped. + :param is_eager: eager values are processed before non eager ones. This + should not be set for arguments or it will inverse the + order of processing. + :param envvar: environment variable(s) that are used to provide a default value for + this parameter. This can be a string or a sequence of strings. If a sequence is + given, only the first non-empty environment variable is used for the parameter. + :param shell_complete: A function that returns custom shell + completions. Used instead of the param's type completion if + given. Takes ``ctx, param, incomplete`` and must return a list + of :class:`~click.shell_completion.CompletionItem` or a list of + strings. + :param deprecated: If ``True`` or non-empty string, issues a message + indicating that the argument is deprecated and highlights + its deprecation in --help. The message can be customized + by using a string as the value. A deprecated parameter + cannot be required, a ValueError will be raised otherwise. + + .. versionchanged:: 8.2.0 + Introduction of ``deprecated``. + + .. versionchanged:: 8.2 + Adding duplicate parameter names to a :class:`~click.core.Command` will + result in a ``UserWarning`` being shown. + + .. versionchanged:: 8.2 + Adding duplicate parameter names to a :class:`~click.core.Command` will + result in a ``UserWarning`` being shown. + + .. versionchanged:: 8.0 + ``process_value`` validates required parameters and bounded + ``nargs``, and invokes the parameter callback before returning + the value. This allows the callback to validate prompts. + ``full_process_value`` is removed. + + .. versionchanged:: 8.0 + ``autocompletion`` is renamed to ``shell_complete`` and has new + semantics described above. The old name is deprecated and will + be removed in 8.1, until then it will be wrapped to match the + new requirements. + + .. versionchanged:: 8.0 + For ``multiple=True, nargs>1``, the default must be a list of + tuples. + + .. versionchanged:: 8.0 + Setting a default is no longer required for ``nargs>1``, it will + default to ``None``. ``multiple=True`` or ``nargs=-1`` will + default to ``()``. + + .. versionchanged:: 7.1 + Empty environment variables are ignored rather than taking the + empty string value. This makes it possible for scripts to clear + variables if they can't unset them. + + .. versionchanged:: 2.0 + Changed signature for parameter callback to also be passed the + parameter. The old callback format will still work, but it will + raise a warning to give you a chance to migrate the code easier. + """ + + param_type_name = "parameter" + + def __init__( + self, + param_decls: cabc.Sequence[str] | None = None, + type: types.ParamType | t.Any | None = None, + required: bool = False, + # XXX The default historically embed two concepts: + # - the declaration of a Parameter object carrying the default (handy to + # arbitrage the default value of coupled Parameters sharing the same + # self.name, like flag options), + # - and the actual value of the default. + # It is confusing and is the source of many issues discussed in: + # https://github.com/pallets/click/pull/3030 + # In the future, we might think of splitting it in two, not unlike + # Option.is_flag and Option.flag_value: we could have something like + # Parameter.is_default and Parameter.default_value. + default: t.Any | t.Callable[[], t.Any] | None = UNSET, + callback: t.Callable[[Context, Parameter, t.Any], t.Any] | None = None, + nargs: int | None = None, + multiple: bool = False, + metavar: str | None = None, + expose_value: bool = True, + is_eager: bool = False, + envvar: str | cabc.Sequence[str] | None = None, + shell_complete: t.Callable[ + [Context, Parameter, str], list[CompletionItem] | list[str] + ] + | None = None, + deprecated: bool | str = False, + ) -> None: + self.name: str | None + self.opts: list[str] + self.secondary_opts: list[str] + self.name, self.opts, self.secondary_opts = self._parse_decls( + param_decls or (), expose_value + ) + self.type: types.ParamType = types.convert_type(type, default) + + # Default nargs to what the type tells us if we have that + # information available. + if nargs is None: + if self.type.is_composite: + nargs = self.type.arity + else: + nargs = 1 + + self.required = required + self.callback = callback + self.nargs = nargs + self.multiple = multiple + self.expose_value = expose_value + self.default = default + self.is_eager = is_eager + self.metavar = metavar + self.envvar = envvar + self._custom_shell_complete = shell_complete + self.deprecated = deprecated + + if __debug__: + if self.type.is_composite and nargs != self.type.arity: + raise ValueError( + f"'nargs' must be {self.type.arity} (or None) for" + f" type {self.type!r}, but it was {nargs}." + ) + + if required and deprecated: + raise ValueError( + f"The {self.param_type_name} '{self.human_readable_name}' " + "is deprecated and still required. A deprecated " + f"{self.param_type_name} cannot be required." + ) + + def to_info_dict(self) -> dict[str, t.Any]: + """Gather information that could be useful for a tool generating + user-facing documentation. + + Use :meth:`click.Context.to_info_dict` to traverse the entire + CLI structure. + + .. versionchanged:: 8.3.0 + Returns ``None`` for the :attr:`default` if it was not set. + + .. versionadded:: 8.0 + """ + return { + "name": self.name, + "param_type_name": self.param_type_name, + "opts": self.opts, + "secondary_opts": self.secondary_opts, + "type": self.type.to_info_dict(), + "required": self.required, + "nargs": self.nargs, + "multiple": self.multiple, + # We explicitly hide the :attr:`UNSET` value to the user, as we choose to + # make it an implementation detail. And because ``to_info_dict`` has been + # designed for documentation purposes, we return ``None`` instead. + "default": self.default if self.default is not UNSET else None, + "envvar": self.envvar, + } + + def __repr__(self) -> str: + return f"<{self.__class__.__name__} {self.name}>" + + def _parse_decls( + self, decls: cabc.Sequence[str], expose_value: bool + ) -> tuple[str | None, list[str], list[str]]: + raise NotImplementedError() + + @property + def human_readable_name(self) -> str: + """Returns the human readable name of this parameter. This is the + same as the name for options, but the metavar for arguments. + """ + return self.name # type: ignore + + def make_metavar(self, ctx: Context) -> str: + if self.metavar is not None: + return self.metavar + + metavar = self.type.get_metavar(param=self, ctx=ctx) + + if metavar is None: + metavar = self.type.name.upper() + + if self.nargs != 1: + metavar += "..." + + return metavar + + @t.overload + def get_default( + self, ctx: Context, call: t.Literal[True] = True + ) -> t.Any | None: ... + + @t.overload + def get_default( + self, ctx: Context, call: bool = ... + ) -> t.Any | t.Callable[[], t.Any] | None: ... + + def get_default( + self, ctx: Context, call: bool = True + ) -> t.Any | t.Callable[[], t.Any] | None: + """Get the default for the parameter. Tries + :meth:`Context.lookup_default` first, then the local default. + + :param ctx: Current context. + :param call: If the default is a callable, call it. Disable to + return the callable instead. + + .. versionchanged:: 8.0.2 + Type casting is no longer performed when getting a default. + + .. versionchanged:: 8.0.1 + Type casting can fail in resilient parsing mode. Invalid + defaults will not prevent showing help text. + + .. versionchanged:: 8.0 + Looks at ``ctx.default_map`` first. + + .. versionchanged:: 8.0 + Added the ``call`` parameter. + """ + value = ctx.lookup_default(self.name, call=False) # type: ignore + + if value is UNSET: + value = self.default + + if call and callable(value): + value = value() + + return value + + def add_to_parser(self, parser: _OptionParser, ctx: Context) -> None: + raise NotImplementedError() + + def consume_value( + self, ctx: Context, opts: cabc.Mapping[str, t.Any] + ) -> tuple[t.Any, ParameterSource]: + """Returns the parameter value produced by the parser. + + If the parser did not produce a value from user input, the value is either + sourced from the environment variable, the default map, or the parameter's + default value. In that order of precedence. + + If no value is found, an internal sentinel value is returned. + + :meta private: + """ + # Collect from the parse the value passed by the user to the CLI. + value = opts.get(self.name, UNSET) # type: ignore + # If the value is set, it means it was sourced from the command line by the + # parser, otherwise it left unset by default. + source = ( + ParameterSource.COMMANDLINE + if value is not UNSET + else ParameterSource.DEFAULT + ) + + if value is UNSET: + envvar_value = self.value_from_envvar(ctx) + if envvar_value is not None: + value = envvar_value + source = ParameterSource.ENVIRONMENT + + if value is UNSET: + default_map_value = ctx.lookup_default(self.name) # type: ignore + if default_map_value is not UNSET: + value = default_map_value + source = ParameterSource.DEFAULT_MAP + + if value is UNSET: + default_value = self.get_default(ctx) + if default_value is not UNSET: + value = default_value + source = ParameterSource.DEFAULT + + return value, source + + def type_cast_value(self, ctx: Context, value: t.Any) -> t.Any: + """Convert and validate a value against the parameter's + :attr:`type`, :attr:`multiple`, and :attr:`nargs`. + """ + if value in (None, UNSET): + if self.multiple or self.nargs == -1: + return () + else: + return value + + def check_iter(value: t.Any) -> cabc.Iterator[t.Any]: + try: + return _check_iter(value) + except TypeError: + # This should only happen when passing in args manually, + # the parser should construct an iterable when parsing + # the command line. + raise BadParameter( + _("Value must be an iterable."), ctx=ctx, param=self + ) from None + + # Define the conversion function based on nargs and type. + + if self.nargs == 1 or self.type.is_composite: + + def convert(value: t.Any) -> t.Any: + return self.type(value, param=self, ctx=ctx) + + elif self.nargs == -1: + + def convert(value: t.Any) -> t.Any: # tuple[t.Any, ...] + return tuple(self.type(x, self, ctx) for x in check_iter(value)) + + else: # nargs > 1 + + def convert(value: t.Any) -> t.Any: # tuple[t.Any, ...] + value = tuple(check_iter(value)) + + if len(value) != self.nargs: + raise BadParameter( + ngettext( + "Takes {nargs} values but 1 was given.", + "Takes {nargs} values but {len} were given.", + len(value), + ).format(nargs=self.nargs, len=len(value)), + ctx=ctx, + param=self, + ) + + return tuple(self.type(x, self, ctx) for x in value) + + if self.multiple: + return tuple(convert(x) for x in check_iter(value)) + + return convert(value) + + def value_is_missing(self, value: t.Any) -> bool: + """A value is considered missing if: + + - it is :attr:`UNSET`, + - or if it is an empty sequence while the parameter is suppose to have + non-single value (i.e. :attr:`nargs` is not ``1`` or :attr:`multiple` is + set). + + :meta private: + """ + if value is UNSET: + return True + + if (self.nargs != 1 or self.multiple) and value == (): + return True + + return False + + def process_value(self, ctx: Context, value: t.Any) -> t.Any: + """Process the value of this parameter: + + 1. Type cast the value using :meth:`type_cast_value`. + 2. Check if the value is missing (see: :meth:`value_is_missing`), and raise + :exc:`MissingParameter` if it is required. + 3. If a :attr:`callback` is set, call it to have the value replaced by the + result of the callback. If the value was not set, the callback receive + ``None``. This keep the legacy behavior as it was before the introduction of + the :attr:`UNSET` sentinel. + + :meta private: + """ + value = self.type_cast_value(ctx, value) + + if self.required and self.value_is_missing(value): + raise MissingParameter(ctx=ctx, param=self) + + if self.callback is not None: + # Legacy case: UNSET is not exposed directly to the callback, but converted + # to None. + if value is UNSET: + value = None + value = self.callback(ctx, self, value) + + return value + + def resolve_envvar_value(self, ctx: Context) -> str | None: + """Returns the value found in the environment variable(s) attached to this + parameter. + + Environment variables values are `always returned as strings + `_. + + This method returns ``None`` if: + + - the :attr:`envvar` property is not set on the :class:`Parameter`, + - the environment variable is not found in the environment, + - the variable is found in the environment but its value is empty (i.e. the + environment variable is present but has an empty string). + + If :attr:`envvar` is setup with multiple environment variables, + then only the first non-empty value is returned. + + .. caution:: + + The raw value extracted from the environment is not normalized and is + returned as-is. Any normalization or reconciliation is performed later by + the :class:`Parameter`'s :attr:`type`. + + :meta private: + """ + if not self.envvar: + return None + + if isinstance(self.envvar, str): + rv = os.environ.get(self.envvar) + + if rv: + return rv + else: + for envvar in self.envvar: + rv = os.environ.get(envvar) + + # Return the first non-empty value of the list of environment variables. + if rv: + return rv + # Else, absence of value is interpreted as an environment variable that + # is not set, so proceed to the next one. + + return None + + def value_from_envvar(self, ctx: Context) -> str | cabc.Sequence[str] | None: + """Process the raw environment variable string for this parameter. + + Returns the string as-is or splits it into a sequence of strings if the + parameter is expecting multiple values (i.e. its :attr:`nargs` property is set + to a value other than ``1``). + + :meta private: + """ + rv = self.resolve_envvar_value(ctx) + + if rv is not None and self.nargs != 1: + return self.type.split_envvar_value(rv) + + return rv + + def handle_parse_result( + self, ctx: Context, opts: cabc.Mapping[str, t.Any], args: list[str] + ) -> tuple[t.Any, list[str]]: + """Process the value produced by the parser from user input. + + Always process the value through the Parameter's :attr:`type`, wherever it + comes from. + + If the parameter is deprecated, this method warn the user about it. But only if + the value has been explicitly set by the user (and as such, is not coming from + a default). + + :meta private: + """ + with augment_usage_errors(ctx, param=self): + value, source = self.consume_value(ctx, opts) + + ctx.set_parameter_source(self.name, source) # type: ignore + + # Display a deprecation warning if necessary. + if ( + self.deprecated + and value is not UNSET + and source not in (ParameterSource.DEFAULT, ParameterSource.DEFAULT_MAP) + ): + extra_message = ( + f" {self.deprecated}" if isinstance(self.deprecated, str) else "" + ) + message = _( + "DeprecationWarning: The {param_type} {name!r} is deprecated." + "{extra_message}" + ).format( + param_type=self.param_type_name, + name=self.human_readable_name, + extra_message=extra_message, + ) + echo(style(message, fg="red"), err=True) + + # Process the value through the parameter's type. + try: + value = self.process_value(ctx, value) + except Exception: + if not ctx.resilient_parsing: + raise + # In resilient parsing mode, we do not want to fail the command if the + # value is incompatible with the parameter type, so we reset the value + # to UNSET, which will be interpreted as a missing value. + value = UNSET + + # Add parameter's value to the context. + if ( + self.expose_value + # We skip adding the value if it was previously set by another parameter + # targeting the same variable name. This prevents parameters competing for + # the same name to override each other. + and self.name not in ctx.params + ): + # Click is logically enforcing that the name is None if the parameter is + # not to be exposed. We still assert it here to please the type checker. + assert self.name is not None, ( + f"{self!r} parameter's name should not be None when exposing value." + ) + # Normalize UNSET values to None, as we're about to pass them to the + # command function and move them to the pure-Python realm of user-written + # code. + ctx.params[self.name] = value if value is not UNSET else None + + return value, args + + def get_help_record(self, ctx: Context) -> tuple[str, str] | None: + pass + + def get_usage_pieces(self, ctx: Context) -> list[str]: + return [] + + def get_error_hint(self, ctx: Context) -> str: + """Get a stringified version of the param for use in error messages to + indicate which param caused the error. + """ + hint_list = self.opts or [self.human_readable_name] + return " / ".join(f"'{x}'" for x in hint_list) + + def shell_complete(self, ctx: Context, incomplete: str) -> list[CompletionItem]: + """Return a list of completions for the incomplete value. If a + ``shell_complete`` function was given during init, it is used. + Otherwise, the :attr:`type` + :meth:`~click.types.ParamType.shell_complete` function is used. + + :param ctx: Invocation context for this command. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + if self._custom_shell_complete is not None: + results = self._custom_shell_complete(ctx, self, incomplete) + + if results and isinstance(results[0], str): + from click.shell_completion import CompletionItem + + results = [CompletionItem(c) for c in results] + + return t.cast("list[CompletionItem]", results) + + return self.type.shell_complete(ctx, self, incomplete) + + +class Option(Parameter): + """Options are usually optional values on the command line and + have some extra features that arguments don't have. + + All other parameters are passed onwards to the parameter constructor. + + :param show_default: Show the default value for this option in its + help text. Values are not shown by default, unless + :attr:`Context.show_default` is ``True``. If this value is a + string, it shows that string in parentheses instead of the + actual value. This is particularly useful for dynamic options. + For single option boolean flags, the default remains hidden if + its value is ``False``. + :param show_envvar: Controls if an environment variable should be + shown on the help page and error messages. + Normally, environment variables are not shown. + :param prompt: If set to ``True`` or a non empty string then the + user will be prompted for input. If set to ``True`` the prompt + will be the option name capitalized. A deprecated option cannot be + prompted. + :param confirmation_prompt: Prompt a second time to confirm the + value if it was prompted for. Can be set to a string instead of + ``True`` to customize the message. + :param prompt_required: If set to ``False``, the user will be + prompted for input only when the option was specified as a flag + without a value. + :param hide_input: If this is ``True`` then the input on the prompt + will be hidden from the user. This is useful for password input. + :param is_flag: forces this option to act as a flag. The default is + auto detection. + :param flag_value: which value should be used for this flag if it's + enabled. This is set to a boolean automatically if + the option string contains a slash to mark two options. + :param multiple: if this is set to `True` then the argument is accepted + multiple times and recorded. This is similar to ``nargs`` + in how it works but supports arbitrary number of + arguments. + :param count: this flag makes an option increment an integer. + :param allow_from_autoenv: if this is enabled then the value of this + parameter will be pulled from an environment + variable in case a prefix is defined on the + context. + :param help: the help string. + :param hidden: hide this option from help outputs. + :param attrs: Other command arguments described in :class:`Parameter`. + + .. versionchanged:: 8.2 + ``envvar`` used with ``flag_value`` will always use the ``flag_value``, + previously it would use the value of the environment variable. + + .. versionchanged:: 8.1 + Help text indentation is cleaned here instead of only in the + ``@option`` decorator. + + .. versionchanged:: 8.1 + The ``show_default`` parameter overrides + ``Context.show_default``. + + .. versionchanged:: 8.1 + The default of a single option boolean flag is not shown if the + default value is ``False``. + + .. versionchanged:: 8.0.1 + ``type`` is detected from ``flag_value`` if given. + """ + + param_type_name = "option" + + def __init__( + self, + param_decls: cabc.Sequence[str] | None = None, + show_default: bool | str | None = None, + prompt: bool | str = False, + confirmation_prompt: bool | str = False, + prompt_required: bool = True, + hide_input: bool = False, + is_flag: bool | None = None, + flag_value: t.Any = UNSET, + multiple: bool = False, + count: bool = False, + allow_from_autoenv: bool = True, + type: types.ParamType | t.Any | None = None, + help: str | None = None, + hidden: bool = False, + show_choices: bool = True, + show_envvar: bool = False, + deprecated: bool | str = False, + **attrs: t.Any, + ) -> None: + if help: + help = inspect.cleandoc(help) + + super().__init__( + param_decls, type=type, multiple=multiple, deprecated=deprecated, **attrs + ) + + if prompt is True: + if self.name is None: + raise TypeError("'name' is required with 'prompt=True'.") + + prompt_text: str | None = self.name.replace("_", " ").capitalize() + elif prompt is False: + prompt_text = None + else: + prompt_text = prompt + + if deprecated: + deprecated_message = ( + f"(DEPRECATED: {deprecated})" + if isinstance(deprecated, str) + else "(DEPRECATED)" + ) + help = help + deprecated_message if help is not None else deprecated_message + + self.prompt = prompt_text + self.confirmation_prompt = confirmation_prompt + self.prompt_required = prompt_required + self.hide_input = hide_input + self.hidden = hidden + + # The _flag_needs_value property tells the parser that this option is a flag + # that cannot be used standalone and needs a value. With this information, the + # parser can determine whether to consider the next user-provided argument in + # the CLI as a value for this flag or as a new option. + # If prompt is enabled but not required, then it opens the possibility for the + # option to gets its value from the user. + self._flag_needs_value = self.prompt is not None and not self.prompt_required + + # Auto-detect if this is a flag or not. + if is_flag is None: + # Implicitly a flag because flag_value was set. + if flag_value is not UNSET: + is_flag = True + # Not a flag, but when used as a flag it shows a prompt. + elif self._flag_needs_value: + is_flag = False + # Implicitly a flag because secondary options names were given. + elif self.secondary_opts: + is_flag = True + # The option is explicitly not a flag. But we do not know yet if it needs a + # value or not. So we look at the default value to determine it. + elif is_flag is False and not self._flag_needs_value: + self._flag_needs_value = self.default is UNSET + + if is_flag: + # Set missing default for flags if not explicitly required or prompted. + if self.default is UNSET and not self.required and not self.prompt: + if multiple: + self.default = () + + # Auto-detect the type of the flag based on the flag_value. + if type is None: + # A flag without a flag_value is a boolean flag. + if flag_value is UNSET: + self.type = types.BoolParamType() + # If the flag value is a boolean, use BoolParamType. + elif isinstance(flag_value, bool): + self.type = types.BoolParamType() + # Otherwise, guess the type from the flag value. + else: + self.type = types.convert_type(None, flag_value) + + self.is_flag: bool = bool(is_flag) + self.is_bool_flag: bool = bool( + is_flag and isinstance(self.type, types.BoolParamType) + ) + self.flag_value: t.Any = flag_value + + # Set boolean flag default to False if unset and not required. + if self.is_bool_flag: + if self.default is UNSET and not self.required: + self.default = False + + # Support the special case of aligning the default value with the flag_value + # for flags whose default is explicitly set to True. Note that as long as we + # have this condition, there is no way a flag can have a default set to True, + # and a flag_value set to something else. Refs: + # https://github.com/pallets/click/issues/3024#issuecomment-3146199461 + # https://github.com/pallets/click/pull/3030/commits/06847da + if self.default is True and self.flag_value is not UNSET: + self.default = self.flag_value + + # Set the default flag_value if it is not set. + if self.flag_value is UNSET: + if self.is_flag: + self.flag_value = True + else: + self.flag_value = None + + # Counting. + self.count = count + if count: + if type is None: + self.type = types.IntRange(min=0) + if self.default is UNSET: + self.default = 0 + + self.allow_from_autoenv = allow_from_autoenv + self.help = help + self.show_default = show_default + self.show_choices = show_choices + self.show_envvar = show_envvar + + if __debug__: + if deprecated and prompt: + raise ValueError("`deprecated` options cannot use `prompt`.") + + if self.nargs == -1: + raise TypeError("nargs=-1 is not supported for options.") + + if not self.is_bool_flag and self.secondary_opts: + raise TypeError("Secondary flag is not valid for non-boolean flag.") + + if self.is_bool_flag and self.hide_input and self.prompt is not None: + raise TypeError( + "'prompt' with 'hide_input' is not valid for boolean flag." + ) + + if self.count: + if self.multiple: + raise TypeError("'count' is not valid with 'multiple'.") + + if self.is_flag: + raise TypeError("'count' is not valid with 'is_flag'.") + + def to_info_dict(self) -> dict[str, t.Any]: + """ + .. versionchanged:: 8.3.0 + Returns ``None`` for the :attr:`flag_value` if it was not set. + """ + info_dict = super().to_info_dict() + info_dict.update( + help=self.help, + prompt=self.prompt, + is_flag=self.is_flag, + # We explicitly hide the :attr:`UNSET` value to the user, as we choose to + # make it an implementation detail. And because ``to_info_dict`` has been + # designed for documentation purposes, we return ``None`` instead. + flag_value=self.flag_value if self.flag_value is not UNSET else None, + count=self.count, + hidden=self.hidden, + ) + return info_dict + + def get_error_hint(self, ctx: Context) -> str: + result = super().get_error_hint(ctx) + if self.show_envvar and self.envvar is not None: + result += f" (env var: '{self.envvar}')" + return result + + def _parse_decls( + self, decls: cabc.Sequence[str], expose_value: bool + ) -> tuple[str | None, list[str], list[str]]: + opts = [] + secondary_opts = [] + name = None + possible_names = [] + + for decl in decls: + if decl.isidentifier(): + if name is not None: + raise TypeError(f"Name '{name}' defined twice") + name = decl + else: + split_char = ";" if decl[:1] == "/" else "/" + if split_char in decl: + first, second = decl.split(split_char, 1) + first = first.rstrip() + if first: + possible_names.append(_split_opt(first)) + opts.append(first) + second = second.lstrip() + if second: + secondary_opts.append(second.lstrip()) + if first == second: + raise ValueError( + f"Boolean option {decl!r} cannot use the" + " same flag for true/false." + ) + else: + possible_names.append(_split_opt(decl)) + opts.append(decl) + + if name is None and possible_names: + possible_names.sort(key=lambda x: -len(x[0])) # group long options first + name = possible_names[0][1].replace("-", "_").lower() + if not name.isidentifier(): + name = None + + if name is None: + if not expose_value: + return None, opts, secondary_opts + raise TypeError( + f"Could not determine name for option with declarations {decls!r}" + ) + + if not opts and not secondary_opts: + raise TypeError( + f"No options defined but a name was passed ({name})." + " Did you mean to declare an argument instead? Did" + f" you mean to pass '--{name}'?" + ) + + return name, opts, secondary_opts + + def add_to_parser(self, parser: _OptionParser, ctx: Context) -> None: + if self.multiple: + action = "append" + elif self.count: + action = "count" + else: + action = "store" + + if self.is_flag: + action = f"{action}_const" + + if self.is_bool_flag and self.secondary_opts: + parser.add_option( + obj=self, opts=self.opts, dest=self.name, action=action, const=True + ) + parser.add_option( + obj=self, + opts=self.secondary_opts, + dest=self.name, + action=action, + const=False, + ) + else: + parser.add_option( + obj=self, + opts=self.opts, + dest=self.name, + action=action, + const=self.flag_value, + ) + else: + parser.add_option( + obj=self, + opts=self.opts, + dest=self.name, + action=action, + nargs=self.nargs, + ) + + def get_help_record(self, ctx: Context) -> tuple[str, str] | None: + if self.hidden: + return None + + any_prefix_is_slash = False + + def _write_opts(opts: cabc.Sequence[str]) -> str: + nonlocal any_prefix_is_slash + + rv, any_slashes = join_options(opts) + + if any_slashes: + any_prefix_is_slash = True + + if not self.is_flag and not self.count: + rv += f" {self.make_metavar(ctx=ctx)}" + + return rv + + rv = [_write_opts(self.opts)] + + if self.secondary_opts: + rv.append(_write_opts(self.secondary_opts)) + + help = self.help or "" + + extra = self.get_help_extra(ctx) + extra_items = [] + if "envvars" in extra: + extra_items.append( + _("env var: {var}").format(var=", ".join(extra["envvars"])) + ) + if "default" in extra: + extra_items.append(_("default: {default}").format(default=extra["default"])) + if "range" in extra: + extra_items.append(extra["range"]) + if "required" in extra: + extra_items.append(_(extra["required"])) + + if extra_items: + extra_str = "; ".join(extra_items) + help = f"{help} [{extra_str}]" if help else f"[{extra_str}]" + + return ("; " if any_prefix_is_slash else " / ").join(rv), help + + def get_help_extra(self, ctx: Context) -> types.OptionHelpExtra: + extra: types.OptionHelpExtra = {} + + if self.show_envvar: + envvar = self.envvar + + if envvar is None: + if ( + self.allow_from_autoenv + and ctx.auto_envvar_prefix is not None + and self.name is not None + ): + envvar = f"{ctx.auto_envvar_prefix}_{self.name.upper()}" + + if envvar is not None: + if isinstance(envvar, str): + extra["envvars"] = (envvar,) + else: + extra["envvars"] = tuple(str(d) for d in envvar) + + # Temporarily enable resilient parsing to avoid type casting + # failing for the default. Might be possible to extend this to + # help formatting in general. + resilient = ctx.resilient_parsing + ctx.resilient_parsing = True + + try: + default_value = self.get_default(ctx, call=False) + finally: + ctx.resilient_parsing = resilient + + show_default = False + show_default_is_str = False + + if self.show_default is not None: + if isinstance(self.show_default, str): + show_default_is_str = show_default = True + else: + show_default = self.show_default + elif ctx.show_default is not None: + show_default = ctx.show_default + + if show_default_is_str or ( + show_default and (default_value not in (None, UNSET)) + ): + if show_default_is_str: + default_string = f"({self.show_default})" + elif isinstance(default_value, (list, tuple)): + default_string = ", ".join(str(d) for d in default_value) + elif isinstance(default_value, enum.Enum): + default_string = default_value.name + elif inspect.isfunction(default_value): + default_string = _("(dynamic)") + elif self.is_bool_flag and self.secondary_opts: + # For boolean flags that have distinct True/False opts, + # use the opt without prefix instead of the value. + default_string = _split_opt( + (self.opts if default_value else self.secondary_opts)[0] + )[1] + elif self.is_bool_flag and not self.secondary_opts and not default_value: + default_string = "" + elif default_value == "": + default_string = '""' + else: + default_string = str(default_value) + + if default_string: + extra["default"] = default_string + + if ( + isinstance(self.type, types._NumberRangeBase) + # skip count with default range type + and not (self.count and self.type.min == 0 and self.type.max is None) + ): + range_str = self.type._describe_range() + + if range_str: + extra["range"] = range_str + + if self.required: + extra["required"] = "required" + + return extra + + def prompt_for_value(self, ctx: Context) -> t.Any: + """This is an alternative flow that can be activated in the full + value processing if a value does not exist. It will prompt the + user until a valid value exists and then returns the processed + value as result. + """ + assert self.prompt is not None + + # Calculate the default before prompting anything to lock in the value before + # attempting any user interaction. + default = self.get_default(ctx) + + # A boolean flag can use a simplified [y/n] confirmation prompt. + if self.is_bool_flag: + # If we have no boolean default, we force the user to explicitly provide + # one. + if default in (UNSET, None): + default = None + # Nothing prevent you to declare an option that is simultaneously: + # 1) auto-detected as a boolean flag, + # 2) allowed to prompt, and + # 3) still declare a non-boolean default. + # This forced casting into a boolean is necessary to align any non-boolean + # default to the prompt, which is going to be a [y/n]-style confirmation + # because the option is still a boolean flag. That way, instead of [y/n], + # we get [Y/n] or [y/N] depending on the truthy value of the default. + # Refs: https://github.com/pallets/click/pull/3030#discussion_r2289180249 + else: + default = bool(default) + return confirm(self.prompt, default) + + # If show_default is set to True/False, provide this to `prompt` as well. For + # non-bool values of `show_default`, we use `prompt`'s default behavior + prompt_kwargs: t.Any = {} + if isinstance(self.show_default, bool): + prompt_kwargs["show_default"] = self.show_default + + return prompt( + self.prompt, + # Use ``None`` to inform the prompt() function to reiterate until a valid + # value is provided by the user if we have no default. + default=None if default is UNSET else default, + type=self.type, + hide_input=self.hide_input, + show_choices=self.show_choices, + confirmation_prompt=self.confirmation_prompt, + value_proc=lambda x: self.process_value(ctx, x), + **prompt_kwargs, + ) + + def resolve_envvar_value(self, ctx: Context) -> str | None: + """:class:`Option` resolves its environment variable the same way as + :func:`Parameter.resolve_envvar_value`, but it also supports + :attr:`Context.auto_envvar_prefix`. If we could not find an environment from + the :attr:`envvar` property, we fallback on :attr:`Context.auto_envvar_prefix` + to build dynamiccaly the environment variable name using the + :python:`{ctx.auto_envvar_prefix}_{self.name.upper()}` template. + + :meta private: + """ + rv = super().resolve_envvar_value(ctx) + + if rv is not None: + return rv + + if ( + self.allow_from_autoenv + and ctx.auto_envvar_prefix is not None + and self.name is not None + ): + envvar = f"{ctx.auto_envvar_prefix}_{self.name.upper()}" + rv = os.environ.get(envvar) + + if rv: + return rv + + return None + + def value_from_envvar(self, ctx: Context) -> t.Any: + """For :class:`Option`, this method processes the raw environment variable + string the same way as :func:`Parameter.value_from_envvar` does. + + But in the case of non-boolean flags, the value is analyzed to determine if the + flag is activated or not, and returns a boolean of its activation, or the + :attr:`flag_value` if the latter is set. + + This method also takes care of repeated options (i.e. options with + :attr:`multiple` set to ``True``). + + :meta private: + """ + rv = self.resolve_envvar_value(ctx) + + # Absent environment variable or an empty string is interpreted as unset. + if rv is None: + return None + + # Non-boolean flags are more liberal in what they accept. But a flag being a + # flag, its envvar value still needs to be analyzed to determine if the flag is + # activated or not. + if self.is_flag and not self.is_bool_flag: + # If the flag_value is set and match the envvar value, return it + # directly. + if self.flag_value is not UNSET and rv == self.flag_value: + return self.flag_value + # Analyze the envvar value as a boolean to know if the flag is + # activated or not. + return types.BoolParamType.str_to_bool(rv) + + # Split the envvar value if it is allowed to be repeated. + value_depth = (self.nargs != 1) + bool(self.multiple) + if value_depth > 0: + multi_rv = self.type.split_envvar_value(rv) + if self.multiple and self.nargs != 1: + multi_rv = batch(multi_rv, self.nargs) # type: ignore[assignment] + + return multi_rv + + return rv + + def consume_value( + self, ctx: Context, opts: cabc.Mapping[str, Parameter] + ) -> tuple[t.Any, ParameterSource]: + """For :class:`Option`, the value can be collected from an interactive prompt + if the option is a flag that needs a value (and the :attr:`prompt` property is + set). + + Additionally, this method handles flag option that are activated without a + value, in which case the :attr:`flag_value` is returned. + + :meta private: + """ + value, source = super().consume_value(ctx, opts) + + # The parser will emit a sentinel value if the option is allowed to as a flag + # without a value. + if value is FLAG_NEEDS_VALUE: + # If the option allows for a prompt, we start an interaction with the user. + if self.prompt is not None and not ctx.resilient_parsing: + value = self.prompt_for_value(ctx) + source = ParameterSource.PROMPT + # Else the flag takes its flag_value as value. + else: + value = self.flag_value + source = ParameterSource.COMMANDLINE + + # A flag which is activated always returns the flag value, unless the value + # comes from the explicitly sets default. + elif ( + self.is_flag + and value is True + and not self.is_bool_flag + and source not in (ParameterSource.DEFAULT, ParameterSource.DEFAULT_MAP) + ): + value = self.flag_value + + # Re-interpret a multiple option which has been sent as-is by the parser. + # Here we replace each occurrence of value-less flags (marked by the + # FLAG_NEEDS_VALUE sentinel) with the flag_value. + elif ( + self.multiple + and value is not UNSET + and source not in (ParameterSource.DEFAULT, ParameterSource.DEFAULT_MAP) + and any(v is FLAG_NEEDS_VALUE for v in value) + ): + value = [self.flag_value if v is FLAG_NEEDS_VALUE else v for v in value] + source = ParameterSource.COMMANDLINE + + # The value wasn't set, or used the param's default, prompt for one to the user + # if prompting is enabled. + elif ( + ( + value is UNSET + or source in (ParameterSource.DEFAULT, ParameterSource.DEFAULT_MAP) + ) + and self.prompt is not None + and (self.required or self.prompt_required) + and not ctx.resilient_parsing + ): + value = self.prompt_for_value(ctx) + source = ParameterSource.PROMPT + + return value, source + + def type_cast_value(self, ctx: Context, value: t.Any) -> t.Any: + if self.is_flag and not self.required: + if value is UNSET: + if self.is_bool_flag: + # If the flag is a boolean flag, we return False if it is not set. + value = False + return super().type_cast_value(ctx, value) + + +class Argument(Parameter): + """Arguments are positional parameters to a command. They generally + provide fewer features than options but can have infinite ``nargs`` + and are required by default. + + All parameters are passed onwards to the constructor of :class:`Parameter`. + """ + + param_type_name = "argument" + + def __init__( + self, + param_decls: cabc.Sequence[str], + required: bool | None = None, + **attrs: t.Any, + ) -> None: + # Auto-detect the requirement status of the argument if not explicitly set. + if required is None: + # The argument gets automatically required if it has no explicit default + # value set and is setup to match at least one value. + if attrs.get("default", UNSET) is UNSET: + required = attrs.get("nargs", 1) > 0 + # If the argument has a default value, it is not required. + else: + required = False + + if "multiple" in attrs: + raise TypeError("__init__() got an unexpected keyword argument 'multiple'.") + + super().__init__(param_decls, required=required, **attrs) + + @property + def human_readable_name(self) -> str: + if self.metavar is not None: + return self.metavar + return self.name.upper() # type: ignore + + def make_metavar(self, ctx: Context) -> str: + if self.metavar is not None: + return self.metavar + var = self.type.get_metavar(param=self, ctx=ctx) + if not var: + var = self.name.upper() # type: ignore + if self.deprecated: + var += "!" + if not self.required: + var = f"[{var}]" + if self.nargs != 1: + var += "..." + return var + + def _parse_decls( + self, decls: cabc.Sequence[str], expose_value: bool + ) -> tuple[str | None, list[str], list[str]]: + if not decls: + if not expose_value: + return None, [], [] + raise TypeError("Argument is marked as exposed, but does not have a name.") + if len(decls) == 1: + name = arg = decls[0] + name = name.replace("-", "_").lower() + else: + raise TypeError( + "Arguments take exactly one parameter declaration, got" + f" {len(decls)}: {decls}." + ) + return name, [arg], [] + + def get_usage_pieces(self, ctx: Context) -> list[str]: + return [self.make_metavar(ctx)] + + def get_error_hint(self, ctx: Context) -> str: + return f"'{self.make_metavar(ctx)}'" + + def add_to_parser(self, parser: _OptionParser, ctx: Context) -> None: + parser.add_argument(dest=self.name, nargs=self.nargs, obj=self) + + +def __getattr__(name: str) -> object: + import warnings + + if name == "BaseCommand": + warnings.warn( + "'BaseCommand' is deprecated and will be removed in Click 9.0. Use" + " 'Command' instead.", + DeprecationWarning, + stacklevel=2, + ) + return _BaseCommand + + if name == "MultiCommand": + warnings.warn( + "'MultiCommand' is deprecated and will be removed in Click 9.0. Use" + " 'Group' instead.", + DeprecationWarning, + stacklevel=2, + ) + return _MultiCommand + + raise AttributeError(name) diff --git a/backend/venv/Lib/site-packages/click/decorators.py b/backend/venv/Lib/site-packages/click/decorators.py new file mode 100644 index 0000000..21f4c34 --- /dev/null +++ b/backend/venv/Lib/site-packages/click/decorators.py @@ -0,0 +1,551 @@ +from __future__ import annotations + +import inspect +import typing as t +from functools import update_wrapper +from gettext import gettext as _ + +from .core import Argument +from .core import Command +from .core import Context +from .core import Group +from .core import Option +from .core import Parameter +from .globals import get_current_context +from .utils import echo + +if t.TYPE_CHECKING: + import typing_extensions as te + + P = te.ParamSpec("P") + +R = t.TypeVar("R") +T = t.TypeVar("T") +_AnyCallable = t.Callable[..., t.Any] +FC = t.TypeVar("FC", bound="_AnyCallable | Command") + + +def pass_context(f: t.Callable[te.Concatenate[Context, P], R]) -> t.Callable[P, R]: + """Marks a callback as wanting to receive the current context + object as first argument. + """ + + def new_func(*args: P.args, **kwargs: P.kwargs) -> R: + return f(get_current_context(), *args, **kwargs) + + return update_wrapper(new_func, f) + + +def pass_obj(f: t.Callable[te.Concatenate[T, P], R]) -> t.Callable[P, R]: + """Similar to :func:`pass_context`, but only pass the object on the + context onwards (:attr:`Context.obj`). This is useful if that object + represents the state of a nested system. + """ + + def new_func(*args: P.args, **kwargs: P.kwargs) -> R: + return f(get_current_context().obj, *args, **kwargs) + + return update_wrapper(new_func, f) + + +def make_pass_decorator( + object_type: type[T], ensure: bool = False +) -> t.Callable[[t.Callable[te.Concatenate[T, P], R]], t.Callable[P, R]]: + """Given an object type this creates a decorator that will work + similar to :func:`pass_obj` but instead of passing the object of the + current context, it will find the innermost context of type + :func:`object_type`. + + This generates a decorator that works roughly like this:: + + from functools import update_wrapper + + def decorator(f): + @pass_context + def new_func(ctx, *args, **kwargs): + obj = ctx.find_object(object_type) + return ctx.invoke(f, obj, *args, **kwargs) + return update_wrapper(new_func, f) + return decorator + + :param object_type: the type of the object to pass. + :param ensure: if set to `True`, a new object will be created and + remembered on the context if it's not there yet. + """ + + def decorator(f: t.Callable[te.Concatenate[T, P], R]) -> t.Callable[P, R]: + def new_func(*args: P.args, **kwargs: P.kwargs) -> R: + ctx = get_current_context() + + obj: T | None + if ensure: + obj = ctx.ensure_object(object_type) + else: + obj = ctx.find_object(object_type) + + if obj is None: + raise RuntimeError( + "Managed to invoke callback without a context" + f" object of type {object_type.__name__!r}" + " existing." + ) + + return ctx.invoke(f, obj, *args, **kwargs) + + return update_wrapper(new_func, f) + + return decorator + + +def pass_meta_key( + key: str, *, doc_description: str | None = None +) -> t.Callable[[t.Callable[te.Concatenate[T, P], R]], t.Callable[P, R]]: + """Create a decorator that passes a key from + :attr:`click.Context.meta` as the first argument to the decorated + function. + + :param key: Key in ``Context.meta`` to pass. + :param doc_description: Description of the object being passed, + inserted into the decorator's docstring. Defaults to "the 'key' + key from Context.meta". + + .. versionadded:: 8.0 + """ + + def decorator(f: t.Callable[te.Concatenate[T, P], R]) -> t.Callable[P, R]: + def new_func(*args: P.args, **kwargs: P.kwargs) -> R: + ctx = get_current_context() + obj = ctx.meta[key] + return ctx.invoke(f, obj, *args, **kwargs) + + return update_wrapper(new_func, f) + + if doc_description is None: + doc_description = f"the {key!r} key from :attr:`click.Context.meta`" + + decorator.__doc__ = ( + f"Decorator that passes {doc_description} as the first argument" + " to the decorated function." + ) + return decorator + + +CmdType = t.TypeVar("CmdType", bound=Command) + + +# variant: no call, directly as decorator for a function. +@t.overload +def command(name: _AnyCallable) -> Command: ... + + +# variant: with positional name and with positional or keyword cls argument: +# @command(namearg, CommandCls, ...) or @command(namearg, cls=CommandCls, ...) +@t.overload +def command( + name: str | None, + cls: type[CmdType], + **attrs: t.Any, +) -> t.Callable[[_AnyCallable], CmdType]: ... + + +# variant: name omitted, cls _must_ be a keyword argument, @command(cls=CommandCls, ...) +@t.overload +def command( + name: None = None, + *, + cls: type[CmdType], + **attrs: t.Any, +) -> t.Callable[[_AnyCallable], CmdType]: ... + + +# variant: with optional string name, no cls argument provided. +@t.overload +def command( + name: str | None = ..., cls: None = None, **attrs: t.Any +) -> t.Callable[[_AnyCallable], Command]: ... + + +def command( + name: str | _AnyCallable | None = None, + cls: type[CmdType] | None = None, + **attrs: t.Any, +) -> Command | t.Callable[[_AnyCallable], Command | CmdType]: + r"""Creates a new :class:`Command` and uses the decorated function as + callback. This will also automatically attach all decorated + :func:`option`\s and :func:`argument`\s as parameters to the command. + + The name of the command defaults to the name of the function, converted to + lowercase, with underscores ``_`` replaced by dashes ``-``, and the suffixes + ``_command``, ``_cmd``, ``_group``, and ``_grp`` are removed. For example, + ``init_data_command`` becomes ``init-data``. + + All keyword arguments are forwarded to the underlying command class. + For the ``params`` argument, any decorated params are appended to + the end of the list. + + Once decorated the function turns into a :class:`Command` instance + that can be invoked as a command line utility or be attached to a + command :class:`Group`. + + :param name: The name of the command. Defaults to modifying the function's + name as described above. + :param cls: The command class to create. Defaults to :class:`Command`. + + .. versionchanged:: 8.2 + The suffixes ``_command``, ``_cmd``, ``_group``, and ``_grp`` are + removed when generating the name. + + .. versionchanged:: 8.1 + This decorator can be applied without parentheses. + + .. versionchanged:: 8.1 + The ``params`` argument can be used. Decorated params are + appended to the end of the list. + """ + + func: t.Callable[[_AnyCallable], t.Any] | None = None + + if callable(name): + func = name + name = None + assert cls is None, "Use 'command(cls=cls)(callable)' to specify a class." + assert not attrs, "Use 'command(**kwargs)(callable)' to provide arguments." + + if cls is None: + cls = t.cast("type[CmdType]", Command) + + def decorator(f: _AnyCallable) -> CmdType: + if isinstance(f, Command): + raise TypeError("Attempted to convert a callback into a command twice.") + + attr_params = attrs.pop("params", None) + params = attr_params if attr_params is not None else [] + + try: + decorator_params = f.__click_params__ # type: ignore + except AttributeError: + pass + else: + del f.__click_params__ # type: ignore + params.extend(reversed(decorator_params)) + + if attrs.get("help") is None: + attrs["help"] = f.__doc__ + + if t.TYPE_CHECKING: + assert cls is not None + assert not callable(name) + + if name is not None: + cmd_name = name + else: + cmd_name = f.__name__.lower().replace("_", "-") + cmd_left, sep, suffix = cmd_name.rpartition("-") + + if sep and suffix in {"command", "cmd", "group", "grp"}: + cmd_name = cmd_left + + cmd = cls(name=cmd_name, callback=f, params=params, **attrs) + cmd.__doc__ = f.__doc__ + return cmd + + if func is not None: + return decorator(func) + + return decorator + + +GrpType = t.TypeVar("GrpType", bound=Group) + + +# variant: no call, directly as decorator for a function. +@t.overload +def group(name: _AnyCallable) -> Group: ... + + +# variant: with positional name and with positional or keyword cls argument: +# @group(namearg, GroupCls, ...) or @group(namearg, cls=GroupCls, ...) +@t.overload +def group( + name: str | None, + cls: type[GrpType], + **attrs: t.Any, +) -> t.Callable[[_AnyCallable], GrpType]: ... + + +# variant: name omitted, cls _must_ be a keyword argument, @group(cmd=GroupCls, ...) +@t.overload +def group( + name: None = None, + *, + cls: type[GrpType], + **attrs: t.Any, +) -> t.Callable[[_AnyCallable], GrpType]: ... + + +# variant: with optional string name, no cls argument provided. +@t.overload +def group( + name: str | None = ..., cls: None = None, **attrs: t.Any +) -> t.Callable[[_AnyCallable], Group]: ... + + +def group( + name: str | _AnyCallable | None = None, + cls: type[GrpType] | None = None, + **attrs: t.Any, +) -> Group | t.Callable[[_AnyCallable], Group | GrpType]: + """Creates a new :class:`Group` with a function as callback. This + works otherwise the same as :func:`command` just that the `cls` + parameter is set to :class:`Group`. + + .. versionchanged:: 8.1 + This decorator can be applied without parentheses. + """ + if cls is None: + cls = t.cast("type[GrpType]", Group) + + if callable(name): + return command(cls=cls, **attrs)(name) + + return command(name, cls, **attrs) + + +def _param_memo(f: t.Callable[..., t.Any], param: Parameter) -> None: + if isinstance(f, Command): + f.params.append(param) + else: + if not hasattr(f, "__click_params__"): + f.__click_params__ = [] # type: ignore + + f.__click_params__.append(param) # type: ignore + + +def argument( + *param_decls: str, cls: type[Argument] | None = None, **attrs: t.Any +) -> t.Callable[[FC], FC]: + """Attaches an argument to the command. All positional arguments are + passed as parameter declarations to :class:`Argument`; all keyword + arguments are forwarded unchanged (except ``cls``). + This is equivalent to creating an :class:`Argument` instance manually + and attaching it to the :attr:`Command.params` list. + + For the default argument class, refer to :class:`Argument` and + :class:`Parameter` for descriptions of parameters. + + :param cls: the argument class to instantiate. This defaults to + :class:`Argument`. + :param param_decls: Passed as positional arguments to the constructor of + ``cls``. + :param attrs: Passed as keyword arguments to the constructor of ``cls``. + """ + if cls is None: + cls = Argument + + def decorator(f: FC) -> FC: + _param_memo(f, cls(param_decls, **attrs)) + return f + + return decorator + + +def option( + *param_decls: str, cls: type[Option] | None = None, **attrs: t.Any +) -> t.Callable[[FC], FC]: + """Attaches an option to the command. All positional arguments are + passed as parameter declarations to :class:`Option`; all keyword + arguments are forwarded unchanged (except ``cls``). + This is equivalent to creating an :class:`Option` instance manually + and attaching it to the :attr:`Command.params` list. + + For the default option class, refer to :class:`Option` and + :class:`Parameter` for descriptions of parameters. + + :param cls: the option class to instantiate. This defaults to + :class:`Option`. + :param param_decls: Passed as positional arguments to the constructor of + ``cls``. + :param attrs: Passed as keyword arguments to the constructor of ``cls``. + """ + if cls is None: + cls = Option + + def decorator(f: FC) -> FC: + _param_memo(f, cls(param_decls, **attrs)) + return f + + return decorator + + +def confirmation_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]: + """Add a ``--yes`` option which shows a prompt before continuing if + not passed. If the prompt is declined, the program will exit. + + :param param_decls: One or more option names. Defaults to the single + value ``"--yes"``. + :param kwargs: Extra arguments are passed to :func:`option`. + """ + + def callback(ctx: Context, param: Parameter, value: bool) -> None: + if not value: + ctx.abort() + + if not param_decls: + param_decls = ("--yes",) + + kwargs.setdefault("is_flag", True) + kwargs.setdefault("callback", callback) + kwargs.setdefault("expose_value", False) + kwargs.setdefault("prompt", "Do you want to continue?") + kwargs.setdefault("help", "Confirm the action without prompting.") + return option(*param_decls, **kwargs) + + +def password_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]: + """Add a ``--password`` option which prompts for a password, hiding + input and asking to enter the value again for confirmation. + + :param param_decls: One or more option names. Defaults to the single + value ``"--password"``. + :param kwargs: Extra arguments are passed to :func:`option`. + """ + if not param_decls: + param_decls = ("--password",) + + kwargs.setdefault("prompt", True) + kwargs.setdefault("confirmation_prompt", True) + kwargs.setdefault("hide_input", True) + return option(*param_decls, **kwargs) + + +def version_option( + version: str | None = None, + *param_decls: str, + package_name: str | None = None, + prog_name: str | None = None, + message: str | None = None, + **kwargs: t.Any, +) -> t.Callable[[FC], FC]: + """Add a ``--version`` option which immediately prints the version + number and exits the program. + + If ``version`` is not provided, Click will try to detect it using + :func:`importlib.metadata.version` to get the version for the + ``package_name``. + + If ``package_name`` is not provided, Click will try to detect it by + inspecting the stack frames. This will be used to detect the + version, so it must match the name of the installed package. + + :param version: The version number to show. If not provided, Click + will try to detect it. + :param param_decls: One or more option names. Defaults to the single + value ``"--version"``. + :param package_name: The package name to detect the version from. If + not provided, Click will try to detect it. + :param prog_name: The name of the CLI to show in the message. If not + provided, it will be detected from the command. + :param message: The message to show. The values ``%(prog)s``, + ``%(package)s``, and ``%(version)s`` are available. Defaults to + ``"%(prog)s, version %(version)s"``. + :param kwargs: Extra arguments are passed to :func:`option`. + :raise RuntimeError: ``version`` could not be detected. + + .. versionchanged:: 8.0 + Add the ``package_name`` parameter, and the ``%(package)s`` + value for messages. + + .. versionchanged:: 8.0 + Use :mod:`importlib.metadata` instead of ``pkg_resources``. The + version is detected based on the package name, not the entry + point name. The Python package name must match the installed + package name, or be passed with ``package_name=``. + """ + if message is None: + message = _("%(prog)s, version %(version)s") + + if version is None and package_name is None: + frame = inspect.currentframe() + f_back = frame.f_back if frame is not None else None + f_globals = f_back.f_globals if f_back is not None else None + # break reference cycle + # https://docs.python.org/3/library/inspect.html#the-interpreter-stack + del frame + + if f_globals is not None: + package_name = f_globals.get("__name__") + + if package_name == "__main__": + package_name = f_globals.get("__package__") + + if package_name: + package_name = package_name.partition(".")[0] + + def callback(ctx: Context, param: Parameter, value: bool) -> None: + if not value or ctx.resilient_parsing: + return + + nonlocal prog_name + nonlocal version + + if prog_name is None: + prog_name = ctx.find_root().info_name + + if version is None and package_name is not None: + import importlib.metadata + + try: + version = importlib.metadata.version(package_name) + except importlib.metadata.PackageNotFoundError: + raise RuntimeError( + f"{package_name!r} is not installed. Try passing" + " 'package_name' instead." + ) from None + + if version is None: + raise RuntimeError( + f"Could not determine the version for {package_name!r} automatically." + ) + + echo( + message % {"prog": prog_name, "package": package_name, "version": version}, + color=ctx.color, + ) + ctx.exit() + + if not param_decls: + param_decls = ("--version",) + + kwargs.setdefault("is_flag", True) + kwargs.setdefault("expose_value", False) + kwargs.setdefault("is_eager", True) + kwargs.setdefault("help", _("Show the version and exit.")) + kwargs["callback"] = callback + return option(*param_decls, **kwargs) + + +def help_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]: + """Pre-configured ``--help`` option which immediately prints the help page + and exits the program. + + :param param_decls: One or more option names. Defaults to the single + value ``"--help"``. + :param kwargs: Extra arguments are passed to :func:`option`. + """ + + def show_help(ctx: Context, param: Parameter, value: bool) -> None: + """Callback that print the help page on ```` and exits.""" + if value and not ctx.resilient_parsing: + echo(ctx.get_help(), color=ctx.color) + ctx.exit() + + if not param_decls: + param_decls = ("--help",) + + kwargs.setdefault("is_flag", True) + kwargs.setdefault("expose_value", False) + kwargs.setdefault("is_eager", True) + kwargs.setdefault("help", _("Show this message and exit.")) + kwargs.setdefault("callback", show_help) + + return option(*param_decls, **kwargs) diff --git a/backend/venv/Lib/site-packages/click/exceptions.py b/backend/venv/Lib/site-packages/click/exceptions.py new file mode 100644 index 0000000..4d782ee --- /dev/null +++ b/backend/venv/Lib/site-packages/click/exceptions.py @@ -0,0 +1,308 @@ +from __future__ import annotations + +import collections.abc as cabc +import typing as t +from gettext import gettext as _ +from gettext import ngettext + +from ._compat import get_text_stderr +from .globals import resolve_color_default +from .utils import echo +from .utils import format_filename + +if t.TYPE_CHECKING: + from .core import Command + from .core import Context + from .core import Parameter + + +def _join_param_hints(param_hint: cabc.Sequence[str] | str | None) -> str | None: + if param_hint is not None and not isinstance(param_hint, str): + return " / ".join(repr(x) for x in param_hint) + + return param_hint + + +class ClickException(Exception): + """An exception that Click can handle and show to the user.""" + + #: The exit code for this exception. + exit_code = 1 + + def __init__(self, message: str) -> None: + super().__init__(message) + # The context will be removed by the time we print the message, so cache + # the color settings here to be used later on (in `show`) + self.show_color: bool | None = resolve_color_default() + self.message = message + + def format_message(self) -> str: + return self.message + + def __str__(self) -> str: + return self.message + + def show(self, file: t.IO[t.Any] | None = None) -> None: + if file is None: + file = get_text_stderr() + + echo( + _("Error: {message}").format(message=self.format_message()), + file=file, + color=self.show_color, + ) + + +class UsageError(ClickException): + """An internal exception that signals a usage error. This typically + aborts any further handling. + + :param message: the error message to display. + :param ctx: optionally the context that caused this error. Click will + fill in the context automatically in some situations. + """ + + exit_code = 2 + + def __init__(self, message: str, ctx: Context | None = None) -> None: + super().__init__(message) + self.ctx = ctx + self.cmd: Command | None = self.ctx.command if self.ctx else None + + def show(self, file: t.IO[t.Any] | None = None) -> None: + if file is None: + file = get_text_stderr() + color = None + hint = "" + if ( + self.ctx is not None + and self.ctx.command.get_help_option(self.ctx) is not None + ): + hint = _("Try '{command} {option}' for help.").format( + command=self.ctx.command_path, option=self.ctx.help_option_names[0] + ) + hint = f"{hint}\n" + if self.ctx is not None: + color = self.ctx.color + echo(f"{self.ctx.get_usage()}\n{hint}", file=file, color=color) + echo( + _("Error: {message}").format(message=self.format_message()), + file=file, + color=color, + ) + + +class BadParameter(UsageError): + """An exception that formats out a standardized error message for a + bad parameter. This is useful when thrown from a callback or type as + Click will attach contextual information to it (for instance, which + parameter it is). + + .. versionadded:: 2.0 + + :param param: the parameter object that caused this error. This can + be left out, and Click will attach this info itself + if possible. + :param param_hint: a string that shows up as parameter name. This + can be used as alternative to `param` in cases + where custom validation should happen. If it is + a string it's used as such, if it's a list then + each item is quoted and separated. + """ + + def __init__( + self, + message: str, + ctx: Context | None = None, + param: Parameter | None = None, + param_hint: cabc.Sequence[str] | str | None = None, + ) -> None: + super().__init__(message, ctx) + self.param = param + self.param_hint = param_hint + + def format_message(self) -> str: + if self.param_hint is not None: + param_hint = self.param_hint + elif self.param is not None: + param_hint = self.param.get_error_hint(self.ctx) # type: ignore + else: + return _("Invalid value: {message}").format(message=self.message) + + return _("Invalid value for {param_hint}: {message}").format( + param_hint=_join_param_hints(param_hint), message=self.message + ) + + +class MissingParameter(BadParameter): + """Raised if click required an option or argument but it was not + provided when invoking the script. + + .. versionadded:: 4.0 + + :param param_type: a string that indicates the type of the parameter. + The default is to inherit the parameter type from + the given `param`. Valid values are ``'parameter'``, + ``'option'`` or ``'argument'``. + """ + + def __init__( + self, + message: str | None = None, + ctx: Context | None = None, + param: Parameter | None = None, + param_hint: cabc.Sequence[str] | str | None = None, + param_type: str | None = None, + ) -> None: + super().__init__(message or "", ctx, param, param_hint) + self.param_type = param_type + + def format_message(self) -> str: + if self.param_hint is not None: + param_hint: cabc.Sequence[str] | str | None = self.param_hint + elif self.param is not None: + param_hint = self.param.get_error_hint(self.ctx) # type: ignore + else: + param_hint = None + + param_hint = _join_param_hints(param_hint) + param_hint = f" {param_hint}" if param_hint else "" + + param_type = self.param_type + if param_type is None and self.param is not None: + param_type = self.param.param_type_name + + msg = self.message + if self.param is not None: + msg_extra = self.param.type.get_missing_message( + param=self.param, ctx=self.ctx + ) + if msg_extra: + if msg: + msg += f". {msg_extra}" + else: + msg = msg_extra + + msg = f" {msg}" if msg else "" + + # Translate param_type for known types. + if param_type == "argument": + missing = _("Missing argument") + elif param_type == "option": + missing = _("Missing option") + elif param_type == "parameter": + missing = _("Missing parameter") + else: + missing = _("Missing {param_type}").format(param_type=param_type) + + return f"{missing}{param_hint}.{msg}" + + def __str__(self) -> str: + if not self.message: + param_name = self.param.name if self.param else None + return _("Missing parameter: {param_name}").format(param_name=param_name) + else: + return self.message + + +class NoSuchOption(UsageError): + """Raised if click attempted to handle an option that does not + exist. + + .. versionadded:: 4.0 + """ + + def __init__( + self, + option_name: str, + message: str | None = None, + possibilities: cabc.Sequence[str] | None = None, + ctx: Context | None = None, + ) -> None: + if message is None: + message = _("No such option: {name}").format(name=option_name) + + super().__init__(message, ctx) + self.option_name = option_name + self.possibilities = possibilities + + def format_message(self) -> str: + if not self.possibilities: + return self.message + + possibility_str = ", ".join(sorted(self.possibilities)) + suggest = ngettext( + "Did you mean {possibility}?", + "(Possible options: {possibilities})", + len(self.possibilities), + ).format(possibility=possibility_str, possibilities=possibility_str) + return f"{self.message} {suggest}" + + +class BadOptionUsage(UsageError): + """Raised if an option is generally supplied but the use of the option + was incorrect. This is for instance raised if the number of arguments + for an option is not correct. + + .. versionadded:: 4.0 + + :param option_name: the name of the option being used incorrectly. + """ + + def __init__( + self, option_name: str, message: str, ctx: Context | None = None + ) -> None: + super().__init__(message, ctx) + self.option_name = option_name + + +class BadArgumentUsage(UsageError): + """Raised if an argument is generally supplied but the use of the argument + was incorrect. This is for instance raised if the number of values + for an argument is not correct. + + .. versionadded:: 6.0 + """ + + +class NoArgsIsHelpError(UsageError): + def __init__(self, ctx: Context) -> None: + self.ctx: Context + super().__init__(ctx.get_help(), ctx=ctx) + + def show(self, file: t.IO[t.Any] | None = None) -> None: + echo(self.format_message(), file=file, err=True, color=self.ctx.color) + + +class FileError(ClickException): + """Raised if a file cannot be opened.""" + + def __init__(self, filename: str, hint: str | None = None) -> None: + if hint is None: + hint = _("unknown error") + + super().__init__(hint) + self.ui_filename: str = format_filename(filename) + self.filename = filename + + def format_message(self) -> str: + return _("Could not open file {filename!r}: {message}").format( + filename=self.ui_filename, message=self.message + ) + + +class Abort(RuntimeError): + """An internal signalling exception that signals Click to abort.""" + + +class Exit(RuntimeError): + """An exception that indicates that the application should exit with some + status code. + + :param code: the status code to exit with. + """ + + __slots__ = ("exit_code",) + + def __init__(self, code: int = 0) -> None: + self.exit_code: int = code diff --git a/backend/venv/Lib/site-packages/click/formatting.py b/backend/venv/Lib/site-packages/click/formatting.py new file mode 100644 index 0000000..0b64f83 --- /dev/null +++ b/backend/venv/Lib/site-packages/click/formatting.py @@ -0,0 +1,301 @@ +from __future__ import annotations + +import collections.abc as cabc +from contextlib import contextmanager +from gettext import gettext as _ + +from ._compat import term_len +from .parser import _split_opt + +# Can force a width. This is used by the test system +FORCED_WIDTH: int | None = None + + +def measure_table(rows: cabc.Iterable[tuple[str, str]]) -> tuple[int, ...]: + widths: dict[int, int] = {} + + for row in rows: + for idx, col in enumerate(row): + widths[idx] = max(widths.get(idx, 0), term_len(col)) + + return tuple(y for x, y in sorted(widths.items())) + + +def iter_rows( + rows: cabc.Iterable[tuple[str, str]], col_count: int +) -> cabc.Iterator[tuple[str, ...]]: + for row in rows: + yield row + ("",) * (col_count - len(row)) + + +def wrap_text( + text: str, + width: int = 78, + initial_indent: str = "", + subsequent_indent: str = "", + preserve_paragraphs: bool = False, +) -> str: + """A helper function that intelligently wraps text. By default, it + assumes that it operates on a single paragraph of text but if the + `preserve_paragraphs` parameter is provided it will intelligently + handle paragraphs (defined by two empty lines). + + If paragraphs are handled, a paragraph can be prefixed with an empty + line containing the ``\\b`` character (``\\x08``) to indicate that + no rewrapping should happen in that block. + + :param text: the text that should be rewrapped. + :param width: the maximum width for the text. + :param initial_indent: the initial indent that should be placed on the + first line as a string. + :param subsequent_indent: the indent string that should be placed on + each consecutive line. + :param preserve_paragraphs: if this flag is set then the wrapping will + intelligently handle paragraphs. + """ + from ._textwrap import TextWrapper + + text = text.expandtabs() + wrapper = TextWrapper( + width, + initial_indent=initial_indent, + subsequent_indent=subsequent_indent, + replace_whitespace=False, + ) + if not preserve_paragraphs: + return wrapper.fill(text) + + p: list[tuple[int, bool, str]] = [] + buf: list[str] = [] + indent = None + + def _flush_par() -> None: + if not buf: + return + if buf[0].strip() == "\b": + p.append((indent or 0, True, "\n".join(buf[1:]))) + else: + p.append((indent or 0, False, " ".join(buf))) + del buf[:] + + for line in text.splitlines(): + if not line: + _flush_par() + indent = None + else: + if indent is None: + orig_len = term_len(line) + line = line.lstrip() + indent = orig_len - term_len(line) + buf.append(line) + _flush_par() + + rv = [] + for indent, raw, text in p: + with wrapper.extra_indent(" " * indent): + if raw: + rv.append(wrapper.indent_only(text)) + else: + rv.append(wrapper.fill(text)) + + return "\n\n".join(rv) + + +class HelpFormatter: + """This class helps with formatting text-based help pages. It's + usually just needed for very special internal cases, but it's also + exposed so that developers can write their own fancy outputs. + + At present, it always writes into memory. + + :param indent_increment: the additional increment for each level. + :param width: the width for the text. This defaults to the terminal + width clamped to a maximum of 78. + """ + + def __init__( + self, + indent_increment: int = 2, + width: int | None = None, + max_width: int | None = None, + ) -> None: + self.indent_increment = indent_increment + if max_width is None: + max_width = 80 + if width is None: + import shutil + + width = FORCED_WIDTH + if width is None: + width = max(min(shutil.get_terminal_size().columns, max_width) - 2, 50) + self.width = width + self.current_indent: int = 0 + self.buffer: list[str] = [] + + def write(self, string: str) -> None: + """Writes a unicode string into the internal buffer.""" + self.buffer.append(string) + + def indent(self) -> None: + """Increases the indentation.""" + self.current_indent += self.indent_increment + + def dedent(self) -> None: + """Decreases the indentation.""" + self.current_indent -= self.indent_increment + + def write_usage(self, prog: str, args: str = "", prefix: str | None = None) -> None: + """Writes a usage line into the buffer. + + :param prog: the program name. + :param args: whitespace separated list of arguments. + :param prefix: The prefix for the first line. Defaults to + ``"Usage: "``. + """ + if prefix is None: + prefix = f"{_('Usage:')} " + + usage_prefix = f"{prefix:>{self.current_indent}}{prog} " + text_width = self.width - self.current_indent + + if text_width >= (term_len(usage_prefix) + 20): + # The arguments will fit to the right of the prefix. + indent = " " * term_len(usage_prefix) + self.write( + wrap_text( + args, + text_width, + initial_indent=usage_prefix, + subsequent_indent=indent, + ) + ) + else: + # The prefix is too long, put the arguments on the next line. + self.write(usage_prefix) + self.write("\n") + indent = " " * (max(self.current_indent, term_len(prefix)) + 4) + self.write( + wrap_text( + args, text_width, initial_indent=indent, subsequent_indent=indent + ) + ) + + self.write("\n") + + def write_heading(self, heading: str) -> None: + """Writes a heading into the buffer.""" + self.write(f"{'':>{self.current_indent}}{heading}:\n") + + def write_paragraph(self) -> None: + """Writes a paragraph into the buffer.""" + if self.buffer: + self.write("\n") + + def write_text(self, text: str) -> None: + """Writes re-indented text into the buffer. This rewraps and + preserves paragraphs. + """ + indent = " " * self.current_indent + self.write( + wrap_text( + text, + self.width, + initial_indent=indent, + subsequent_indent=indent, + preserve_paragraphs=True, + ) + ) + self.write("\n") + + def write_dl( + self, + rows: cabc.Sequence[tuple[str, str]], + col_max: int = 30, + col_spacing: int = 2, + ) -> None: + """Writes a definition list into the buffer. This is how options + and commands are usually formatted. + + :param rows: a list of two item tuples for the terms and values. + :param col_max: the maximum width of the first column. + :param col_spacing: the number of spaces between the first and + second column. + """ + rows = list(rows) + widths = measure_table(rows) + if len(widths) != 2: + raise TypeError("Expected two columns for definition list") + + first_col = min(widths[0], col_max) + col_spacing + + for first, second in iter_rows(rows, len(widths)): + self.write(f"{'':>{self.current_indent}}{first}") + if not second: + self.write("\n") + continue + if term_len(first) <= first_col - col_spacing: + self.write(" " * (first_col - term_len(first))) + else: + self.write("\n") + self.write(" " * (first_col + self.current_indent)) + + text_width = max(self.width - first_col - 2, 10) + wrapped_text = wrap_text(second, text_width, preserve_paragraphs=True) + lines = wrapped_text.splitlines() + + if lines: + self.write(f"{lines[0]}\n") + + for line in lines[1:]: + self.write(f"{'':>{first_col + self.current_indent}}{line}\n") + else: + self.write("\n") + + @contextmanager + def section(self, name: str) -> cabc.Iterator[None]: + """Helpful context manager that writes a paragraph, a heading, + and the indents. + + :param name: the section name that is written as heading. + """ + self.write_paragraph() + self.write_heading(name) + self.indent() + try: + yield + finally: + self.dedent() + + @contextmanager + def indentation(self) -> cabc.Iterator[None]: + """A context manager that increases the indentation.""" + self.indent() + try: + yield + finally: + self.dedent() + + def getvalue(self) -> str: + """Returns the buffer contents.""" + return "".join(self.buffer) + + +def join_options(options: cabc.Sequence[str]) -> tuple[str, bool]: + """Given a list of option strings this joins them in the most appropriate + way and returns them in the form ``(formatted_string, + any_prefix_is_slash)`` where the second item in the tuple is a flag that + indicates if any of the option prefixes was a slash. + """ + rv = [] + any_prefix_is_slash = False + + for opt in options: + prefix = _split_opt(opt)[0] + + if prefix == "/": + any_prefix_is_slash = True + + rv.append((len(prefix), opt)) + + rv.sort(key=lambda x: x[0]) + return ", ".join(x[1] for x in rv), any_prefix_is_slash diff --git a/backend/venv/Lib/site-packages/click/globals.py b/backend/venv/Lib/site-packages/click/globals.py new file mode 100644 index 0000000..a2f9172 --- /dev/null +++ b/backend/venv/Lib/site-packages/click/globals.py @@ -0,0 +1,67 @@ +from __future__ import annotations + +import typing as t +from threading import local + +if t.TYPE_CHECKING: + from .core import Context + +_local = local() + + +@t.overload +def get_current_context(silent: t.Literal[False] = False) -> Context: ... + + +@t.overload +def get_current_context(silent: bool = ...) -> Context | None: ... + + +def get_current_context(silent: bool = False) -> Context | None: + """Returns the current click context. This can be used as a way to + access the current context object from anywhere. This is a more implicit + alternative to the :func:`pass_context` decorator. This function is + primarily useful for helpers such as :func:`echo` which might be + interested in changing its behavior based on the current context. + + To push the current context, :meth:`Context.scope` can be used. + + .. versionadded:: 5.0 + + :param silent: if set to `True` the return value is `None` if no context + is available. The default behavior is to raise a + :exc:`RuntimeError`. + """ + try: + return t.cast("Context", _local.stack[-1]) + except (AttributeError, IndexError) as e: + if not silent: + raise RuntimeError("There is no active click context.") from e + + return None + + +def push_context(ctx: Context) -> None: + """Pushes a new context to the current stack.""" + _local.__dict__.setdefault("stack", []).append(ctx) + + +def pop_context() -> None: + """Removes the top level from the stack.""" + _local.stack.pop() + + +def resolve_color_default(color: bool | None = None) -> bool | None: + """Internal helper to get the default value of the color flag. If a + value is passed it's returned unchanged, otherwise it's looked up from + the current context. + """ + if color is not None: + return color + + ctx = get_current_context(silent=True) + + if ctx is not None: + return ctx.color + + return None diff --git a/backend/venv/Lib/site-packages/click/parser.py b/backend/venv/Lib/site-packages/click/parser.py new file mode 100644 index 0000000..1ea1f71 --- /dev/null +++ b/backend/venv/Lib/site-packages/click/parser.py @@ -0,0 +1,532 @@ +""" +This module started out as largely a copy paste from the stdlib's +optparse module with the features removed that we do not need from +optparse because we implement them in Click on a higher level (for +instance type handling, help formatting and a lot more). + +The plan is to remove more and more from here over time. + +The reason this is a different module and not optparse from the stdlib +is that there are differences in 2.x and 3.x about the error messages +generated and optparse in the stdlib uses gettext for no good reason +and might cause us issues. + +Click uses parts of optparse written by Gregory P. Ward and maintained +by the Python Software Foundation. This is limited to code in parser.py. + +Copyright 2001-2006 Gregory P. Ward. All rights reserved. +Copyright 2002-2006 Python Software Foundation. All rights reserved. +""" + +# This code uses parts of optparse written by Gregory P. Ward and +# maintained by the Python Software Foundation. +# Copyright 2001-2006 Gregory P. Ward +# Copyright 2002-2006 Python Software Foundation +from __future__ import annotations + +import collections.abc as cabc +import typing as t +from collections import deque +from gettext import gettext as _ +from gettext import ngettext + +from ._utils import FLAG_NEEDS_VALUE +from ._utils import UNSET +from .exceptions import BadArgumentUsage +from .exceptions import BadOptionUsage +from .exceptions import NoSuchOption +from .exceptions import UsageError + +if t.TYPE_CHECKING: + from ._utils import T_FLAG_NEEDS_VALUE + from ._utils import T_UNSET + from .core import Argument as CoreArgument + from .core import Context + from .core import Option as CoreOption + from .core import Parameter as CoreParameter + +V = t.TypeVar("V") + + +def _unpack_args( + args: cabc.Sequence[str], nargs_spec: cabc.Sequence[int] +) -> tuple[cabc.Sequence[str | cabc.Sequence[str | None] | None], list[str]]: + """Given an iterable of arguments and an iterable of nargs specifications, + it returns a tuple with all the unpacked arguments at the first index + and all remaining arguments as the second. + + The nargs specification is the number of arguments that should be consumed + or `-1` to indicate that this position should eat up all the remainders. + + Missing items are filled with ``UNSET``. + """ + args = deque(args) + nargs_spec = deque(nargs_spec) + rv: list[str | tuple[str | T_UNSET, ...] | T_UNSET] = [] + spos: int | None = None + + def _fetch(c: deque[V]) -> V | T_UNSET: + try: + if spos is None: + return c.popleft() + else: + return c.pop() + except IndexError: + return UNSET + + while nargs_spec: + nargs = _fetch(nargs_spec) + + if nargs is None: + continue + + if nargs == 1: + rv.append(_fetch(args)) # type: ignore[arg-type] + elif nargs > 1: + x = [_fetch(args) for _ in range(nargs)] + + # If we're reversed, we're pulling in the arguments in reverse, + # so we need to turn them around. + if spos is not None: + x.reverse() + + rv.append(tuple(x)) + elif nargs < 0: + if spos is not None: + raise TypeError("Cannot have two nargs < 0") + + spos = len(rv) + rv.append(UNSET) + + # spos is the position of the wildcard (star). If it's not `None`, + # we fill it with the remainder. + if spos is not None: + rv[spos] = tuple(args) + args = [] + rv[spos + 1 :] = reversed(rv[spos + 1 :]) + + return tuple(rv), list(args) + + +def _split_opt(opt: str) -> tuple[str, str]: + first = opt[:1] + if first.isalnum(): + return "", opt + if opt[1:2] == first: + return opt[:2], opt[2:] + return first, opt[1:] + + +def _normalize_opt(opt: str, ctx: Context | None) -> str: + if ctx is None or ctx.token_normalize_func is None: + return opt + prefix, opt = _split_opt(opt) + return f"{prefix}{ctx.token_normalize_func(opt)}" + + +class _Option: + def __init__( + self, + obj: CoreOption, + opts: cabc.Sequence[str], + dest: str | None, + action: str | None = None, + nargs: int = 1, + const: t.Any | None = None, + ): + self._short_opts = [] + self._long_opts = [] + self.prefixes: set[str] = set() + + for opt in opts: + prefix, value = _split_opt(opt) + if not prefix: + raise ValueError(f"Invalid start character for option ({opt})") + self.prefixes.add(prefix[0]) + if len(prefix) == 1 and len(value) == 1: + self._short_opts.append(opt) + else: + self._long_opts.append(opt) + self.prefixes.add(prefix) + + if action is None: + action = "store" + + self.dest = dest + self.action = action + self.nargs = nargs + self.const = const + self.obj = obj + + @property + def takes_value(self) -> bool: + return self.action in ("store", "append") + + def process(self, value: t.Any, state: _ParsingState) -> None: + if self.action == "store": + state.opts[self.dest] = value # type: ignore + elif self.action == "store_const": + state.opts[self.dest] = self.const # type: ignore + elif self.action == "append": + state.opts.setdefault(self.dest, []).append(value) # type: ignore + elif self.action == "append_const": + state.opts.setdefault(self.dest, []).append(self.const) # type: ignore + elif self.action == "count": + state.opts[self.dest] = state.opts.get(self.dest, 0) + 1 # type: ignore + else: + raise ValueError(f"unknown action '{self.action}'") + state.order.append(self.obj) + + +class _Argument: + def __init__(self, obj: CoreArgument, dest: str | None, nargs: int = 1): + self.dest = dest + self.nargs = nargs + self.obj = obj + + def process( + self, + value: str | cabc.Sequence[str | None] | None | T_UNSET, + state: _ParsingState, + ) -> None: + if self.nargs > 1: + assert isinstance(value, cabc.Sequence) + holes = sum(1 for x in value if x is UNSET) + if holes == len(value): + value = UNSET + elif holes != 0: + raise BadArgumentUsage( + _("Argument {name!r} takes {nargs} values.").format( + name=self.dest, nargs=self.nargs + ) + ) + + # We failed to collect any argument value so we consider the argument as unset. + if value == (): + value = UNSET + + state.opts[self.dest] = value # type: ignore + state.order.append(self.obj) + + +class _ParsingState: + def __init__(self, rargs: list[str]) -> None: + self.opts: dict[str, t.Any] = {} + self.largs: list[str] = [] + self.rargs = rargs + self.order: list[CoreParameter] = [] + + +class _OptionParser: + """The option parser is an internal class that is ultimately used to + parse options and arguments. It's modelled after optparse and brings + a similar but vastly simplified API. It should generally not be used + directly as the high level Click classes wrap it for you. + + It's not nearly as extensible as optparse or argparse as it does not + implement features that are implemented on a higher level (such as + types or defaults). + + :param ctx: optionally the :class:`~click.Context` where this parser + should go with. + + .. deprecated:: 8.2 + Will be removed in Click 9.0. + """ + + def __init__(self, ctx: Context | None = None) -> None: + #: The :class:`~click.Context` for this parser. This might be + #: `None` for some advanced use cases. + self.ctx = ctx + #: This controls how the parser deals with interspersed arguments. + #: If this is set to `False`, the parser will stop on the first + #: non-option. Click uses this to implement nested subcommands + #: safely. + self.allow_interspersed_args: bool = True + #: This tells the parser how to deal with unknown options. By + #: default it will error out (which is sensible), but there is a + #: second mode where it will ignore it and continue processing + #: after shifting all the unknown options into the resulting args. + self.ignore_unknown_options: bool = False + + if ctx is not None: + self.allow_interspersed_args = ctx.allow_interspersed_args + self.ignore_unknown_options = ctx.ignore_unknown_options + + self._short_opt: dict[str, _Option] = {} + self._long_opt: dict[str, _Option] = {} + self._opt_prefixes = {"-", "--"} + self._args: list[_Argument] = [] + + def add_option( + self, + obj: CoreOption, + opts: cabc.Sequence[str], + dest: str | None, + action: str | None = None, + nargs: int = 1, + const: t.Any | None = None, + ) -> None: + """Adds a new option named `dest` to the parser. The destination + is not inferred (unlike with optparse) and needs to be explicitly + provided. Action can be any of ``store``, ``store_const``, + ``append``, ``append_const`` or ``count``. + + The `obj` can be used to identify the option in the order list + that is returned from the parser. + """ + opts = [_normalize_opt(opt, self.ctx) for opt in opts] + option = _Option(obj, opts, dest, action=action, nargs=nargs, const=const) + self._opt_prefixes.update(option.prefixes) + for opt in option._short_opts: + self._short_opt[opt] = option + for opt in option._long_opts: + self._long_opt[opt] = option + + def add_argument(self, obj: CoreArgument, dest: str | None, nargs: int = 1) -> None: + """Adds a positional argument named `dest` to the parser. + + The `obj` can be used to identify the option in the order list + that is returned from the parser. + """ + self._args.append(_Argument(obj, dest=dest, nargs=nargs)) + + def parse_args( + self, args: list[str] + ) -> tuple[dict[str, t.Any], list[str], list[CoreParameter]]: + """Parses positional arguments and returns ``(values, args, order)`` + for the parsed options and arguments as well as the leftover + arguments if there are any. The order is a list of objects as they + appear on the command line. If arguments appear multiple times they + will be memorized multiple times as well. + """ + state = _ParsingState(args) + try: + self._process_args_for_options(state) + self._process_args_for_args(state) + except UsageError: + if self.ctx is None or not self.ctx.resilient_parsing: + raise + return state.opts, state.largs, state.order + + def _process_args_for_args(self, state: _ParsingState) -> None: + pargs, args = _unpack_args( + state.largs + state.rargs, [x.nargs for x in self._args] + ) + + for idx, arg in enumerate(self._args): + arg.process(pargs[idx], state) + + state.largs = args + state.rargs = [] + + def _process_args_for_options(self, state: _ParsingState) -> None: + while state.rargs: + arg = state.rargs.pop(0) + arglen = len(arg) + # Double dashes always handled explicitly regardless of what + # prefixes are valid. + if arg == "--": + return + elif arg[:1] in self._opt_prefixes and arglen > 1: + self._process_opts(arg, state) + elif self.allow_interspersed_args: + state.largs.append(arg) + else: + state.rargs.insert(0, arg) + return + + # Say this is the original argument list: + # [arg0, arg1, ..., arg(i-1), arg(i), arg(i+1), ..., arg(N-1)] + # ^ + # (we are about to process arg(i)). + # + # Then rargs is [arg(i), ..., arg(N-1)] and largs is a *subset* of + # [arg0, ..., arg(i-1)] (any options and their arguments will have + # been removed from largs). + # + # The while loop will usually consume 1 or more arguments per pass. + # If it consumes 1 (eg. arg is an option that takes no arguments), + # then after _process_arg() is done the situation is: + # + # largs = subset of [arg0, ..., arg(i)] + # rargs = [arg(i+1), ..., arg(N-1)] + # + # If allow_interspersed_args is false, largs will always be + # *empty* -- still a subset of [arg0, ..., arg(i-1)], but + # not a very interesting subset! + + def _match_long_opt( + self, opt: str, explicit_value: str | None, state: _ParsingState + ) -> None: + if opt not in self._long_opt: + from difflib import get_close_matches + + possibilities = get_close_matches(opt, self._long_opt) + raise NoSuchOption(opt, possibilities=possibilities, ctx=self.ctx) + + option = self._long_opt[opt] + if option.takes_value: + # At this point it's safe to modify rargs by injecting the + # explicit value, because no exception is raised in this + # branch. This means that the inserted value will be fully + # consumed. + if explicit_value is not None: + state.rargs.insert(0, explicit_value) + + value = self._get_value_from_state(opt, option, state) + + elif explicit_value is not None: + raise BadOptionUsage( + opt, _("Option {name!r} does not take a value.").format(name=opt) + ) + + else: + value = UNSET + + option.process(value, state) + + def _match_short_opt(self, arg: str, state: _ParsingState) -> None: + stop = False + i = 1 + prefix = arg[0] + unknown_options = [] + + for ch in arg[1:]: + opt = _normalize_opt(f"{prefix}{ch}", self.ctx) + option = self._short_opt.get(opt) + i += 1 + + if not option: + if self.ignore_unknown_options: + unknown_options.append(ch) + continue + raise NoSuchOption(opt, ctx=self.ctx) + if option.takes_value: + # Any characters left in arg? Pretend they're the + # next arg, and stop consuming characters of arg. + if i < len(arg): + state.rargs.insert(0, arg[i:]) + stop = True + + value = self._get_value_from_state(opt, option, state) + + else: + value = UNSET + + option.process(value, state) + + if stop: + break + + # If we got any unknown options we recombine the string of the + # remaining options and re-attach the prefix, then report that + # to the state as new larg. This way there is basic combinatorics + # that can be achieved while still ignoring unknown arguments. + if self.ignore_unknown_options and unknown_options: + state.largs.append(f"{prefix}{''.join(unknown_options)}") + + def _get_value_from_state( + self, option_name: str, option: _Option, state: _ParsingState + ) -> str | cabc.Sequence[str] | T_FLAG_NEEDS_VALUE: + nargs = option.nargs + + value: str | cabc.Sequence[str] | T_FLAG_NEEDS_VALUE + + if len(state.rargs) < nargs: + if option.obj._flag_needs_value: + # Option allows omitting the value. + value = FLAG_NEEDS_VALUE + else: + raise BadOptionUsage( + option_name, + ngettext( + "Option {name!r} requires an argument.", + "Option {name!r} requires {nargs} arguments.", + nargs, + ).format(name=option_name, nargs=nargs), + ) + elif nargs == 1: + next_rarg = state.rargs[0] + + if ( + option.obj._flag_needs_value + and isinstance(next_rarg, str) + and next_rarg[:1] in self._opt_prefixes + and len(next_rarg) > 1 + ): + # The next arg looks like the start of an option, don't + # use it as the value if omitting the value is allowed. + value = FLAG_NEEDS_VALUE + else: + value = state.rargs.pop(0) + else: + value = tuple(state.rargs[:nargs]) + del state.rargs[:nargs] + + return value + + def _process_opts(self, arg: str, state: _ParsingState) -> None: + explicit_value = None + # Long option handling happens in two parts. The first part is + # supporting explicitly attached values. In any case, we will try + # to long match the option first. + if "=" in arg: + long_opt, explicit_value = arg.split("=", 1) + else: + long_opt = arg + norm_long_opt = _normalize_opt(long_opt, self.ctx) + + # At this point we will match the (assumed) long option through + # the long option matching code. Note that this allows options + # like "-foo" to be matched as long options. + try: + self._match_long_opt(norm_long_opt, explicit_value, state) + except NoSuchOption: + # At this point the long option matching failed, and we need + # to try with short options. However there is a special rule + # which says, that if we have a two character options prefix + # (applies to "--foo" for instance), we do not dispatch to the + # short option code and will instead raise the no option + # error. + if arg[:2] not in self._opt_prefixes: + self._match_short_opt(arg, state) + return + + if not self.ignore_unknown_options: + raise + + state.largs.append(arg) + + +def __getattr__(name: str) -> object: + import warnings + + if name in { + "OptionParser", + "Argument", + "Option", + "split_opt", + "normalize_opt", + "ParsingState", + }: + warnings.warn( + f"'parser.{name}' is deprecated and will be removed in Click 9.0." + " The old parser is available in 'optparse'.", + DeprecationWarning, + stacklevel=2, + ) + return globals()[f"_{name}"] + + if name == "split_arg_string": + from .shell_completion import split_arg_string + + warnings.warn( + "Importing 'parser.split_arg_string' is deprecated, it will only be" + " available in 'shell_completion' in Click 9.0.", + DeprecationWarning, + stacklevel=2, + ) + return split_arg_string + + raise AttributeError(name) diff --git a/backend/venv/Lib/site-packages/click/py.typed b/backend/venv/Lib/site-packages/click/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/backend/venv/Lib/site-packages/click/shell_completion.py b/backend/venv/Lib/site-packages/click/shell_completion.py new file mode 100644 index 0000000..8f1564c --- /dev/null +++ b/backend/venv/Lib/site-packages/click/shell_completion.py @@ -0,0 +1,667 @@ +from __future__ import annotations + +import collections.abc as cabc +import os +import re +import typing as t +from gettext import gettext as _ + +from .core import Argument +from .core import Command +from .core import Context +from .core import Group +from .core import Option +from .core import Parameter +from .core import ParameterSource +from .utils import echo + + +def shell_complete( + cli: Command, + ctx_args: cabc.MutableMapping[str, t.Any], + prog_name: str, + complete_var: str, + instruction: str, +) -> int: + """Perform shell completion for the given CLI program. + + :param cli: Command being called. + :param ctx_args: Extra arguments to pass to + ``cli.make_context``. + :param prog_name: Name of the executable in the shell. + :param complete_var: Name of the environment variable that holds + the completion instruction. + :param instruction: Value of ``complete_var`` with the completion + instruction and shell, in the form ``instruction_shell``. + :return: Status code to exit with. + """ + shell, _, instruction = instruction.partition("_") + comp_cls = get_completion_class(shell) + + if comp_cls is None: + return 1 + + comp = comp_cls(cli, ctx_args, prog_name, complete_var) + + if instruction == "source": + echo(comp.source()) + return 0 + + if instruction == "complete": + echo(comp.complete()) + return 0 + + return 1 + + +class CompletionItem: + """Represents a completion value and metadata about the value. The + default metadata is ``type`` to indicate special shell handling, + and ``help`` if a shell supports showing a help string next to the + value. + + Arbitrary parameters can be passed when creating the object, and + accessed using ``item.attr``. If an attribute wasn't passed, + accessing it returns ``None``. + + :param value: The completion suggestion. + :param type: Tells the shell script to provide special completion + support for the type. Click uses ``"dir"`` and ``"file"``. + :param help: String shown next to the value if supported. + :param kwargs: Arbitrary metadata. The built-in implementations + don't use this, but custom type completions paired with custom + shell support could use it. + """ + + __slots__ = ("value", "type", "help", "_info") + + def __init__( + self, + value: t.Any, + type: str = "plain", + help: str | None = None, + **kwargs: t.Any, + ) -> None: + self.value: t.Any = value + self.type: str = type + self.help: str | None = help + self._info = kwargs + + def __getattr__(self, name: str) -> t.Any: + return self._info.get(name) + + +# Only Bash >= 4.4 has the nosort option. +_SOURCE_BASH = """\ +%(complete_func)s() { + local IFS=$'\\n' + local response + + response=$(env COMP_WORDS="${COMP_WORDS[*]}" COMP_CWORD=$COMP_CWORD \ +%(complete_var)s=bash_complete $1) + + for completion in $response; do + IFS=',' read type value <<< "$completion" + + if [[ $type == 'dir' ]]; then + COMPREPLY=() + compopt -o dirnames + elif [[ $type == 'file' ]]; then + COMPREPLY=() + compopt -o default + elif [[ $type == 'plain' ]]; then + COMPREPLY+=($value) + fi + done + + return 0 +} + +%(complete_func)s_setup() { + complete -o nosort -F %(complete_func)s %(prog_name)s +} + +%(complete_func)s_setup; +""" + +# See ZshComplete.format_completion below, and issue #2703, before +# changing this script. +# +# (TL;DR: _describe is picky about the format, but this Zsh script snippet +# is already widely deployed. So freeze this script, and use clever-ish +# handling of colons in ZshComplet.format_completion.) +_SOURCE_ZSH = """\ +#compdef %(prog_name)s + +%(complete_func)s() { + local -a completions + local -a completions_with_descriptions + local -a response + (( ! $+commands[%(prog_name)s] )) && return 1 + + response=("${(@f)$(env COMP_WORDS="${words[*]}" COMP_CWORD=$((CURRENT-1)) \ +%(complete_var)s=zsh_complete %(prog_name)s)}") + + for type key descr in ${response}; do + if [[ "$type" == "plain" ]]; then + if [[ "$descr" == "_" ]]; then + completions+=("$key") + else + completions_with_descriptions+=("$key":"$descr") + fi + elif [[ "$type" == "dir" ]]; then + _path_files -/ + elif [[ "$type" == "file" ]]; then + _path_files -f + fi + done + + if [ -n "$completions_with_descriptions" ]; then + _describe -V unsorted completions_with_descriptions -U + fi + + if [ -n "$completions" ]; then + compadd -U -V unsorted -a completions + fi +} + +if [[ $zsh_eval_context[-1] == loadautofunc ]]; then + # autoload from fpath, call function directly + %(complete_func)s "$@" +else + # eval/source/. command, register function for later + compdef %(complete_func)s %(prog_name)s +fi +""" + +_SOURCE_FISH = """\ +function %(complete_func)s; + set -l response (env %(complete_var)s=fish_complete COMP_WORDS=(commandline -cp) \ +COMP_CWORD=(commandline -t) %(prog_name)s); + + for completion in $response; + set -l metadata (string split "," $completion); + + if test $metadata[1] = "dir"; + __fish_complete_directories $metadata[2]; + else if test $metadata[1] = "file"; + __fish_complete_path $metadata[2]; + else if test $metadata[1] = "plain"; + echo $metadata[2]; + end; + end; +end; + +complete --no-files --command %(prog_name)s --arguments \ +"(%(complete_func)s)"; +""" + + +class ShellComplete: + """Base class for providing shell completion support. A subclass for + a given shell will override attributes and methods to implement the + completion instructions (``source`` and ``complete``). + + :param cli: Command being called. + :param prog_name: Name of the executable in the shell. + :param complete_var: Name of the environment variable that holds + the completion instruction. + + .. versionadded:: 8.0 + """ + + name: t.ClassVar[str] + """Name to register the shell as with :func:`add_completion_class`. + This is used in completion instructions (``{name}_source`` and + ``{name}_complete``). + """ + + source_template: t.ClassVar[str] + """Completion script template formatted by :meth:`source`. This must + be provided by subclasses. + """ + + def __init__( + self, + cli: Command, + ctx_args: cabc.MutableMapping[str, t.Any], + prog_name: str, + complete_var: str, + ) -> None: + self.cli = cli + self.ctx_args = ctx_args + self.prog_name = prog_name + self.complete_var = complete_var + + @property + def func_name(self) -> str: + """The name of the shell function defined by the completion + script. + """ + safe_name = re.sub(r"\W*", "", self.prog_name.replace("-", "_"), flags=re.ASCII) + return f"_{safe_name}_completion" + + def source_vars(self) -> dict[str, t.Any]: + """Vars for formatting :attr:`source_template`. + + By default this provides ``complete_func``, ``complete_var``, + and ``prog_name``. + """ + return { + "complete_func": self.func_name, + "complete_var": self.complete_var, + "prog_name": self.prog_name, + } + + def source(self) -> str: + """Produce the shell script that defines the completion + function. By default this ``%``-style formats + :attr:`source_template` with the dict returned by + :meth:`source_vars`. + """ + return self.source_template % self.source_vars() + + def get_completion_args(self) -> tuple[list[str], str]: + """Use the env vars defined by the shell script to return a + tuple of ``args, incomplete``. This must be implemented by + subclasses. + """ + raise NotImplementedError + + def get_completions(self, args: list[str], incomplete: str) -> list[CompletionItem]: + """Determine the context and last complete command or parameter + from the complete args. Call that object's ``shell_complete`` + method to get the completions for the incomplete value. + + :param args: List of complete args before the incomplete value. + :param incomplete: Value being completed. May be empty. + """ + ctx = _resolve_context(self.cli, self.ctx_args, self.prog_name, args) + obj, incomplete = _resolve_incomplete(ctx, args, incomplete) + return obj.shell_complete(ctx, incomplete) + + def format_completion(self, item: CompletionItem) -> str: + """Format a completion item into the form recognized by the + shell script. This must be implemented by subclasses. + + :param item: Completion item to format. + """ + raise NotImplementedError + + def complete(self) -> str: + """Produce the completion data to send back to the shell. + + By default this calls :meth:`get_completion_args`, gets the + completions, then calls :meth:`format_completion` for each + completion. + """ + args, incomplete = self.get_completion_args() + completions = self.get_completions(args, incomplete) + out = [self.format_completion(item) for item in completions] + return "\n".join(out) + + +class BashComplete(ShellComplete): + """Shell completion for Bash.""" + + name = "bash" + source_template = _SOURCE_BASH + + @staticmethod + def _check_version() -> None: + import shutil + import subprocess + + bash_exe = shutil.which("bash") + + if bash_exe is None: + match = None + else: + output = subprocess.run( + [bash_exe, "--norc", "-c", 'echo "${BASH_VERSION}"'], + stdout=subprocess.PIPE, + ) + match = re.search(r"^(\d+)\.(\d+)\.\d+", output.stdout.decode()) + + if match is not None: + major, minor = match.groups() + + if major < "4" or major == "4" and minor < "4": + echo( + _( + "Shell completion is not supported for Bash" + " versions older than 4.4." + ), + err=True, + ) + else: + echo( + _("Couldn't detect Bash version, shell completion is not supported."), + err=True, + ) + + def source(self) -> str: + self._check_version() + return super().source() + + def get_completion_args(self) -> tuple[list[str], str]: + cwords = split_arg_string(os.environ["COMP_WORDS"]) + cword = int(os.environ["COMP_CWORD"]) + args = cwords[1:cword] + + try: + incomplete = cwords[cword] + except IndexError: + incomplete = "" + + return args, incomplete + + def format_completion(self, item: CompletionItem) -> str: + return f"{item.type},{item.value}" + + +class ZshComplete(ShellComplete): + """Shell completion for Zsh.""" + + name = "zsh" + source_template = _SOURCE_ZSH + + def get_completion_args(self) -> tuple[list[str], str]: + cwords = split_arg_string(os.environ["COMP_WORDS"]) + cword = int(os.environ["COMP_CWORD"]) + args = cwords[1:cword] + + try: + incomplete = cwords[cword] + except IndexError: + incomplete = "" + + return args, incomplete + + def format_completion(self, item: CompletionItem) -> str: + help_ = item.help or "_" + # The zsh completion script uses `_describe` on items with help + # texts (which splits the item help from the item value at the + # first unescaped colon) and `compadd` on items without help + # text (which uses the item value as-is and does not support + # colon escaping). So escape colons in the item value if and + # only if the item help is not the sentinel "_" value, as used + # by the completion script. + # + # (The zsh completion script is potentially widely deployed, and + # thus harder to fix than this method.) + # + # See issue #1812 and issue #2703 for further context. + value = item.value.replace(":", r"\:") if help_ != "_" else item.value + return f"{item.type}\n{value}\n{help_}" + + +class FishComplete(ShellComplete): + """Shell completion for Fish.""" + + name = "fish" + source_template = _SOURCE_FISH + + def get_completion_args(self) -> tuple[list[str], str]: + cwords = split_arg_string(os.environ["COMP_WORDS"]) + incomplete = os.environ["COMP_CWORD"] + if incomplete: + incomplete = split_arg_string(incomplete)[0] + args = cwords[1:] + + # Fish stores the partial word in both COMP_WORDS and + # COMP_CWORD, remove it from complete args. + if incomplete and args and args[-1] == incomplete: + args.pop() + + return args, incomplete + + def format_completion(self, item: CompletionItem) -> str: + if item.help: + return f"{item.type},{item.value}\t{item.help}" + + return f"{item.type},{item.value}" + + +ShellCompleteType = t.TypeVar("ShellCompleteType", bound="type[ShellComplete]") + + +_available_shells: dict[str, type[ShellComplete]] = { + "bash": BashComplete, + "fish": FishComplete, + "zsh": ZshComplete, +} + + +def add_completion_class( + cls: ShellCompleteType, name: str | None = None +) -> ShellCompleteType: + """Register a :class:`ShellComplete` subclass under the given name. + The name will be provided by the completion instruction environment + variable during completion. + + :param cls: The completion class that will handle completion for the + shell. + :param name: Name to register the class under. Defaults to the + class's ``name`` attribute. + """ + if name is None: + name = cls.name + + _available_shells[name] = cls + + return cls + + +def get_completion_class(shell: str) -> type[ShellComplete] | None: + """Look up a registered :class:`ShellComplete` subclass by the name + provided by the completion instruction environment variable. If the + name isn't registered, returns ``None``. + + :param shell: Name the class is registered under. + """ + return _available_shells.get(shell) + + +def split_arg_string(string: str) -> list[str]: + """Split an argument string as with :func:`shlex.split`, but don't + fail if the string is incomplete. Ignores a missing closing quote or + incomplete escape sequence and uses the partial token as-is. + + .. code-block:: python + + split_arg_string("example 'my file") + ["example", "my file"] + + split_arg_string("example my\\") + ["example", "my"] + + :param string: String to split. + + .. versionchanged:: 8.2 + Moved to ``shell_completion`` from ``parser``. + """ + import shlex + + lex = shlex.shlex(string, posix=True) + lex.whitespace_split = True + lex.commenters = "" + out = [] + + try: + for token in lex: + out.append(token) + except ValueError: + # Raised when end-of-string is reached in an invalid state. Use + # the partial token as-is. The quote or escape character is in + # lex.state, not lex.token. + out.append(lex.token) + + return out + + +def _is_incomplete_argument(ctx: Context, param: Parameter) -> bool: + """Determine if the given parameter is an argument that can still + accept values. + + :param ctx: Invocation context for the command represented by the + parsed complete args. + :param param: Argument object being checked. + """ + if not isinstance(param, Argument): + return False + + assert param.name is not None + # Will be None if expose_value is False. + value = ctx.params.get(param.name) + return ( + param.nargs == -1 + or ctx.get_parameter_source(param.name) is not ParameterSource.COMMANDLINE + or ( + param.nargs > 1 + and isinstance(value, (tuple, list)) + and len(value) < param.nargs + ) + ) + + +def _start_of_option(ctx: Context, value: str) -> bool: + """Check if the value looks like the start of an option.""" + if not value: + return False + + c = value[0] + return c in ctx._opt_prefixes + + +def _is_incomplete_option(ctx: Context, args: list[str], param: Parameter) -> bool: + """Determine if the given parameter is an option that needs a value. + + :param args: List of complete args before the incomplete value. + :param param: Option object being checked. + """ + if not isinstance(param, Option): + return False + + if param.is_flag or param.count: + return False + + last_option = None + + for index, arg in enumerate(reversed(args)): + if index + 1 > param.nargs: + break + + if _start_of_option(ctx, arg): + last_option = arg + break + + return last_option is not None and last_option in param.opts + + +def _resolve_context( + cli: Command, + ctx_args: cabc.MutableMapping[str, t.Any], + prog_name: str, + args: list[str], +) -> Context: + """Produce the context hierarchy starting with the command and + traversing the complete arguments. This only follows the commands, + it doesn't trigger input prompts or callbacks. + + :param cli: Command being called. + :param prog_name: Name of the executable in the shell. + :param args: List of complete args before the incomplete value. + """ + ctx_args["resilient_parsing"] = True + with cli.make_context(prog_name, args.copy(), **ctx_args) as ctx: + args = ctx._protected_args + ctx.args + + while args: + command = ctx.command + + if isinstance(command, Group): + if not command.chain: + name, cmd, args = command.resolve_command(ctx, args) + + if cmd is None: + return ctx + + with cmd.make_context( + name, args, parent=ctx, resilient_parsing=True + ) as sub_ctx: + ctx = sub_ctx + args = ctx._protected_args + ctx.args + else: + sub_ctx = ctx + + while args: + name, cmd, args = command.resolve_command(ctx, args) + + if cmd is None: + return ctx + + with cmd.make_context( + name, + args, + parent=ctx, + allow_extra_args=True, + allow_interspersed_args=False, + resilient_parsing=True, + ) as sub_sub_ctx: + sub_ctx = sub_sub_ctx + args = sub_ctx.args + + ctx = sub_ctx + args = [*sub_ctx._protected_args, *sub_ctx.args] + else: + break + + return ctx + + +def _resolve_incomplete( + ctx: Context, args: list[str], incomplete: str +) -> tuple[Command | Parameter, str]: + """Find the Click object that will handle the completion of the + incomplete value. Return the object and the incomplete value. + + :param ctx: Invocation context for the command represented by + the parsed complete args. + :param args: List of complete args before the incomplete value. + :param incomplete: Value being completed. May be empty. + """ + # Different shells treat an "=" between a long option name and + # value differently. Might keep the value joined, return the "=" + # as a separate item, or return the split name and value. Always + # split and discard the "=" to make completion easier. + if incomplete == "=": + incomplete = "" + elif "=" in incomplete and _start_of_option(ctx, incomplete): + name, _, incomplete = incomplete.partition("=") + args.append(name) + + # The "--" marker tells Click to stop treating values as options + # even if they start with the option character. If it hasn't been + # given and the incomplete arg looks like an option, the current + # command will provide option name completions. + if "--" not in args and _start_of_option(ctx, incomplete): + return ctx.command, incomplete + + params = ctx.command.get_params(ctx) + + # If the last complete arg is an option name with an incomplete + # value, the option will provide value completions. + for param in params: + if _is_incomplete_option(ctx, args, param): + return param, incomplete + + # It's not an option name or value. The first argument without a + # parsed value will provide value completions. + for param in params: + if _is_incomplete_argument(ctx, param): + return param, incomplete + + # There were no unparsed arguments, the command may be a group that + # will provide command name completions. + return ctx.command, incomplete diff --git a/backend/venv/Lib/site-packages/click/termui.py b/backend/venv/Lib/site-packages/click/termui.py new file mode 100644 index 0000000..dcbb222 --- /dev/null +++ b/backend/venv/Lib/site-packages/click/termui.py @@ -0,0 +1,877 @@ +from __future__ import annotations + +import collections.abc as cabc +import inspect +import io +import itertools +import sys +import typing as t +from contextlib import AbstractContextManager +from gettext import gettext as _ + +from ._compat import isatty +from ._compat import strip_ansi +from .exceptions import Abort +from .exceptions import UsageError +from .globals import resolve_color_default +from .types import Choice +from .types import convert_type +from .types import ParamType +from .utils import echo +from .utils import LazyFile + +if t.TYPE_CHECKING: + from ._termui_impl import ProgressBar + +V = t.TypeVar("V") + +# The prompt functions to use. The doc tools currently override these +# functions to customize how they work. +visible_prompt_func: t.Callable[[str], str] = input + +_ansi_colors = { + "black": 30, + "red": 31, + "green": 32, + "yellow": 33, + "blue": 34, + "magenta": 35, + "cyan": 36, + "white": 37, + "reset": 39, + "bright_black": 90, + "bright_red": 91, + "bright_green": 92, + "bright_yellow": 93, + "bright_blue": 94, + "bright_magenta": 95, + "bright_cyan": 96, + "bright_white": 97, +} +_ansi_reset_all = "\033[0m" + + +def hidden_prompt_func(prompt: str) -> str: + import getpass + + return getpass.getpass(prompt) + + +def _build_prompt( + text: str, + suffix: str, + show_default: bool = False, + default: t.Any | None = None, + show_choices: bool = True, + type: ParamType | None = None, +) -> str: + prompt = text + if type is not None and show_choices and isinstance(type, Choice): + prompt += f" ({', '.join(map(str, type.choices))})" + if default is not None and show_default: + prompt = f"{prompt} [{_format_default(default)}]" + return f"{prompt}{suffix}" + + +def _format_default(default: t.Any) -> t.Any: + if isinstance(default, (io.IOBase, LazyFile)) and hasattr(default, "name"): + return default.name + + return default + + +def prompt( + text: str, + default: t.Any | None = None, + hide_input: bool = False, + confirmation_prompt: bool | str = False, + type: ParamType | t.Any | None = None, + value_proc: t.Callable[[str], t.Any] | None = None, + prompt_suffix: str = ": ", + show_default: bool = True, + err: bool = False, + show_choices: bool = True, +) -> t.Any: + """Prompts a user for input. This is a convenience function that can + be used to prompt a user for input later. + + If the user aborts the input by sending an interrupt signal, this + function will catch it and raise a :exc:`Abort` exception. + + :param text: the text to show for the prompt. + :param default: the default value to use if no input happens. If this + is not given it will prompt until it's aborted. + :param hide_input: if this is set to true then the input value will + be hidden. + :param confirmation_prompt: Prompt a second time to confirm the + value. Can be set to a string instead of ``True`` to customize + the message. + :param type: the type to use to check the value against. + :param value_proc: if this parameter is provided it's a function that + is invoked instead of the type conversion to + convert a value. + :param prompt_suffix: a suffix that should be added to the prompt. + :param show_default: shows or hides the default value in the prompt. + :param err: if set to true the file defaults to ``stderr`` instead of + ``stdout``, the same as with echo. + :param show_choices: Show or hide choices if the passed type is a Choice. + For example if type is a Choice of either day or week, + show_choices is true and text is "Group by" then the + prompt will be "Group by (day, week): ". + + .. versionadded:: 8.0 + ``confirmation_prompt`` can be a custom string. + + .. versionadded:: 7.0 + Added the ``show_choices`` parameter. + + .. versionadded:: 6.0 + Added unicode support for cmd.exe on Windows. + + .. versionadded:: 4.0 + Added the `err` parameter. + + """ + + def prompt_func(text: str) -> str: + f = hidden_prompt_func if hide_input else visible_prompt_func + try: + # Write the prompt separately so that we get nice + # coloring through colorama on Windows + echo(text.rstrip(" "), nl=False, err=err) + # Echo a space to stdout to work around an issue where + # readline causes backspace to clear the whole line. + return f(" ") + except (KeyboardInterrupt, EOFError): + # getpass doesn't print a newline if the user aborts input with ^C. + # Allegedly this behavior is inherited from getpass(3). + # A doc bug has been filed at https://bugs.python.org/issue24711 + if hide_input: + echo(None, err=err) + raise Abort() from None + + if value_proc is None: + value_proc = convert_type(type, default) + + prompt = _build_prompt( + text, prompt_suffix, show_default, default, show_choices, type + ) + + if confirmation_prompt: + if confirmation_prompt is True: + confirmation_prompt = _("Repeat for confirmation") + + confirmation_prompt = _build_prompt(confirmation_prompt, prompt_suffix) + + while True: + while True: + value = prompt_func(prompt) + if value: + break + elif default is not None: + value = default + break + try: + result = value_proc(value) + except UsageError as e: + if hide_input: + echo(_("Error: The value you entered was invalid."), err=err) + else: + echo(_("Error: {e.message}").format(e=e), err=err) + continue + if not confirmation_prompt: + return result + while True: + value2 = prompt_func(confirmation_prompt) + is_empty = not value and not value2 + if value2 or is_empty: + break + if value == value2: + return result + echo(_("Error: The two entered values do not match."), err=err) + + +def confirm( + text: str, + default: bool | None = False, + abort: bool = False, + prompt_suffix: str = ": ", + show_default: bool = True, + err: bool = False, +) -> bool: + """Prompts for confirmation (yes/no question). + + If the user aborts the input by sending a interrupt signal this + function will catch it and raise a :exc:`Abort` exception. + + :param text: the question to ask. + :param default: The default value to use when no input is given. If + ``None``, repeat until input is given. + :param abort: if this is set to `True` a negative answer aborts the + exception by raising :exc:`Abort`. + :param prompt_suffix: a suffix that should be added to the prompt. + :param show_default: shows or hides the default value in the prompt. + :param err: if set to true the file defaults to ``stderr`` instead of + ``stdout``, the same as with echo. + + .. versionchanged:: 8.0 + Repeat until input is given if ``default`` is ``None``. + + .. versionadded:: 4.0 + Added the ``err`` parameter. + """ + prompt = _build_prompt( + text, + prompt_suffix, + show_default, + "y/n" if default is None else ("Y/n" if default else "y/N"), + ) + + while True: + try: + # Write the prompt separately so that we get nice + # coloring through colorama on Windows + echo(prompt.rstrip(" "), nl=False, err=err) + # Echo a space to stdout to work around an issue where + # readline causes backspace to clear the whole line. + value = visible_prompt_func(" ").lower().strip() + except (KeyboardInterrupt, EOFError): + raise Abort() from None + if value in ("y", "yes"): + rv = True + elif value in ("n", "no"): + rv = False + elif default is not None and value == "": + rv = default + else: + echo(_("Error: invalid input"), err=err) + continue + break + if abort and not rv: + raise Abort() + return rv + + +def echo_via_pager( + text_or_generator: cabc.Iterable[str] | t.Callable[[], cabc.Iterable[str]] | str, + color: bool | None = None, +) -> None: + """This function takes a text and shows it via an environment specific + pager on stdout. + + .. versionchanged:: 3.0 + Added the `color` flag. + + :param text_or_generator: the text to page, or alternatively, a + generator emitting the text to page. + :param color: controls if the pager supports ANSI colors or not. The + default is autodetection. + """ + color = resolve_color_default(color) + + if inspect.isgeneratorfunction(text_or_generator): + i = t.cast("t.Callable[[], cabc.Iterable[str]]", text_or_generator)() + elif isinstance(text_or_generator, str): + i = [text_or_generator] + else: + i = iter(t.cast("cabc.Iterable[str]", text_or_generator)) + + # convert every element of i to a text type if necessary + text_generator = (el if isinstance(el, str) else str(el) for el in i) + + from ._termui_impl import pager + + return pager(itertools.chain(text_generator, "\n"), color) + + +@t.overload +def progressbar( + *, + length: int, + label: str | None = None, + hidden: bool = False, + show_eta: bool = True, + show_percent: bool | None = None, + show_pos: bool = False, + fill_char: str = "#", + empty_char: str = "-", + bar_template: str = "%(label)s [%(bar)s] %(info)s", + info_sep: str = " ", + width: int = 36, + file: t.TextIO | None = None, + color: bool | None = None, + update_min_steps: int = 1, +) -> ProgressBar[int]: ... + + +@t.overload +def progressbar( + iterable: cabc.Iterable[V] | None = None, + length: int | None = None, + label: str | None = None, + hidden: bool = False, + show_eta: bool = True, + show_percent: bool | None = None, + show_pos: bool = False, + item_show_func: t.Callable[[V | None], str | None] | None = None, + fill_char: str = "#", + empty_char: str = "-", + bar_template: str = "%(label)s [%(bar)s] %(info)s", + info_sep: str = " ", + width: int = 36, + file: t.TextIO | None = None, + color: bool | None = None, + update_min_steps: int = 1, +) -> ProgressBar[V]: ... + + +def progressbar( + iterable: cabc.Iterable[V] | None = None, + length: int | None = None, + label: str | None = None, + hidden: bool = False, + show_eta: bool = True, + show_percent: bool | None = None, + show_pos: bool = False, + item_show_func: t.Callable[[V | None], str | None] | None = None, + fill_char: str = "#", + empty_char: str = "-", + bar_template: str = "%(label)s [%(bar)s] %(info)s", + info_sep: str = " ", + width: int = 36, + file: t.TextIO | None = None, + color: bool | None = None, + update_min_steps: int = 1, +) -> ProgressBar[V]: + """This function creates an iterable context manager that can be used + to iterate over something while showing a progress bar. It will + either iterate over the `iterable` or `length` items (that are counted + up). While iteration happens, this function will print a rendered + progress bar to the given `file` (defaults to stdout) and will attempt + to calculate remaining time and more. By default, this progress bar + will not be rendered if the file is not a terminal. + + The context manager creates the progress bar. When the context + manager is entered the progress bar is already created. With every + iteration over the progress bar, the iterable passed to the bar is + advanced and the bar is updated. When the context manager exits, + a newline is printed and the progress bar is finalized on screen. + + Note: The progress bar is currently designed for use cases where the + total progress can be expected to take at least several seconds. + Because of this, the ProgressBar class object won't display + progress that is considered too fast, and progress where the time + between steps is less than a second. + + No printing must happen or the progress bar will be unintentionally + destroyed. + + Example usage:: + + with progressbar(items) as bar: + for item in bar: + do_something_with(item) + + Alternatively, if no iterable is specified, one can manually update the + progress bar through the `update()` method instead of directly + iterating over the progress bar. The update method accepts the number + of steps to increment the bar with:: + + with progressbar(length=chunks.total_bytes) as bar: + for chunk in chunks: + process_chunk(chunk) + bar.update(chunks.bytes) + + The ``update()`` method also takes an optional value specifying the + ``current_item`` at the new position. This is useful when used + together with ``item_show_func`` to customize the output for each + manual step:: + + with click.progressbar( + length=total_size, + label='Unzipping archive', + item_show_func=lambda a: a.filename + ) as bar: + for archive in zip_file: + archive.extract() + bar.update(archive.size, archive) + + :param iterable: an iterable to iterate over. If not provided the length + is required. + :param length: the number of items to iterate over. By default the + progressbar will attempt to ask the iterator about its + length, which might or might not work. If an iterable is + also provided this parameter can be used to override the + length. If an iterable is not provided the progress bar + will iterate over a range of that length. + :param label: the label to show next to the progress bar. + :param hidden: hide the progressbar. Defaults to ``False``. When no tty is + detected, it will only print the progressbar label. Setting this to + ``False`` also disables that. + :param show_eta: enables or disables the estimated time display. This is + automatically disabled if the length cannot be + determined. + :param show_percent: enables or disables the percentage display. The + default is `True` if the iterable has a length or + `False` if not. + :param show_pos: enables or disables the absolute position display. The + default is `False`. + :param item_show_func: A function called with the current item which + can return a string to show next to the progress bar. If the + function returns ``None`` nothing is shown. The current item can + be ``None``, such as when entering and exiting the bar. + :param fill_char: the character to use to show the filled part of the + progress bar. + :param empty_char: the character to use to show the non-filled part of + the progress bar. + :param bar_template: the format string to use as template for the bar. + The parameters in it are ``label`` for the label, + ``bar`` for the progress bar and ``info`` for the + info section. + :param info_sep: the separator between multiple info items (eta etc.) + :param width: the width of the progress bar in characters, 0 means full + terminal width + :param file: The file to write to. If this is not a terminal then + only the label is printed. + :param color: controls if the terminal supports ANSI colors or not. The + default is autodetection. This is only needed if ANSI + codes are included anywhere in the progress bar output + which is not the case by default. + :param update_min_steps: Render only when this many updates have + completed. This allows tuning for very fast iterators. + + .. versionadded:: 8.2 + The ``hidden`` argument. + + .. versionchanged:: 8.0 + Output is shown even if execution time is less than 0.5 seconds. + + .. versionchanged:: 8.0 + ``item_show_func`` shows the current item, not the previous one. + + .. versionchanged:: 8.0 + Labels are echoed if the output is not a TTY. Reverts a change + in 7.0 that removed all output. + + .. versionadded:: 8.0 + The ``update_min_steps`` parameter. + + .. versionadded:: 4.0 + The ``color`` parameter and ``update`` method. + + .. versionadded:: 2.0 + """ + from ._termui_impl import ProgressBar + + color = resolve_color_default(color) + return ProgressBar( + iterable=iterable, + length=length, + hidden=hidden, + show_eta=show_eta, + show_percent=show_percent, + show_pos=show_pos, + item_show_func=item_show_func, + fill_char=fill_char, + empty_char=empty_char, + bar_template=bar_template, + info_sep=info_sep, + file=file, + label=label, + width=width, + color=color, + update_min_steps=update_min_steps, + ) + + +def clear() -> None: + """Clears the terminal screen. This will have the effect of clearing + the whole visible space of the terminal and moving the cursor to the + top left. This does not do anything if not connected to a terminal. + + .. versionadded:: 2.0 + """ + if not isatty(sys.stdout): + return + + # ANSI escape \033[2J clears the screen, \033[1;1H moves the cursor + echo("\033[2J\033[1;1H", nl=False) + + +def _interpret_color(color: int | tuple[int, int, int] | str, offset: int = 0) -> str: + if isinstance(color, int): + return f"{38 + offset};5;{color:d}" + + if isinstance(color, (tuple, list)): + r, g, b = color + return f"{38 + offset};2;{r:d};{g:d};{b:d}" + + return str(_ansi_colors[color] + offset) + + +def style( + text: t.Any, + fg: int | tuple[int, int, int] | str | None = None, + bg: int | tuple[int, int, int] | str | None = None, + bold: bool | None = None, + dim: bool | None = None, + underline: bool | None = None, + overline: bool | None = None, + italic: bool | None = None, + blink: bool | None = None, + reverse: bool | None = None, + strikethrough: bool | None = None, + reset: bool = True, +) -> str: + """Styles a text with ANSI styles and returns the new string. By + default the styling is self contained which means that at the end + of the string a reset code is issued. This can be prevented by + passing ``reset=False``. + + Examples:: + + click.echo(click.style('Hello World!', fg='green')) + click.echo(click.style('ATTENTION!', blink=True)) + click.echo(click.style('Some things', reverse=True, fg='cyan')) + click.echo(click.style('More colors', fg=(255, 12, 128), bg=117)) + + Supported color names: + + * ``black`` (might be a gray) + * ``red`` + * ``green`` + * ``yellow`` (might be an orange) + * ``blue`` + * ``magenta`` + * ``cyan`` + * ``white`` (might be light gray) + * ``bright_black`` + * ``bright_red`` + * ``bright_green`` + * ``bright_yellow`` + * ``bright_blue`` + * ``bright_magenta`` + * ``bright_cyan`` + * ``bright_white`` + * ``reset`` (reset the color code only) + + If the terminal supports it, color may also be specified as: + + - An integer in the interval [0, 255]. The terminal must support + 8-bit/256-color mode. + - An RGB tuple of three integers in [0, 255]. The terminal must + support 24-bit/true-color mode. + + See https://en.wikipedia.org/wiki/ANSI_color and + https://gist.github.com/XVilka/8346728 for more information. + + :param text: the string to style with ansi codes. + :param fg: if provided this will become the foreground color. + :param bg: if provided this will become the background color. + :param bold: if provided this will enable or disable bold mode. + :param dim: if provided this will enable or disable dim mode. This is + badly supported. + :param underline: if provided this will enable or disable underline. + :param overline: if provided this will enable or disable overline. + :param italic: if provided this will enable or disable italic. + :param blink: if provided this will enable or disable blinking. + :param reverse: if provided this will enable or disable inverse + rendering (foreground becomes background and the + other way round). + :param strikethrough: if provided this will enable or disable + striking through text. + :param reset: by default a reset-all code is added at the end of the + string which means that styles do not carry over. This + can be disabled to compose styles. + + .. versionchanged:: 8.0 + A non-string ``message`` is converted to a string. + + .. versionchanged:: 8.0 + Added support for 256 and RGB color codes. + + .. versionchanged:: 8.0 + Added the ``strikethrough``, ``italic``, and ``overline`` + parameters. + + .. versionchanged:: 7.0 + Added support for bright colors. + + .. versionadded:: 2.0 + """ + if not isinstance(text, str): + text = str(text) + + bits = [] + + if fg: + try: + bits.append(f"\033[{_interpret_color(fg)}m") + except KeyError: + raise TypeError(f"Unknown color {fg!r}") from None + + if bg: + try: + bits.append(f"\033[{_interpret_color(bg, 10)}m") + except KeyError: + raise TypeError(f"Unknown color {bg!r}") from None + + if bold is not None: + bits.append(f"\033[{1 if bold else 22}m") + if dim is not None: + bits.append(f"\033[{2 if dim else 22}m") + if underline is not None: + bits.append(f"\033[{4 if underline else 24}m") + if overline is not None: + bits.append(f"\033[{53 if overline else 55}m") + if italic is not None: + bits.append(f"\033[{3 if italic else 23}m") + if blink is not None: + bits.append(f"\033[{5 if blink else 25}m") + if reverse is not None: + bits.append(f"\033[{7 if reverse else 27}m") + if strikethrough is not None: + bits.append(f"\033[{9 if strikethrough else 29}m") + bits.append(text) + if reset: + bits.append(_ansi_reset_all) + return "".join(bits) + + +def unstyle(text: str) -> str: + """Removes ANSI styling information from a string. Usually it's not + necessary to use this function as Click's echo function will + automatically remove styling if necessary. + + .. versionadded:: 2.0 + + :param text: the text to remove style information from. + """ + return strip_ansi(text) + + +def secho( + message: t.Any | None = None, + file: t.IO[t.AnyStr] | None = None, + nl: bool = True, + err: bool = False, + color: bool | None = None, + **styles: t.Any, +) -> None: + """This function combines :func:`echo` and :func:`style` into one + call. As such the following two calls are the same:: + + click.secho('Hello World!', fg='green') + click.echo(click.style('Hello World!', fg='green')) + + All keyword arguments are forwarded to the underlying functions + depending on which one they go with. + + Non-string types will be converted to :class:`str`. However, + :class:`bytes` are passed directly to :meth:`echo` without applying + style. If you want to style bytes that represent text, call + :meth:`bytes.decode` first. + + .. versionchanged:: 8.0 + A non-string ``message`` is converted to a string. Bytes are + passed through without style applied. + + .. versionadded:: 2.0 + """ + if message is not None and not isinstance(message, (bytes, bytearray)): + message = style(message, **styles) + + return echo(message, file=file, nl=nl, err=err, color=color) + + +@t.overload +def edit( + text: bytes | bytearray, + editor: str | None = None, + env: cabc.Mapping[str, str] | None = None, + require_save: bool = False, + extension: str = ".txt", +) -> bytes | None: ... + + +@t.overload +def edit( + text: str, + editor: str | None = None, + env: cabc.Mapping[str, str] | None = None, + require_save: bool = True, + extension: str = ".txt", +) -> str | None: ... + + +@t.overload +def edit( + text: None = None, + editor: str | None = None, + env: cabc.Mapping[str, str] | None = None, + require_save: bool = True, + extension: str = ".txt", + filename: str | cabc.Iterable[str] | None = None, +) -> None: ... + + +def edit( + text: str | bytes | bytearray | None = None, + editor: str | None = None, + env: cabc.Mapping[str, str] | None = None, + require_save: bool = True, + extension: str = ".txt", + filename: str | cabc.Iterable[str] | None = None, +) -> str | bytes | bytearray | None: + r"""Edits the given text in the defined editor. If an editor is given + (should be the full path to the executable but the regular operating + system search path is used for finding the executable) it overrides + the detected editor. Optionally, some environment variables can be + used. If the editor is closed without changes, `None` is returned. In + case a file is edited directly the return value is always `None` and + `require_save` and `extension` are ignored. + + If the editor cannot be opened a :exc:`UsageError` is raised. + + Note for Windows: to simplify cross-platform usage, the newlines are + automatically converted from POSIX to Windows and vice versa. As such, + the message here will have ``\n`` as newline markers. + + :param text: the text to edit. + :param editor: optionally the editor to use. Defaults to automatic + detection. + :param env: environment variables to forward to the editor. + :param require_save: if this is true, then not saving in the editor + will make the return value become `None`. + :param extension: the extension to tell the editor about. This defaults + to `.txt` but changing this might change syntax + highlighting. + :param filename: if provided it will edit this file instead of the + provided text contents. It will not use a temporary + file as an indirection in that case. If the editor supports + editing multiple files at once, a sequence of files may be + passed as well. Invoke `click.file` once per file instead + if multiple files cannot be managed at once or editing the + files serially is desired. + + .. versionchanged:: 8.2.0 + ``filename`` now accepts any ``Iterable[str]`` in addition to a ``str`` + if the ``editor`` supports editing multiple files at once. + + """ + from ._termui_impl import Editor + + ed = Editor(editor=editor, env=env, require_save=require_save, extension=extension) + + if filename is None: + return ed.edit(text) + + if isinstance(filename, str): + filename = (filename,) + + ed.edit_files(filenames=filename) + return None + + +def launch(url: str, wait: bool = False, locate: bool = False) -> int: + """This function launches the given URL (or filename) in the default + viewer application for this file type. If this is an executable, it + might launch the executable in a new session. The return value is + the exit code of the launched application. Usually, ``0`` indicates + success. + + Examples:: + + click.launch('https://click.palletsprojects.com/') + click.launch('/my/downloaded/file', locate=True) + + .. versionadded:: 2.0 + + :param url: URL or filename of the thing to launch. + :param wait: Wait for the program to exit before returning. This + only works if the launched program blocks. In particular, + ``xdg-open`` on Linux does not block. + :param locate: if this is set to `True` then instead of launching the + application associated with the URL it will attempt to + launch a file manager with the file located. This + might have weird effects if the URL does not point to + the filesystem. + """ + from ._termui_impl import open_url + + return open_url(url, wait=wait, locate=locate) + + +# If this is provided, getchar() calls into this instead. This is used +# for unittesting purposes. +_getchar: t.Callable[[bool], str] | None = None + + +def getchar(echo: bool = False) -> str: + """Fetches a single character from the terminal and returns it. This + will always return a unicode character and under certain rare + circumstances this might return more than one character. The + situations which more than one character is returned is when for + whatever reason multiple characters end up in the terminal buffer or + standard input was not actually a terminal. + + Note that this will always read from the terminal, even if something + is piped into the standard input. + + Note for Windows: in rare cases when typing non-ASCII characters, this + function might wait for a second character and then return both at once. + This is because certain Unicode characters look like special-key markers. + + .. versionadded:: 2.0 + + :param echo: if set to `True`, the character read will also show up on + the terminal. The default is to not show it. + """ + global _getchar + + if _getchar is None: + from ._termui_impl import getchar as f + + _getchar = f + + return _getchar(echo) + + +def raw_terminal() -> AbstractContextManager[int]: + from ._termui_impl import raw_terminal as f + + return f() + + +def pause(info: str | None = None, err: bool = False) -> None: + """This command stops execution and waits for the user to press any + key to continue. This is similar to the Windows batch "pause" + command. If the program is not run through a terminal, this command + will instead do nothing. + + .. versionadded:: 2.0 + + .. versionadded:: 4.0 + Added the `err` parameter. + + :param info: The message to print before pausing. Defaults to + ``"Press any key to continue..."``. + :param err: if set to message goes to ``stderr`` instead of + ``stdout``, the same as with echo. + """ + if not isatty(sys.stdin) or not isatty(sys.stdout): + return + + if info is None: + info = _("Press any key to continue...") + + try: + if info: + echo(info, nl=False, err=err) + try: + getchar() + except (KeyboardInterrupt, EOFError): + pass + finally: + if info: + echo(err=err) diff --git a/backend/venv/Lib/site-packages/click/testing.py b/backend/venv/Lib/site-packages/click/testing.py new file mode 100644 index 0000000..f6f60b8 --- /dev/null +++ b/backend/venv/Lib/site-packages/click/testing.py @@ -0,0 +1,577 @@ +from __future__ import annotations + +import collections.abc as cabc +import contextlib +import io +import os +import shlex +import sys +import tempfile +import typing as t +from types import TracebackType + +from . import _compat +from . import formatting +from . import termui +from . import utils +from ._compat import _find_binary_reader + +if t.TYPE_CHECKING: + from _typeshed import ReadableBuffer + + from .core import Command + + +class EchoingStdin: + def __init__(self, input: t.BinaryIO, output: t.BinaryIO) -> None: + self._input = input + self._output = output + self._paused = False + + def __getattr__(self, x: str) -> t.Any: + return getattr(self._input, x) + + def _echo(self, rv: bytes) -> bytes: + if not self._paused: + self._output.write(rv) + + return rv + + def read(self, n: int = -1) -> bytes: + return self._echo(self._input.read(n)) + + def read1(self, n: int = -1) -> bytes: + return self._echo(self._input.read1(n)) # type: ignore + + def readline(self, n: int = -1) -> bytes: + return self._echo(self._input.readline(n)) + + def readlines(self) -> list[bytes]: + return [self._echo(x) for x in self._input.readlines()] + + def __iter__(self) -> cabc.Iterator[bytes]: + return iter(self._echo(x) for x in self._input) + + def __repr__(self) -> str: + return repr(self._input) + + +@contextlib.contextmanager +def _pause_echo(stream: EchoingStdin | None) -> cabc.Iterator[None]: + if stream is None: + yield + else: + stream._paused = True + yield + stream._paused = False + + +class BytesIOCopy(io.BytesIO): + """Patch ``io.BytesIO`` to let the written stream be copied to another. + + .. versionadded:: 8.2 + """ + + def __init__(self, copy_to: io.BytesIO) -> None: + super().__init__() + self.copy_to = copy_to + + def flush(self) -> None: + super().flush() + self.copy_to.flush() + + def write(self, b: ReadableBuffer) -> int: + self.copy_to.write(b) + return super().write(b) + + +class StreamMixer: + """Mixes `` and `` streams. + + The result is available in the ``output`` attribute. + + .. versionadded:: 8.2 + """ + + def __init__(self) -> None: + self.output: io.BytesIO = io.BytesIO() + self.stdout: io.BytesIO = BytesIOCopy(copy_to=self.output) + self.stderr: io.BytesIO = BytesIOCopy(copy_to=self.output) + + def __del__(self) -> None: + """ + Guarantee that embedded file-like objects are closed in a + predictable order, protecting against races between + self.output being closed and other streams being flushed on close + + .. versionadded:: 8.2.2 + """ + self.stderr.close() + self.stdout.close() + self.output.close() + + +class _NamedTextIOWrapper(io.TextIOWrapper): + def __init__( + self, buffer: t.BinaryIO, name: str, mode: str, **kwargs: t.Any + ) -> None: + super().__init__(buffer, **kwargs) + self._name = name + self._mode = mode + + @property + def name(self) -> str: + return self._name + + @property + def mode(self) -> str: + return self._mode + + +def make_input_stream( + input: str | bytes | t.IO[t.Any] | None, charset: str +) -> t.BinaryIO: + # Is already an input stream. + if hasattr(input, "read"): + rv = _find_binary_reader(t.cast("t.IO[t.Any]", input)) + + if rv is not None: + return rv + + raise TypeError("Could not find binary reader for input stream.") + + if input is None: + input = b"" + elif isinstance(input, str): + input = input.encode(charset) + + return io.BytesIO(input) + + +class Result: + """Holds the captured result of an invoked CLI script. + + :param runner: The runner that created the result + :param stdout_bytes: The standard output as bytes. + :param stderr_bytes: The standard error as bytes. + :param output_bytes: A mix of ``stdout_bytes`` and ``stderr_bytes``, as the + user would see it in its terminal. + :param return_value: The value returned from the invoked command. + :param exit_code: The exit code as integer. + :param exception: The exception that happened if one did. + :param exc_info: Exception information (exception type, exception instance, + traceback type). + + .. versionchanged:: 8.2 + ``stderr_bytes`` no longer optional, ``output_bytes`` introduced and + ``mix_stderr`` has been removed. + + .. versionadded:: 8.0 + Added ``return_value``. + """ + + def __init__( + self, + runner: CliRunner, + stdout_bytes: bytes, + stderr_bytes: bytes, + output_bytes: bytes, + return_value: t.Any, + exit_code: int, + exception: BaseException | None, + exc_info: tuple[type[BaseException], BaseException, TracebackType] + | None = None, + ): + self.runner = runner + self.stdout_bytes = stdout_bytes + self.stderr_bytes = stderr_bytes + self.output_bytes = output_bytes + self.return_value = return_value + self.exit_code = exit_code + self.exception = exception + self.exc_info = exc_info + + @property + def output(self) -> str: + """The terminal output as unicode string, as the user would see it. + + .. versionchanged:: 8.2 + No longer a proxy for ``self.stdout``. Now has its own independent stream + that is mixing `` and ``, in the order they were written. + """ + return self.output_bytes.decode(self.runner.charset, "replace").replace( + "\r\n", "\n" + ) + + @property + def stdout(self) -> str: + """The standard output as unicode string.""" + return self.stdout_bytes.decode(self.runner.charset, "replace").replace( + "\r\n", "\n" + ) + + @property + def stderr(self) -> str: + """The standard error as unicode string. + + .. versionchanged:: 8.2 + No longer raise an exception, always returns the `` string. + """ + return self.stderr_bytes.decode(self.runner.charset, "replace").replace( + "\r\n", "\n" + ) + + def __repr__(self) -> str: + exc_str = repr(self.exception) if self.exception else "okay" + return f"<{type(self).__name__} {exc_str}>" + + +class CliRunner: + """The CLI runner provides functionality to invoke a Click command line + script for unittesting purposes in a isolated environment. This only + works in single-threaded systems without any concurrency as it changes the + global interpreter state. + + :param charset: the character set for the input and output data. + :param env: a dictionary with environment variables for overriding. + :param echo_stdin: if this is set to `True`, then reading from `` writes + to ``. This is useful for showing examples in + some circumstances. Note that regular prompts + will automatically echo the input. + :param catch_exceptions: Whether to catch any exceptions other than + ``SystemExit`` when running :meth:`~CliRunner.invoke`. + + .. versionchanged:: 8.2 + Added the ``catch_exceptions`` parameter. + + .. versionchanged:: 8.2 + ``mix_stderr`` parameter has been removed. + """ + + def __init__( + self, + charset: str = "utf-8", + env: cabc.Mapping[str, str | None] | None = None, + echo_stdin: bool = False, + catch_exceptions: bool = True, + ) -> None: + self.charset = charset + self.env: cabc.Mapping[str, str | None] = env or {} + self.echo_stdin = echo_stdin + self.catch_exceptions = catch_exceptions + + def get_default_prog_name(self, cli: Command) -> str: + """Given a command object it will return the default program name + for it. The default is the `name` attribute or ``"root"`` if not + set. + """ + return cli.name or "root" + + def make_env( + self, overrides: cabc.Mapping[str, str | None] | None = None + ) -> cabc.Mapping[str, str | None]: + """Returns the environment overrides for invoking a script.""" + rv = dict(self.env) + if overrides: + rv.update(overrides) + return rv + + @contextlib.contextmanager + def isolation( + self, + input: str | bytes | t.IO[t.Any] | None = None, + env: cabc.Mapping[str, str | None] | None = None, + color: bool = False, + ) -> cabc.Iterator[tuple[io.BytesIO, io.BytesIO, io.BytesIO]]: + """A context manager that sets up the isolation for invoking of a + command line tool. This sets up `` with the given input data + and `os.environ` with the overrides from the given dictionary. + This also rebinds some internals in Click to be mocked (like the + prompt functionality). + + This is automatically done in the :meth:`invoke` method. + + :param input: the input stream to put into `sys.stdin`. + :param env: the environment overrides as dictionary. + :param color: whether the output should contain color codes. The + application can still override this explicitly. + + .. versionadded:: 8.2 + An additional output stream is returned, which is a mix of + `` and `` streams. + + .. versionchanged:: 8.2 + Always returns the `` stream. + + .. versionchanged:: 8.0 + `` is opened with ``errors="backslashreplace"`` + instead of the default ``"strict"``. + + .. versionchanged:: 4.0 + Added the ``color`` parameter. + """ + bytes_input = make_input_stream(input, self.charset) + echo_input = None + + old_stdin = sys.stdin + old_stdout = sys.stdout + old_stderr = sys.stderr + old_forced_width = formatting.FORCED_WIDTH + formatting.FORCED_WIDTH = 80 + + env = self.make_env(env) + + stream_mixer = StreamMixer() + + if self.echo_stdin: + bytes_input = echo_input = t.cast( + t.BinaryIO, EchoingStdin(bytes_input, stream_mixer.stdout) + ) + + sys.stdin = text_input = _NamedTextIOWrapper( + bytes_input, encoding=self.charset, name="", mode="r" + ) + + if self.echo_stdin: + # Force unbuffered reads, otherwise TextIOWrapper reads a + # large chunk which is echoed early. + text_input._CHUNK_SIZE = 1 # type: ignore + + sys.stdout = _NamedTextIOWrapper( + stream_mixer.stdout, encoding=self.charset, name="", mode="w" + ) + + sys.stderr = _NamedTextIOWrapper( + stream_mixer.stderr, + encoding=self.charset, + name="", + mode="w", + errors="backslashreplace", + ) + + @_pause_echo(echo_input) # type: ignore + def visible_input(prompt: str | None = None) -> str: + sys.stdout.write(prompt or "") + try: + val = next(text_input).rstrip("\r\n") + except StopIteration as e: + raise EOFError() from e + sys.stdout.write(f"{val}\n") + sys.stdout.flush() + return val + + @_pause_echo(echo_input) # type: ignore + def hidden_input(prompt: str | None = None) -> str: + sys.stdout.write(f"{prompt or ''}\n") + sys.stdout.flush() + try: + return next(text_input).rstrip("\r\n") + except StopIteration as e: + raise EOFError() from e + + @_pause_echo(echo_input) # type: ignore + def _getchar(echo: bool) -> str: + char = sys.stdin.read(1) + + if echo: + sys.stdout.write(char) + + sys.stdout.flush() + return char + + default_color = color + + def should_strip_ansi( + stream: t.IO[t.Any] | None = None, color: bool | None = None + ) -> bool: + if color is None: + return not default_color + return not color + + old_visible_prompt_func = termui.visible_prompt_func + old_hidden_prompt_func = termui.hidden_prompt_func + old__getchar_func = termui._getchar + old_should_strip_ansi = utils.should_strip_ansi # type: ignore + old__compat_should_strip_ansi = _compat.should_strip_ansi + termui.visible_prompt_func = visible_input + termui.hidden_prompt_func = hidden_input + termui._getchar = _getchar + utils.should_strip_ansi = should_strip_ansi # type: ignore + _compat.should_strip_ansi = should_strip_ansi + + old_env = {} + try: + for key, value in env.items(): + old_env[key] = os.environ.get(key) + if value is None: + try: + del os.environ[key] + except Exception: + pass + else: + os.environ[key] = value + yield (stream_mixer.stdout, stream_mixer.stderr, stream_mixer.output) + finally: + for key, value in old_env.items(): + if value is None: + try: + del os.environ[key] + except Exception: + pass + else: + os.environ[key] = value + sys.stdout = old_stdout + sys.stderr = old_stderr + sys.stdin = old_stdin + termui.visible_prompt_func = old_visible_prompt_func + termui.hidden_prompt_func = old_hidden_prompt_func + termui._getchar = old__getchar_func + utils.should_strip_ansi = old_should_strip_ansi # type: ignore + _compat.should_strip_ansi = old__compat_should_strip_ansi + formatting.FORCED_WIDTH = old_forced_width + + def invoke( + self, + cli: Command, + args: str | cabc.Sequence[str] | None = None, + input: str | bytes | t.IO[t.Any] | None = None, + env: cabc.Mapping[str, str | None] | None = None, + catch_exceptions: bool | None = None, + color: bool = False, + **extra: t.Any, + ) -> Result: + """Invokes a command in an isolated environment. The arguments are + forwarded directly to the command line script, the `extra` keyword + arguments are passed to the :meth:`~clickpkg.Command.main` function of + the command. + + This returns a :class:`Result` object. + + :param cli: the command to invoke + :param args: the arguments to invoke. It may be given as an iterable + or a string. When given as string it will be interpreted + as a Unix shell command. More details at + :func:`shlex.split`. + :param input: the input data for `sys.stdin`. + :param env: the environment overrides. + :param catch_exceptions: Whether to catch any other exceptions than + ``SystemExit``. If :data:`None`, the value + from :class:`CliRunner` is used. + :param extra: the keyword arguments to pass to :meth:`main`. + :param color: whether the output should contain color codes. The + application can still override this explicitly. + + .. versionadded:: 8.2 + The result object has the ``output_bytes`` attribute with + the mix of ``stdout_bytes`` and ``stderr_bytes``, as the user would + see it in its terminal. + + .. versionchanged:: 8.2 + The result object always returns the ``stderr_bytes`` stream. + + .. versionchanged:: 8.0 + The result object has the ``return_value`` attribute with + the value returned from the invoked command. + + .. versionchanged:: 4.0 + Added the ``color`` parameter. + + .. versionchanged:: 3.0 + Added the ``catch_exceptions`` parameter. + + .. versionchanged:: 3.0 + The result object has the ``exc_info`` attribute with the + traceback if available. + """ + exc_info = None + if catch_exceptions is None: + catch_exceptions = self.catch_exceptions + + with self.isolation(input=input, env=env, color=color) as outstreams: + return_value = None + exception: BaseException | None = None + exit_code = 0 + + if isinstance(args, str): + args = shlex.split(args) + + try: + prog_name = extra.pop("prog_name") + except KeyError: + prog_name = self.get_default_prog_name(cli) + + try: + return_value = cli.main(args=args or (), prog_name=prog_name, **extra) + except SystemExit as e: + exc_info = sys.exc_info() + e_code = t.cast("int | t.Any | None", e.code) + + if e_code is None: + e_code = 0 + + if e_code != 0: + exception = e + + if not isinstance(e_code, int): + sys.stdout.write(str(e_code)) + sys.stdout.write("\n") + e_code = 1 + + exit_code = e_code + + except Exception as e: + if not catch_exceptions: + raise + exception = e + exit_code = 1 + exc_info = sys.exc_info() + finally: + sys.stdout.flush() + sys.stderr.flush() + stdout = outstreams[0].getvalue() + stderr = outstreams[1].getvalue() + output = outstreams[2].getvalue() + + return Result( + runner=self, + stdout_bytes=stdout, + stderr_bytes=stderr, + output_bytes=output, + return_value=return_value, + exit_code=exit_code, + exception=exception, + exc_info=exc_info, # type: ignore + ) + + @contextlib.contextmanager + def isolated_filesystem( + self, temp_dir: str | os.PathLike[str] | None = None + ) -> cabc.Iterator[str]: + """A context manager that creates a temporary directory and + changes the current working directory to it. This isolates tests + that affect the contents of the CWD to prevent them from + interfering with each other. + + :param temp_dir: Create the temporary directory under this + directory. If given, the created directory is not removed + when exiting. + + .. versionchanged:: 8.0 + Added the ``temp_dir`` parameter. + """ + cwd = os.getcwd() + dt = tempfile.mkdtemp(dir=temp_dir) + os.chdir(dt) + + try: + yield dt + finally: + os.chdir(cwd) + + if temp_dir is None: + import shutil + + try: + shutil.rmtree(dt) + except OSError: + pass diff --git a/backend/venv/Lib/site-packages/click/types.py b/backend/venv/Lib/site-packages/click/types.py new file mode 100644 index 0000000..e71c1c2 --- /dev/null +++ b/backend/venv/Lib/site-packages/click/types.py @@ -0,0 +1,1209 @@ +from __future__ import annotations + +import collections.abc as cabc +import enum +import os +import stat +import sys +import typing as t +from datetime import datetime +from gettext import gettext as _ +from gettext import ngettext + +from ._compat import _get_argv_encoding +from ._compat import open_stream +from .exceptions import BadParameter +from .utils import format_filename +from .utils import LazyFile +from .utils import safecall + +if t.TYPE_CHECKING: + import typing_extensions as te + + from .core import Context + from .core import Parameter + from .shell_completion import CompletionItem + +ParamTypeValue = t.TypeVar("ParamTypeValue") + + +class ParamType: + """Represents the type of a parameter. Validates and converts values + from the command line or Python into the correct type. + + To implement a custom type, subclass and implement at least the + following: + + - The :attr:`name` class attribute must be set. + - Calling an instance of the type with ``None`` must return + ``None``. This is already implemented by default. + - :meth:`convert` must convert string values to the correct type. + - :meth:`convert` must accept values that are already the correct + type. + - It must be able to convert a value if the ``ctx`` and ``param`` + arguments are ``None``. This can occur when converting prompt + input. + """ + + is_composite: t.ClassVar[bool] = False + arity: t.ClassVar[int] = 1 + + #: the descriptive name of this type + name: str + + #: if a list of this type is expected and the value is pulled from a + #: string environment variable, this is what splits it up. `None` + #: means any whitespace. For all parameters the general rule is that + #: whitespace splits them up. The exception are paths and files which + #: are split by ``os.path.pathsep`` by default (":" on Unix and ";" on + #: Windows). + envvar_list_splitter: t.ClassVar[str | None] = None + + def to_info_dict(self) -> dict[str, t.Any]: + """Gather information that could be useful for a tool generating + user-facing documentation. + + Use :meth:`click.Context.to_info_dict` to traverse the entire + CLI structure. + + .. versionadded:: 8.0 + """ + # The class name without the "ParamType" suffix. + param_type = type(self).__name__.partition("ParamType")[0] + param_type = param_type.partition("ParameterType")[0] + + # Custom subclasses might not remember to set a name. + if hasattr(self, "name"): + name = self.name + else: + name = param_type + + return {"param_type": param_type, "name": name} + + def __call__( + self, + value: t.Any, + param: Parameter | None = None, + ctx: Context | None = None, + ) -> t.Any: + if value is not None: + return self.convert(value, param, ctx) + + def get_metavar(self, param: Parameter, ctx: Context) -> str | None: + """Returns the metavar default for this param if it provides one.""" + + def get_missing_message(self, param: Parameter, ctx: Context | None) -> str | None: + """Optionally might return extra information about a missing + parameter. + + .. versionadded:: 2.0 + """ + + def convert( + self, value: t.Any, param: Parameter | None, ctx: Context | None + ) -> t.Any: + """Convert the value to the correct type. This is not called if + the value is ``None`` (the missing value). + + This must accept string values from the command line, as well as + values that are already the correct type. It may also convert + other compatible types. + + The ``param`` and ``ctx`` arguments may be ``None`` in certain + situations, such as when converting prompt input. + + If the value cannot be converted, call :meth:`fail` with a + descriptive message. + + :param value: The value to convert. + :param param: The parameter that is using this type to convert + its value. May be ``None``. + :param ctx: The current context that arrived at this value. May + be ``None``. + """ + return value + + def split_envvar_value(self, rv: str) -> cabc.Sequence[str]: + """Given a value from an environment variable this splits it up + into small chunks depending on the defined envvar list splitter. + + If the splitter is set to `None`, which means that whitespace splits, + then leading and trailing whitespace is ignored. Otherwise, leading + and trailing splitters usually lead to empty items being included. + """ + return (rv or "").split(self.envvar_list_splitter) + + def fail( + self, + message: str, + param: Parameter | None = None, + ctx: Context | None = None, + ) -> t.NoReturn: + """Helper method to fail with an invalid value message.""" + raise BadParameter(message, ctx=ctx, param=param) + + def shell_complete( + self, ctx: Context, param: Parameter, incomplete: str + ) -> list[CompletionItem]: + """Return a list of + :class:`~click.shell_completion.CompletionItem` objects for the + incomplete value. Most types do not provide completions, but + some do, and this allows custom types to provide custom + completions as well. + + :param ctx: Invocation context for this command. + :param param: The parameter that is requesting completion. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + return [] + + +class CompositeParamType(ParamType): + is_composite = True + + @property + def arity(self) -> int: # type: ignore + raise NotImplementedError() + + +class FuncParamType(ParamType): + def __init__(self, func: t.Callable[[t.Any], t.Any]) -> None: + self.name: str = func.__name__ + self.func = func + + def to_info_dict(self) -> dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict["func"] = self.func + return info_dict + + def convert( + self, value: t.Any, param: Parameter | None, ctx: Context | None + ) -> t.Any: + try: + return self.func(value) + except ValueError: + try: + value = str(value) + except UnicodeError: + value = value.decode("utf-8", "replace") + + self.fail(value, param, ctx) + + +class UnprocessedParamType(ParamType): + name = "text" + + def convert( + self, value: t.Any, param: Parameter | None, ctx: Context | None + ) -> t.Any: + return value + + def __repr__(self) -> str: + return "UNPROCESSED" + + +class StringParamType(ParamType): + name = "text" + + def convert( + self, value: t.Any, param: Parameter | None, ctx: Context | None + ) -> t.Any: + if isinstance(value, bytes): + enc = _get_argv_encoding() + try: + value = value.decode(enc) + except UnicodeError: + fs_enc = sys.getfilesystemencoding() + if fs_enc != enc: + try: + value = value.decode(fs_enc) + except UnicodeError: + value = value.decode("utf-8", "replace") + else: + value = value.decode("utf-8", "replace") + return value + return str(value) + + def __repr__(self) -> str: + return "STRING" + + +class Choice(ParamType, t.Generic[ParamTypeValue]): + """The choice type allows a value to be checked against a fixed set + of supported values. + + You may pass any iterable value which will be converted to a tuple + and thus will only be iterated once. + + The resulting value will always be one of the originally passed choices. + See :meth:`normalize_choice` for more info on the mapping of strings + to choices. See :ref:`choice-opts` for an example. + + :param case_sensitive: Set to false to make choices case + insensitive. Defaults to true. + + .. versionchanged:: 8.2.0 + Non-``str`` ``choices`` are now supported. It can additionally be any + iterable. Before you were not recommended to pass anything but a list or + tuple. + + .. versionadded:: 8.2.0 + Choice normalization can be overridden via :meth:`normalize_choice`. + """ + + name = "choice" + + def __init__( + self, choices: cabc.Iterable[ParamTypeValue], case_sensitive: bool = True + ) -> None: + self.choices: cabc.Sequence[ParamTypeValue] = tuple(choices) + self.case_sensitive = case_sensitive + + def to_info_dict(self) -> dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict["choices"] = self.choices + info_dict["case_sensitive"] = self.case_sensitive + return info_dict + + def _normalized_mapping( + self, ctx: Context | None = None + ) -> cabc.Mapping[ParamTypeValue, str]: + """ + Returns mapping where keys are the original choices and the values are + the normalized values that are accepted via the command line. + + This is a simple wrapper around :meth:`normalize_choice`, use that + instead which is supported. + """ + return { + choice: self.normalize_choice( + choice=choice, + ctx=ctx, + ) + for choice in self.choices + } + + def normalize_choice(self, choice: ParamTypeValue, ctx: Context | None) -> str: + """ + Normalize a choice value, used to map a passed string to a choice. + Each choice must have a unique normalized value. + + By default uses :meth:`Context.token_normalize_func` and if not case + sensitive, convert it to a casefolded value. + + .. versionadded:: 8.2.0 + """ + normed_value = choice.name if isinstance(choice, enum.Enum) else str(choice) + + if ctx is not None and ctx.token_normalize_func is not None: + normed_value = ctx.token_normalize_func(normed_value) + + if not self.case_sensitive: + normed_value = normed_value.casefold() + + return normed_value + + def get_metavar(self, param: Parameter, ctx: Context) -> str | None: + if param.param_type_name == "option" and not param.show_choices: # type: ignore + choice_metavars = [ + convert_type(type(choice)).name.upper() for choice in self.choices + ] + choices_str = "|".join([*dict.fromkeys(choice_metavars)]) + else: + choices_str = "|".join( + [str(i) for i in self._normalized_mapping(ctx=ctx).values()] + ) + + # Use curly braces to indicate a required argument. + if param.required and param.param_type_name == "argument": + return f"{{{choices_str}}}" + + # Use square braces to indicate an option or optional argument. + return f"[{choices_str}]" + + def get_missing_message(self, param: Parameter, ctx: Context | None) -> str: + """ + Message shown when no choice is passed. + + .. versionchanged:: 8.2.0 Added ``ctx`` argument. + """ + return _("Choose from:\n\t{choices}").format( + choices=",\n\t".join(self._normalized_mapping(ctx=ctx).values()) + ) + + def convert( + self, value: t.Any, param: Parameter | None, ctx: Context | None + ) -> ParamTypeValue: + """ + For a given value from the parser, normalize it and find its + matching normalized value in the list of choices. Then return the + matched "original" choice. + """ + normed_value = self.normalize_choice(choice=value, ctx=ctx) + normalized_mapping = self._normalized_mapping(ctx=ctx) + + try: + return next( + original + for original, normalized in normalized_mapping.items() + if normalized == normed_value + ) + except StopIteration: + self.fail( + self.get_invalid_choice_message(value=value, ctx=ctx), + param=param, + ctx=ctx, + ) + + def get_invalid_choice_message(self, value: t.Any, ctx: Context | None) -> str: + """Get the error message when the given choice is invalid. + + :param value: The invalid value. + + .. versionadded:: 8.2 + """ + choices_str = ", ".join(map(repr, self._normalized_mapping(ctx=ctx).values())) + return ngettext( + "{value!r} is not {choice}.", + "{value!r} is not one of {choices}.", + len(self.choices), + ).format(value=value, choice=choices_str, choices=choices_str) + + def __repr__(self) -> str: + return f"Choice({list(self.choices)})" + + def shell_complete( + self, ctx: Context, param: Parameter, incomplete: str + ) -> list[CompletionItem]: + """Complete choices that start with the incomplete value. + + :param ctx: Invocation context for this command. + :param param: The parameter that is requesting completion. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + str_choices = map(str, self.choices) + + if self.case_sensitive: + matched = (c for c in str_choices if c.startswith(incomplete)) + else: + incomplete = incomplete.lower() + matched = (c for c in str_choices if c.lower().startswith(incomplete)) + + return [CompletionItem(c) for c in matched] + + +class DateTime(ParamType): + """The DateTime type converts date strings into `datetime` objects. + + The format strings which are checked are configurable, but default to some + common (non-timezone aware) ISO 8601 formats. + + When specifying *DateTime* formats, you should only pass a list or a tuple. + Other iterables, like generators, may lead to surprising results. + + The format strings are processed using ``datetime.strptime``, and this + consequently defines the format strings which are allowed. + + Parsing is tried using each format, in order, and the first format which + parses successfully is used. + + :param formats: A list or tuple of date format strings, in the order in + which they should be tried. Defaults to + ``'%Y-%m-%d'``, ``'%Y-%m-%dT%H:%M:%S'``, + ``'%Y-%m-%d %H:%M:%S'``. + """ + + name = "datetime" + + def __init__(self, formats: cabc.Sequence[str] | None = None): + self.formats: cabc.Sequence[str] = formats or [ + "%Y-%m-%d", + "%Y-%m-%dT%H:%M:%S", + "%Y-%m-%d %H:%M:%S", + ] + + def to_info_dict(self) -> dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict["formats"] = self.formats + return info_dict + + def get_metavar(self, param: Parameter, ctx: Context) -> str | None: + return f"[{'|'.join(self.formats)}]" + + def _try_to_convert_date(self, value: t.Any, format: str) -> datetime | None: + try: + return datetime.strptime(value, format) + except ValueError: + return None + + def convert( + self, value: t.Any, param: Parameter | None, ctx: Context | None + ) -> t.Any: + if isinstance(value, datetime): + return value + + for format in self.formats: + converted = self._try_to_convert_date(value, format) + + if converted is not None: + return converted + + formats_str = ", ".join(map(repr, self.formats)) + self.fail( + ngettext( + "{value!r} does not match the format {format}.", + "{value!r} does not match the formats {formats}.", + len(self.formats), + ).format(value=value, format=formats_str, formats=formats_str), + param, + ctx, + ) + + def __repr__(self) -> str: + return "DateTime" + + +class _NumberParamTypeBase(ParamType): + _number_class: t.ClassVar[type[t.Any]] + + def convert( + self, value: t.Any, param: Parameter | None, ctx: Context | None + ) -> t.Any: + try: + return self._number_class(value) + except ValueError: + self.fail( + _("{value!r} is not a valid {number_type}.").format( + value=value, number_type=self.name + ), + param, + ctx, + ) + + +class _NumberRangeBase(_NumberParamTypeBase): + def __init__( + self, + min: float | None = None, + max: float | None = None, + min_open: bool = False, + max_open: bool = False, + clamp: bool = False, + ) -> None: + self.min = min + self.max = max + self.min_open = min_open + self.max_open = max_open + self.clamp = clamp + + def to_info_dict(self) -> dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict.update( + min=self.min, + max=self.max, + min_open=self.min_open, + max_open=self.max_open, + clamp=self.clamp, + ) + return info_dict + + def convert( + self, value: t.Any, param: Parameter | None, ctx: Context | None + ) -> t.Any: + import operator + + rv = super().convert(value, param, ctx) + lt_min: bool = self.min is not None and ( + operator.le if self.min_open else operator.lt + )(rv, self.min) + gt_max: bool = self.max is not None and ( + operator.ge if self.max_open else operator.gt + )(rv, self.max) + + if self.clamp: + if lt_min: + return self._clamp(self.min, 1, self.min_open) # type: ignore + + if gt_max: + return self._clamp(self.max, -1, self.max_open) # type: ignore + + if lt_min or gt_max: + self.fail( + _("{value} is not in the range {range}.").format( + value=rv, range=self._describe_range() + ), + param, + ctx, + ) + + return rv + + def _clamp(self, bound: float, dir: t.Literal[1, -1], open: bool) -> float: + """Find the valid value to clamp to bound in the given + direction. + + :param bound: The boundary value. + :param dir: 1 or -1 indicating the direction to move. + :param open: If true, the range does not include the bound. + """ + raise NotImplementedError + + def _describe_range(self) -> str: + """Describe the range for use in help text.""" + if self.min is None: + op = "<" if self.max_open else "<=" + return f"x{op}{self.max}" + + if self.max is None: + op = ">" if self.min_open else ">=" + return f"x{op}{self.min}" + + lop = "<" if self.min_open else "<=" + rop = "<" if self.max_open else "<=" + return f"{self.min}{lop}x{rop}{self.max}" + + def __repr__(self) -> str: + clamp = " clamped" if self.clamp else "" + return f"<{type(self).__name__} {self._describe_range()}{clamp}>" + + +class IntParamType(_NumberParamTypeBase): + name = "integer" + _number_class = int + + def __repr__(self) -> str: + return "INT" + + +class IntRange(_NumberRangeBase, IntParamType): + """Restrict an :data:`click.INT` value to a range of accepted + values. See :ref:`ranges`. + + If ``min`` or ``max`` are not passed, any value is accepted in that + direction. If ``min_open`` or ``max_open`` are enabled, the + corresponding boundary is not included in the range. + + If ``clamp`` is enabled, a value outside the range is clamped to the + boundary instead of failing. + + .. versionchanged:: 8.0 + Added the ``min_open`` and ``max_open`` parameters. + """ + + name = "integer range" + + def _clamp( # type: ignore + self, bound: int, dir: t.Literal[1, -1], open: bool + ) -> int: + if not open: + return bound + + return bound + dir + + +class FloatParamType(_NumberParamTypeBase): + name = "float" + _number_class = float + + def __repr__(self) -> str: + return "FLOAT" + + +class FloatRange(_NumberRangeBase, FloatParamType): + """Restrict a :data:`click.FLOAT` value to a range of accepted + values. See :ref:`ranges`. + + If ``min`` or ``max`` are not passed, any value is accepted in that + direction. If ``min_open`` or ``max_open`` are enabled, the + corresponding boundary is not included in the range. + + If ``clamp`` is enabled, a value outside the range is clamped to the + boundary instead of failing. This is not supported if either + boundary is marked ``open``. + + .. versionchanged:: 8.0 + Added the ``min_open`` and ``max_open`` parameters. + """ + + name = "float range" + + def __init__( + self, + min: float | None = None, + max: float | None = None, + min_open: bool = False, + max_open: bool = False, + clamp: bool = False, + ) -> None: + super().__init__( + min=min, max=max, min_open=min_open, max_open=max_open, clamp=clamp + ) + + if (min_open or max_open) and clamp: + raise TypeError("Clamping is not supported for open bounds.") + + def _clamp(self, bound: float, dir: t.Literal[1, -1], open: bool) -> float: + if not open: + return bound + + # Could use math.nextafter here, but clamping an + # open float range doesn't seem to be particularly useful. It's + # left up to the user to write a callback to do it if needed. + raise RuntimeError("Clamping is not supported for open bounds.") + + +class BoolParamType(ParamType): + name = "boolean" + + bool_states: dict[str, bool] = { + "1": True, + "0": False, + "yes": True, + "no": False, + "true": True, + "false": False, + "on": True, + "off": False, + "t": True, + "f": False, + "y": True, + "n": False, + # Absence of value is considered False. + "": False, + } + """A mapping of string values to boolean states. + + Mapping is inspired by :py:attr:`configparser.ConfigParser.BOOLEAN_STATES` + and extends it. + + .. caution:: + String values are lower-cased, as the ``str_to_bool`` comparison function + below is case-insensitive. + + .. warning:: + The mapping is not exhaustive, and does not cover all possible boolean strings + representations. It will remains as it is to avoid endless bikeshedding. + + Future work my be considered to make this mapping user-configurable from public + API. + """ + + @staticmethod + def str_to_bool(value: str | bool) -> bool | None: + """Convert a string to a boolean value. + + If the value is already a boolean, it is returned as-is. If the value is a + string, it is stripped of whitespaces and lower-cased, then checked against + the known boolean states pre-defined in the `BoolParamType.bool_states` mapping + above. + + Returns `None` if the value does not match any known boolean state. + """ + if isinstance(value, bool): + return value + return BoolParamType.bool_states.get(value.strip().lower()) + + def convert( + self, value: t.Any, param: Parameter | None, ctx: Context | None + ) -> bool: + normalized = self.str_to_bool(value) + if normalized is None: + self.fail( + _( + "{value!r} is not a valid boolean. Recognized values: {states}" + ).format(value=value, states=", ".join(sorted(self.bool_states))), + param, + ctx, + ) + return normalized + + def __repr__(self) -> str: + return "BOOL" + + +class UUIDParameterType(ParamType): + name = "uuid" + + def convert( + self, value: t.Any, param: Parameter | None, ctx: Context | None + ) -> t.Any: + import uuid + + if isinstance(value, uuid.UUID): + return value + + value = value.strip() + + try: + return uuid.UUID(value) + except ValueError: + self.fail( + _("{value!r} is not a valid UUID.").format(value=value), param, ctx + ) + + def __repr__(self) -> str: + return "UUID" + + +class File(ParamType): + """Declares a parameter to be a file for reading or writing. The file + is automatically closed once the context tears down (after the command + finished working). + + Files can be opened for reading or writing. The special value ``-`` + indicates stdin or stdout depending on the mode. + + By default, the file is opened for reading text data, but it can also be + opened in binary mode or for writing. The encoding parameter can be used + to force a specific encoding. + + The `lazy` flag controls if the file should be opened immediately or upon + first IO. The default is to be non-lazy for standard input and output + streams as well as files opened for reading, `lazy` otherwise. When opening a + file lazily for reading, it is still opened temporarily for validation, but + will not be held open until first IO. lazy is mainly useful when opening + for writing to avoid creating the file until it is needed. + + Files can also be opened atomically in which case all writes go into a + separate file in the same folder and upon completion the file will + be moved over to the original location. This is useful if a file + regularly read by other users is modified. + + See :ref:`file-args` for more information. + + .. versionchanged:: 2.0 + Added the ``atomic`` parameter. + """ + + name = "filename" + envvar_list_splitter: t.ClassVar[str] = os.path.pathsep + + def __init__( + self, + mode: str = "r", + encoding: str | None = None, + errors: str | None = "strict", + lazy: bool | None = None, + atomic: bool = False, + ) -> None: + self.mode = mode + self.encoding = encoding + self.errors = errors + self.lazy = lazy + self.atomic = atomic + + def to_info_dict(self) -> dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict.update(mode=self.mode, encoding=self.encoding) + return info_dict + + def resolve_lazy_flag(self, value: str | os.PathLike[str]) -> bool: + if self.lazy is not None: + return self.lazy + if os.fspath(value) == "-": + return False + elif "w" in self.mode: + return True + return False + + def convert( + self, + value: str | os.PathLike[str] | t.IO[t.Any], + param: Parameter | None, + ctx: Context | None, + ) -> t.IO[t.Any]: + if _is_file_like(value): + return value + + value = t.cast("str | os.PathLike[str]", value) + + try: + lazy = self.resolve_lazy_flag(value) + + if lazy: + lf = LazyFile( + value, self.mode, self.encoding, self.errors, atomic=self.atomic + ) + + if ctx is not None: + ctx.call_on_close(lf.close_intelligently) + + return t.cast("t.IO[t.Any]", lf) + + f, should_close = open_stream( + value, self.mode, self.encoding, self.errors, atomic=self.atomic + ) + + # If a context is provided, we automatically close the file + # at the end of the context execution (or flush out). If a + # context does not exist, it's the caller's responsibility to + # properly close the file. This for instance happens when the + # type is used with prompts. + if ctx is not None: + if should_close: + ctx.call_on_close(safecall(f.close)) + else: + ctx.call_on_close(safecall(f.flush)) + + return f + except OSError as e: + self.fail(f"'{format_filename(value)}': {e.strerror}", param, ctx) + + def shell_complete( + self, ctx: Context, param: Parameter, incomplete: str + ) -> list[CompletionItem]: + """Return a special completion marker that tells the completion + system to use the shell to provide file path completions. + + :param ctx: Invocation context for this command. + :param param: The parameter that is requesting completion. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + return [CompletionItem(incomplete, type="file")] + + +def _is_file_like(value: t.Any) -> te.TypeGuard[t.IO[t.Any]]: + return hasattr(value, "read") or hasattr(value, "write") + + +class Path(ParamType): + """The ``Path`` type is similar to the :class:`File` type, but + returns the filename instead of an open file. Various checks can be + enabled to validate the type of file and permissions. + + :param exists: The file or directory needs to exist for the value to + be valid. If this is not set to ``True``, and the file does not + exist, then all further checks are silently skipped. + :param file_okay: Allow a file as a value. + :param dir_okay: Allow a directory as a value. + :param readable: if true, a readable check is performed. + :param writable: if true, a writable check is performed. + :param executable: if true, an executable check is performed. + :param resolve_path: Make the value absolute and resolve any + symlinks. A ``~`` is not expanded, as this is supposed to be + done by the shell only. + :param allow_dash: Allow a single dash as a value, which indicates + a standard stream (but does not open it). Use + :func:`~click.open_file` to handle opening this value. + :param path_type: Convert the incoming path value to this type. If + ``None``, keep Python's default, which is ``str``. Useful to + convert to :class:`pathlib.Path`. + + .. versionchanged:: 8.1 + Added the ``executable`` parameter. + + .. versionchanged:: 8.0 + Allow passing ``path_type=pathlib.Path``. + + .. versionchanged:: 6.0 + Added the ``allow_dash`` parameter. + """ + + envvar_list_splitter: t.ClassVar[str] = os.path.pathsep + + def __init__( + self, + exists: bool = False, + file_okay: bool = True, + dir_okay: bool = True, + writable: bool = False, + readable: bool = True, + resolve_path: bool = False, + allow_dash: bool = False, + path_type: type[t.Any] | None = None, + executable: bool = False, + ): + self.exists = exists + self.file_okay = file_okay + self.dir_okay = dir_okay + self.readable = readable + self.writable = writable + self.executable = executable + self.resolve_path = resolve_path + self.allow_dash = allow_dash + self.type = path_type + + if self.file_okay and not self.dir_okay: + self.name: str = _("file") + elif self.dir_okay and not self.file_okay: + self.name = _("directory") + else: + self.name = _("path") + + def to_info_dict(self) -> dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict.update( + exists=self.exists, + file_okay=self.file_okay, + dir_okay=self.dir_okay, + writable=self.writable, + readable=self.readable, + allow_dash=self.allow_dash, + ) + return info_dict + + def coerce_path_result( + self, value: str | os.PathLike[str] + ) -> str | bytes | os.PathLike[str]: + if self.type is not None and not isinstance(value, self.type): + if self.type is str: + return os.fsdecode(value) + elif self.type is bytes: + return os.fsencode(value) + else: + return t.cast("os.PathLike[str]", self.type(value)) + + return value + + def convert( + self, + value: str | os.PathLike[str], + param: Parameter | None, + ctx: Context | None, + ) -> str | bytes | os.PathLike[str]: + rv = value + + is_dash = self.file_okay and self.allow_dash and rv in (b"-", "-") + + if not is_dash: + if self.resolve_path: + rv = os.path.realpath(rv) + + try: + st = os.stat(rv) + except OSError: + if not self.exists: + return self.coerce_path_result(rv) + self.fail( + _("{name} {filename!r} does not exist.").format( + name=self.name.title(), filename=format_filename(value) + ), + param, + ctx, + ) + + if not self.file_okay and stat.S_ISREG(st.st_mode): + self.fail( + _("{name} {filename!r} is a file.").format( + name=self.name.title(), filename=format_filename(value) + ), + param, + ctx, + ) + if not self.dir_okay and stat.S_ISDIR(st.st_mode): + self.fail( + _("{name} {filename!r} is a directory.").format( + name=self.name.title(), filename=format_filename(value) + ), + param, + ctx, + ) + + if self.readable and not os.access(rv, os.R_OK): + self.fail( + _("{name} {filename!r} is not readable.").format( + name=self.name.title(), filename=format_filename(value) + ), + param, + ctx, + ) + + if self.writable and not os.access(rv, os.W_OK): + self.fail( + _("{name} {filename!r} is not writable.").format( + name=self.name.title(), filename=format_filename(value) + ), + param, + ctx, + ) + + if self.executable and not os.access(value, os.X_OK): + self.fail( + _("{name} {filename!r} is not executable.").format( + name=self.name.title(), filename=format_filename(value) + ), + param, + ctx, + ) + + return self.coerce_path_result(rv) + + def shell_complete( + self, ctx: Context, param: Parameter, incomplete: str + ) -> list[CompletionItem]: + """Return a special completion marker that tells the completion + system to use the shell to provide path completions for only + directories or any paths. + + :param ctx: Invocation context for this command. + :param param: The parameter that is requesting completion. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + type = "dir" if self.dir_okay and not self.file_okay else "file" + return [CompletionItem(incomplete, type=type)] + + +class Tuple(CompositeParamType): + """The default behavior of Click is to apply a type on a value directly. + This works well in most cases, except for when `nargs` is set to a fixed + count and different types should be used for different items. In this + case the :class:`Tuple` type can be used. This type can only be used + if `nargs` is set to a fixed number. + + For more information see :ref:`tuple-type`. + + This can be selected by using a Python tuple literal as a type. + + :param types: a list of types that should be used for the tuple items. + """ + + def __init__(self, types: cabc.Sequence[type[t.Any] | ParamType]) -> None: + self.types: cabc.Sequence[ParamType] = [convert_type(ty) for ty in types] + + def to_info_dict(self) -> dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict["types"] = [t.to_info_dict() for t in self.types] + return info_dict + + @property + def name(self) -> str: # type: ignore + return f"<{' '.join(ty.name for ty in self.types)}>" + + @property + def arity(self) -> int: # type: ignore + return len(self.types) + + def convert( + self, value: t.Any, param: Parameter | None, ctx: Context | None + ) -> t.Any: + len_type = len(self.types) + len_value = len(value) + + if len_value != len_type: + self.fail( + ngettext( + "{len_type} values are required, but {len_value} was given.", + "{len_type} values are required, but {len_value} were given.", + len_value, + ).format(len_type=len_type, len_value=len_value), + param=param, + ctx=ctx, + ) + + return tuple( + ty(x, param, ctx) for ty, x in zip(self.types, value, strict=False) + ) + + +def convert_type(ty: t.Any | None, default: t.Any | None = None) -> ParamType: + """Find the most appropriate :class:`ParamType` for the given Python + type. If the type isn't provided, it can be inferred from a default + value. + """ + guessed_type = False + + if ty is None and default is not None: + if isinstance(default, (tuple, list)): + # If the default is empty, ty will remain None and will + # return STRING. + if default: + item = default[0] + + # A tuple of tuples needs to detect the inner types. + # Can't call convert recursively because that would + # incorrectly unwind the tuple to a single type. + if isinstance(item, (tuple, list)): + ty = tuple(map(type, item)) + else: + ty = type(item) + else: + ty = type(default) + + guessed_type = True + + if isinstance(ty, tuple): + return Tuple(ty) + + if isinstance(ty, ParamType): + return ty + + if ty is str or ty is None: + return STRING + + if ty is int: + return INT + + if ty is float: + return FLOAT + + if ty is bool: + return BOOL + + if guessed_type: + return STRING + + if __debug__: + try: + if issubclass(ty, ParamType): + raise AssertionError( + f"Attempted to use an uninstantiated parameter type ({ty})." + ) + except TypeError: + # ty is an instance (correct), so issubclass fails. + pass + + return FuncParamType(ty) + + +#: A dummy parameter type that just does nothing. From a user's +#: perspective this appears to just be the same as `STRING` but +#: internally no string conversion takes place if the input was bytes. +#: This is usually useful when working with file paths as they can +#: appear in bytes and unicode. +#: +#: For path related uses the :class:`Path` type is a better choice but +#: there are situations where an unprocessed type is useful which is why +#: it is is provided. +#: +#: .. versionadded:: 4.0 +UNPROCESSED = UnprocessedParamType() + +#: A unicode string parameter type which is the implicit default. This +#: can also be selected by using ``str`` as type. +STRING = StringParamType() + +#: An integer parameter. This can also be selected by using ``int`` as +#: type. +INT = IntParamType() + +#: A floating point value parameter. This can also be selected by using +#: ``float`` as type. +FLOAT = FloatParamType() + +#: A boolean parameter. This is the default for boolean flags. This can +#: also be selected by using ``bool`` as a type. +BOOL = BoolParamType() + +#: A UUID parameter. +UUID = UUIDParameterType() + + +class OptionHelpExtra(t.TypedDict, total=False): + envvars: tuple[str, ...] + default: str + range: str + required: str diff --git a/backend/venv/Lib/site-packages/click/utils.py b/backend/venv/Lib/site-packages/click/utils.py new file mode 100644 index 0000000..beae26f --- /dev/null +++ b/backend/venv/Lib/site-packages/click/utils.py @@ -0,0 +1,627 @@ +from __future__ import annotations + +import collections.abc as cabc +import os +import re +import sys +import typing as t +from functools import update_wrapper +from types import ModuleType +from types import TracebackType + +from ._compat import _default_text_stderr +from ._compat import _default_text_stdout +from ._compat import _find_binary_writer +from ._compat import auto_wrap_for_ansi +from ._compat import binary_streams +from ._compat import open_stream +from ._compat import should_strip_ansi +from ._compat import strip_ansi +from ._compat import text_streams +from ._compat import WIN +from .globals import resolve_color_default + +if t.TYPE_CHECKING: + import typing_extensions as te + + P = te.ParamSpec("P") + +R = t.TypeVar("R") + + +def _posixify(name: str) -> str: + return "-".join(name.split()).lower() + + +def safecall(func: t.Callable[P, R]) -> t.Callable[P, R | None]: + """Wraps a function so that it swallows exceptions.""" + + def wrapper(*args: P.args, **kwargs: P.kwargs) -> R | None: + try: + return func(*args, **kwargs) + except Exception: + pass + return None + + return update_wrapper(wrapper, func) + + +def make_str(value: t.Any) -> str: + """Converts a value into a valid string.""" + if isinstance(value, bytes): + try: + return value.decode(sys.getfilesystemencoding()) + except UnicodeError: + return value.decode("utf-8", "replace") + return str(value) + + +def make_default_short_help(help: str, max_length: int = 45) -> str: + """Returns a condensed version of help string.""" + # Consider only the first paragraph. + paragraph_end = help.find("\n\n") + + if paragraph_end != -1: + help = help[:paragraph_end] + + # Collapse newlines, tabs, and spaces. + words = help.split() + + if not words: + return "" + + # The first paragraph started with a "no rewrap" marker, ignore it. + if words[0] == "\b": + words = words[1:] + + total_length = 0 + last_index = len(words) - 1 + + for i, word in enumerate(words): + total_length += len(word) + (i > 0) + + if total_length > max_length: # too long, truncate + break + + if word[-1] == ".": # sentence end, truncate without "..." + return " ".join(words[: i + 1]) + + if total_length == max_length and i != last_index: + break # not at sentence end, truncate with "..." + else: + return " ".join(words) # no truncation needed + + # Account for the length of the suffix. + total_length += len("...") + + # remove words until the length is short enough + while i > 0: + total_length -= len(words[i]) + (i > 0) + + if total_length <= max_length: + break + + i -= 1 + + return " ".join(words[:i]) + "..." + + +class LazyFile: + """A lazy file works like a regular file but it does not fully open + the file but it does perform some basic checks early to see if the + filename parameter does make sense. This is useful for safely opening + files for writing. + """ + + def __init__( + self, + filename: str | os.PathLike[str], + mode: str = "r", + encoding: str | None = None, + errors: str | None = "strict", + atomic: bool = False, + ): + self.name: str = os.fspath(filename) + self.mode = mode + self.encoding = encoding + self.errors = errors + self.atomic = atomic + self._f: t.IO[t.Any] | None + self.should_close: bool + + if self.name == "-": + self._f, self.should_close = open_stream(filename, mode, encoding, errors) + else: + if "r" in mode: + # Open and close the file in case we're opening it for + # reading so that we can catch at least some errors in + # some cases early. + open(filename, mode).close() + self._f = None + self.should_close = True + + def __getattr__(self, name: str) -> t.Any: + return getattr(self.open(), name) + + def __repr__(self) -> str: + if self._f is not None: + return repr(self._f) + return f"" + + def open(self) -> t.IO[t.Any]: + """Opens the file if it's not yet open. This call might fail with + a :exc:`FileError`. Not handling this error will produce an error + that Click shows. + """ + if self._f is not None: + return self._f + try: + rv, self.should_close = open_stream( + self.name, self.mode, self.encoding, self.errors, atomic=self.atomic + ) + except OSError as e: + from .exceptions import FileError + + raise FileError(self.name, hint=e.strerror) from e + self._f = rv + return rv + + def close(self) -> None: + """Closes the underlying file, no matter what.""" + if self._f is not None: + self._f.close() + + def close_intelligently(self) -> None: + """This function only closes the file if it was opened by the lazy + file wrapper. For instance this will never close stdin. + """ + if self.should_close: + self.close() + + def __enter__(self) -> LazyFile: + return self + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_value: BaseException | None, + tb: TracebackType | None, + ) -> None: + self.close_intelligently() + + def __iter__(self) -> cabc.Iterator[t.AnyStr]: + self.open() + return iter(self._f) # type: ignore + + +class KeepOpenFile: + def __init__(self, file: t.IO[t.Any]) -> None: + self._file: t.IO[t.Any] = file + + def __getattr__(self, name: str) -> t.Any: + return getattr(self._file, name) + + def __enter__(self) -> KeepOpenFile: + return self + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_value: BaseException | None, + tb: TracebackType | None, + ) -> None: + pass + + def __repr__(self) -> str: + return repr(self._file) + + def __iter__(self) -> cabc.Iterator[t.AnyStr]: + return iter(self._file) + + +def echo( + message: t.Any | None = None, + file: t.IO[t.Any] | None = None, + nl: bool = True, + err: bool = False, + color: bool | None = None, +) -> None: + """Print a message and newline to stdout or a file. This should be + used instead of :func:`print` because it provides better support + for different data, files, and environments. + + Compared to :func:`print`, this does the following: + + - Ensures that the output encoding is not misconfigured on Linux. + - Supports Unicode in the Windows console. + - Supports writing to binary outputs, and supports writing bytes + to text outputs. + - Supports colors and styles on Windows. + - Removes ANSI color and style codes if the output does not look + like an interactive terminal. + - Always flushes the output. + + :param message: The string or bytes to output. Other objects are + converted to strings. + :param file: The file to write to. Defaults to ``stdout``. + :param err: Write to ``stderr`` instead of ``stdout``. + :param nl: Print a newline after the message. Enabled by default. + :param color: Force showing or hiding colors and other styles. By + default Click will remove color if the output does not look like + an interactive terminal. + + .. versionchanged:: 6.0 + Support Unicode output on the Windows console. Click does not + modify ``sys.stdout``, so ``sys.stdout.write()`` and ``print()`` + will still not support Unicode. + + .. versionchanged:: 4.0 + Added the ``color`` parameter. + + .. versionadded:: 3.0 + Added the ``err`` parameter. + + .. versionchanged:: 2.0 + Support colors on Windows if colorama is installed. + """ + if file is None: + if err: + file = _default_text_stderr() + else: + file = _default_text_stdout() + + # There are no standard streams attached to write to. For example, + # pythonw on Windows. + if file is None: + return + + # Convert non bytes/text into the native string type. + if message is not None and not isinstance(message, (str, bytes, bytearray)): + out: str | bytes | bytearray | None = str(message) + else: + out = message + + if nl: + out = out or "" + if isinstance(out, str): + out += "\n" + else: + out += b"\n" + + if not out: + file.flush() + return + + # If there is a message and the value looks like bytes, we manually + # need to find the binary stream and write the message in there. + # This is done separately so that most stream types will work as you + # would expect. Eg: you can write to StringIO for other cases. + if isinstance(out, (bytes, bytearray)): + binary_file = _find_binary_writer(file) + + if binary_file is not None: + file.flush() + binary_file.write(out) + binary_file.flush() + return + + # ANSI style code support. For no message or bytes, nothing happens. + # When outputting to a file instead of a terminal, strip codes. + else: + color = resolve_color_default(color) + + if should_strip_ansi(file, color): + out = strip_ansi(out) + elif WIN: + if auto_wrap_for_ansi is not None: + file = auto_wrap_for_ansi(file, color) # type: ignore + elif not color: + out = strip_ansi(out) + + file.write(out) # type: ignore + file.flush() + + +def get_binary_stream(name: t.Literal["stdin", "stdout", "stderr"]) -> t.BinaryIO: + """Returns a system stream for byte processing. + + :param name: the name of the stream to open. Valid names are ``'stdin'``, + ``'stdout'`` and ``'stderr'`` + """ + opener = binary_streams.get(name) + if opener is None: + raise TypeError(f"Unknown standard stream '{name}'") + return opener() + + +def get_text_stream( + name: t.Literal["stdin", "stdout", "stderr"], + encoding: str | None = None, + errors: str | None = "strict", +) -> t.TextIO: + """Returns a system stream for text processing. This usually returns + a wrapped stream around a binary stream returned from + :func:`get_binary_stream` but it also can take shortcuts for already + correctly configured streams. + + :param name: the name of the stream to open. Valid names are ``'stdin'``, + ``'stdout'`` and ``'stderr'`` + :param encoding: overrides the detected default encoding. + :param errors: overrides the default error mode. + """ + opener = text_streams.get(name) + if opener is None: + raise TypeError(f"Unknown standard stream '{name}'") + return opener(encoding, errors) + + +def open_file( + filename: str | os.PathLike[str], + mode: str = "r", + encoding: str | None = None, + errors: str | None = "strict", + lazy: bool = False, + atomic: bool = False, +) -> t.IO[t.Any]: + """Open a file, with extra behavior to handle ``'-'`` to indicate + a standard stream, lazy open on write, and atomic write. Similar to + the behavior of the :class:`~click.File` param type. + + If ``'-'`` is given to open ``stdout`` or ``stdin``, the stream is + wrapped so that using it in a context manager will not close it. + This makes it possible to use the function without accidentally + closing a standard stream: + + .. code-block:: python + + with open_file(filename) as f: + ... + + :param filename: The name or Path of the file to open, or ``'-'`` for + ``stdin``/``stdout``. + :param mode: The mode in which to open the file. + :param encoding: The encoding to decode or encode a file opened in + text mode. + :param errors: The error handling mode. + :param lazy: Wait to open the file until it is accessed. For read + mode, the file is temporarily opened to raise access errors + early, then closed until it is read again. + :param atomic: Write to a temporary file and replace the given file + on close. + + .. versionadded:: 3.0 + """ + if lazy: + return t.cast( + "t.IO[t.Any]", LazyFile(filename, mode, encoding, errors, atomic=atomic) + ) + + f, should_close = open_stream(filename, mode, encoding, errors, atomic=atomic) + + if not should_close: + f = t.cast("t.IO[t.Any]", KeepOpenFile(f)) + + return f + + +def format_filename( + filename: str | bytes | os.PathLike[str] | os.PathLike[bytes], + shorten: bool = False, +) -> str: + """Format a filename as a string for display. Ensures the filename can be + displayed by replacing any invalid bytes or surrogate escapes in the name + with the replacement character ``�``. + + Invalid bytes or surrogate escapes will raise an error when written to a + stream with ``errors="strict"``. This will typically happen with ``stdout`` + when the locale is something like ``en_GB.UTF-8``. + + Many scenarios *are* safe to write surrogates though, due to PEP 538 and + PEP 540, including: + + - Writing to ``stderr``, which uses ``errors="backslashreplace"``. + - The system has ``LANG=C.UTF-8``, ``C``, or ``POSIX``. Python opens + stdout and stderr with ``errors="surrogateescape"``. + - None of ``LANG/LC_*`` are set. Python assumes ``LANG=C.UTF-8``. + - Python is started in UTF-8 mode with ``PYTHONUTF8=1`` or ``-X utf8``. + Python opens stdout and stderr with ``errors="surrogateescape"``. + + :param filename: formats a filename for UI display. This will also convert + the filename into unicode without failing. + :param shorten: this optionally shortens the filename to strip of the + path that leads up to it. + """ + if shorten: + filename = os.path.basename(filename) + else: + filename = os.fspath(filename) + + if isinstance(filename, bytes): + filename = filename.decode(sys.getfilesystemencoding(), "replace") + else: + filename = filename.encode("utf-8", "surrogateescape").decode( + "utf-8", "replace" + ) + + return filename + + +def get_app_dir(app_name: str, roaming: bool = True, force_posix: bool = False) -> str: + r"""Returns the config folder for the application. The default behavior + is to return whatever is most appropriate for the operating system. + + To give you an idea, for an app called ``"Foo Bar"``, something like + the following folders could be returned: + + Mac OS X: + ``~/Library/Application Support/Foo Bar`` + Mac OS X (POSIX): + ``~/.foo-bar`` + Unix: + ``~/.config/foo-bar`` + Unix (POSIX): + ``~/.foo-bar`` + Windows (roaming): + ``C:\Users\\AppData\Roaming\Foo Bar`` + Windows (not roaming): + ``C:\Users\\AppData\Local\Foo Bar`` + + .. versionadded:: 2.0 + + :param app_name: the application name. This should be properly capitalized + and can contain whitespace. + :param roaming: controls if the folder should be roaming or not on Windows. + Has no effect otherwise. + :param force_posix: if this is set to `True` then on any POSIX system the + folder will be stored in the home folder with a leading + dot instead of the XDG config home or darwin's + application support folder. + """ + if WIN: + key = "APPDATA" if roaming else "LOCALAPPDATA" + folder = os.environ.get(key) + if folder is None: + folder = os.path.expanduser("~") + return os.path.join(folder, app_name) + if force_posix: + return os.path.join(os.path.expanduser(f"~/.{_posixify(app_name)}")) + if sys.platform == "darwin": + return os.path.join( + os.path.expanduser("~/Library/Application Support"), app_name + ) + return os.path.join( + os.environ.get("XDG_CONFIG_HOME", os.path.expanduser("~/.config")), + _posixify(app_name), + ) + + +class PacifyFlushWrapper: + """This wrapper is used to catch and suppress BrokenPipeErrors resulting + from ``.flush()`` being called on broken pipe during the shutdown/final-GC + of the Python interpreter. Notably ``.flush()`` is always called on + ``sys.stdout`` and ``sys.stderr``. So as to have minimal impact on any + other cleanup code, and the case where the underlying file is not a broken + pipe, all calls and attributes are proxied. + """ + + def __init__(self, wrapped: t.IO[t.Any]) -> None: + self.wrapped = wrapped + + def flush(self) -> None: + try: + self.wrapped.flush() + except OSError as e: + import errno + + if e.errno != errno.EPIPE: + raise + + def __getattr__(self, attr: str) -> t.Any: + return getattr(self.wrapped, attr) + + +def _detect_program_name( + path: str | None = None, _main: ModuleType | None = None +) -> str: + """Determine the command used to run the program, for use in help + text. If a file or entry point was executed, the file name is + returned. If ``python -m`` was used to execute a module or package, + ``python -m name`` is returned. + + This doesn't try to be too precise, the goal is to give a concise + name for help text. Files are only shown as their name without the + path. ``python`` is only shown for modules, and the full path to + ``sys.executable`` is not shown. + + :param path: The Python file being executed. Python puts this in + ``sys.argv[0]``, which is used by default. + :param _main: The ``__main__`` module. This should only be passed + during internal testing. + + .. versionadded:: 8.0 + Based on command args detection in the Werkzeug reloader. + + :meta private: + """ + if _main is None: + _main = sys.modules["__main__"] + + if not path: + path = sys.argv[0] + + # The value of __package__ indicates how Python was called. It may + # not exist if a setuptools script is installed as an egg. It may be + # set incorrectly for entry points created with pip on Windows. + # It is set to "" inside a Shiv or PEX zipapp. + if getattr(_main, "__package__", None) in {None, ""} or ( + os.name == "nt" + and _main.__package__ == "" + and not os.path.exists(path) + and os.path.exists(f"{path}.exe") + ): + # Executed a file, like "python app.py". + return os.path.basename(path) + + # Executed a module, like "python -m example". + # Rewritten by Python from "-m script" to "/path/to/script.py". + # Need to look at main module to determine how it was executed. + py_module = t.cast(str, _main.__package__) + name = os.path.splitext(os.path.basename(path))[0] + + # A submodule like "example.cli". + if name != "__main__": + py_module = f"{py_module}.{name}" + + return f"python -m {py_module.lstrip('.')}" + + +def _expand_args( + args: cabc.Iterable[str], + *, + user: bool = True, + env: bool = True, + glob_recursive: bool = True, +) -> list[str]: + """Simulate Unix shell expansion with Python functions. + + See :func:`glob.glob`, :func:`os.path.expanduser`, and + :func:`os.path.expandvars`. + + This is intended for use on Windows, where the shell does not do any + expansion. It may not exactly match what a Unix shell would do. + + :param args: List of command line arguments to expand. + :param user: Expand user home directory. + :param env: Expand environment variables. + :param glob_recursive: ``**`` matches directories recursively. + + .. versionchanged:: 8.1 + Invalid glob patterns are treated as empty expansions rather + than raising an error. + + .. versionadded:: 8.0 + + :meta private: + """ + from glob import glob + + out = [] + + for arg in args: + if user: + arg = os.path.expanduser(arg) + + if env: + arg = os.path.expandvars(arg) + + try: + matches = glob(arg, recursive=glob_recursive) + except re.error: + matches = [] + + if not matches: + out.append(arg) + else: + out.extend(matches) + + return out diff --git a/backend/venv/Lib/site-packages/colorama-0.4.6.dist-info/INSTALLER b/backend/venv/Lib/site-packages/colorama-0.4.6.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/backend/venv/Lib/site-packages/colorama-0.4.6.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/backend/venv/Lib/site-packages/colorama-0.4.6.dist-info/METADATA b/backend/venv/Lib/site-packages/colorama-0.4.6.dist-info/METADATA new file mode 100644 index 0000000..a1b5c57 --- /dev/null +++ b/backend/venv/Lib/site-packages/colorama-0.4.6.dist-info/METADATA @@ -0,0 +1,441 @@ +Metadata-Version: 2.1 +Name: colorama +Version: 0.4.6 +Summary: Cross-platform colored terminal text. +Project-URL: Homepage, https://github.com/tartley/colorama +Author-email: Jonathan Hartley +License-File: LICENSE.txt +Keywords: ansi,color,colour,crossplatform,terminal,text,windows,xplatform +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Console +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Topic :: Terminals +Requires-Python: !=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7 +Description-Content-Type: text/x-rst + +.. image:: https://img.shields.io/pypi/v/colorama.svg + :target: https://pypi.org/project/colorama/ + :alt: Latest Version + +.. image:: https://img.shields.io/pypi/pyversions/colorama.svg + :target: https://pypi.org/project/colorama/ + :alt: Supported Python versions + +.. image:: https://github.com/tartley/colorama/actions/workflows/test.yml/badge.svg + :target: https://github.com/tartley/colorama/actions/workflows/test.yml + :alt: Build Status + +Colorama +======== + +Makes ANSI escape character sequences (for producing colored terminal text and +cursor positioning) work under MS Windows. + +.. |donate| image:: https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif + :target: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=2MZ9D2GMLYCUJ&item_name=Colorama¤cy_code=USD + :alt: Donate with Paypal + +`PyPI for releases `_ | +`Github for source `_ | +`Colorama for enterprise on Tidelift `_ + +If you find Colorama useful, please |donate| to the authors. Thank you! + +Installation +------------ + +Tested on CPython 2.7, 3.7, 3.8, 3.9 and 3.10 and Pypy 2.7 and 3.8. + +No requirements other than the standard library. + +.. code-block:: bash + + pip install colorama + # or + conda install -c anaconda colorama + +Description +----------- + +ANSI escape character sequences have long been used to produce colored terminal +text and cursor positioning on Unix and Macs. Colorama makes this work on +Windows, too, by wrapping ``stdout``, stripping ANSI sequences it finds (which +would appear as gobbledygook in the output), and converting them into the +appropriate win32 calls to modify the state of the terminal. On other platforms, +Colorama does nothing. + +This has the upshot of providing a simple cross-platform API for printing +colored terminal text from Python, and has the happy side-effect that existing +applications or libraries which use ANSI sequences to produce colored output on +Linux or Macs can now also work on Windows, simply by calling +``colorama.just_fix_windows_console()`` (since v0.4.6) or ``colorama.init()`` +(all versions, but may have other side-effects – see below). + +An alternative approach is to install ``ansi.sys`` on Windows machines, which +provides the same behaviour for all applications running in terminals. Colorama +is intended for situations where that isn't easy (e.g., maybe your app doesn't +have an installer.) + +Demo scripts in the source code repository print some colored text using +ANSI sequences. Compare their output under Gnome-terminal's built in ANSI +handling, versus on Windows Command-Prompt using Colorama: + +.. image:: https://github.com/tartley/colorama/raw/master/screenshots/ubuntu-demo.png + :width: 661 + :height: 357 + :alt: ANSI sequences on Ubuntu under gnome-terminal. + +.. image:: https://github.com/tartley/colorama/raw/master/screenshots/windows-demo.png + :width: 668 + :height: 325 + :alt: Same ANSI sequences on Windows, using Colorama. + +These screenshots show that, on Windows, Colorama does not support ANSI 'dim +text'; it looks the same as 'normal text'. + +Usage +----- + +Initialisation +.............. + +If the only thing you want from Colorama is to get ANSI escapes to work on +Windows, then run: + +.. code-block:: python + + from colorama import just_fix_windows_console + just_fix_windows_console() + +If you're on a recent version of Windows 10 or better, and your stdout/stderr +are pointing to a Windows console, then this will flip the magic configuration +switch to enable Windows' built-in ANSI support. + +If you're on an older version of Windows, and your stdout/stderr are pointing to +a Windows console, then this will wrap ``sys.stdout`` and/or ``sys.stderr`` in a +magic file object that intercepts ANSI escape sequences and issues the +appropriate Win32 calls to emulate them. + +In all other circumstances, it does nothing whatsoever. Basically the idea is +that this makes Windows act like Unix with respect to ANSI escape handling. + +It's safe to call this function multiple times. It's safe to call this function +on non-Windows platforms, but it won't do anything. It's safe to call this +function when one or both of your stdout/stderr are redirected to a file – it +won't do anything to those streams. + +Alternatively, you can use the older interface with more features (but also more +potential footguns): + +.. code-block:: python + + from colorama import init + init() + +This does the same thing as ``just_fix_windows_console``, except for the +following differences: + +- It's not safe to call ``init`` multiple times; you can end up with multiple + layers of wrapping and broken ANSI support. + +- Colorama will apply a heuristic to guess whether stdout/stderr support ANSI, + and if it thinks they don't, then it will wrap ``sys.stdout`` and + ``sys.stderr`` in a magic file object that strips out ANSI escape sequences + before printing them. This happens on all platforms, and can be convenient if + you want to write your code to emit ANSI escape sequences unconditionally, and + let Colorama decide whether they should actually be output. But note that + Colorama's heuristic is not particularly clever. + +- ``init`` also accepts explicit keyword args to enable/disable various + functionality – see below. + +To stop using Colorama before your program exits, simply call ``deinit()``. +This will restore ``stdout`` and ``stderr`` to their original values, so that +Colorama is disabled. To resume using Colorama again, call ``reinit()``; it is +cheaper than calling ``init()`` again (but does the same thing). + +Most users should depend on ``colorama >= 0.4.6``, and use +``just_fix_windows_console``. The old ``init`` interface will be supported +indefinitely for backwards compatibility, but we don't plan to fix any issues +with it, also for backwards compatibility. + +Colored Output +.............. + +Cross-platform printing of colored text can then be done using Colorama's +constant shorthand for ANSI escape sequences. These are deliberately +rudimentary, see below. + +.. code-block:: python + + from colorama import Fore, Back, Style + print(Fore.RED + 'some red text') + print(Back.GREEN + 'and with a green background') + print(Style.DIM + 'and in dim text') + print(Style.RESET_ALL) + print('back to normal now') + +...or simply by manually printing ANSI sequences from your own code: + +.. code-block:: python + + print('\033[31m' + 'some red text') + print('\033[39m') # and reset to default color + +...or, Colorama can be used in conjunction with existing ANSI libraries +such as the venerable `Termcolor `_ +the fabulous `Blessings `_, +or the incredible `_Rich `_. + +If you wish Colorama's Fore, Back and Style constants were more capable, +then consider using one of the above highly capable libraries to generate +colors, etc, and use Colorama just for its primary purpose: to convert +those ANSI sequences to also work on Windows: + +SIMILARLY, do not send PRs adding the generation of new ANSI types to Colorama. +We are only interested in converting ANSI codes to win32 API calls, not +shortcuts like the above to generate ANSI characters. + +.. code-block:: python + + from colorama import just_fix_windows_console + from termcolor import colored + + # use Colorama to make Termcolor work on Windows too + just_fix_windows_console() + + # then use Termcolor for all colored text output + print(colored('Hello, World!', 'green', 'on_red')) + +Available formatting constants are:: + + Fore: BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, RESET. + Back: BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, RESET. + Style: DIM, NORMAL, BRIGHT, RESET_ALL + +``Style.RESET_ALL`` resets foreground, background, and brightness. Colorama will +perform this reset automatically on program exit. + +These are fairly well supported, but not part of the standard:: + + Fore: LIGHTBLACK_EX, LIGHTRED_EX, LIGHTGREEN_EX, LIGHTYELLOW_EX, LIGHTBLUE_EX, LIGHTMAGENTA_EX, LIGHTCYAN_EX, LIGHTWHITE_EX + Back: LIGHTBLACK_EX, LIGHTRED_EX, LIGHTGREEN_EX, LIGHTYELLOW_EX, LIGHTBLUE_EX, LIGHTMAGENTA_EX, LIGHTCYAN_EX, LIGHTWHITE_EX + +Cursor Positioning +.................. + +ANSI codes to reposition the cursor are supported. See ``demos/demo06.py`` for +an example of how to generate them. + +Init Keyword Args +................. + +``init()`` accepts some ``**kwargs`` to override default behaviour. + +init(autoreset=False): + If you find yourself repeatedly sending reset sequences to turn off color + changes at the end of every print, then ``init(autoreset=True)`` will + automate that: + + .. code-block:: python + + from colorama import init + init(autoreset=True) + print(Fore.RED + 'some red text') + print('automatically back to default color again') + +init(strip=None): + Pass ``True`` or ``False`` to override whether ANSI codes should be + stripped from the output. The default behaviour is to strip if on Windows + or if output is redirected (not a tty). + +init(convert=None): + Pass ``True`` or ``False`` to override whether to convert ANSI codes in the + output into win32 calls. The default behaviour is to convert if on Windows + and output is to a tty (terminal). + +init(wrap=True): + On Windows, Colorama works by replacing ``sys.stdout`` and ``sys.stderr`` + with proxy objects, which override the ``.write()`` method to do their work. + If this wrapping causes you problems, then this can be disabled by passing + ``init(wrap=False)``. The default behaviour is to wrap if ``autoreset`` or + ``strip`` or ``convert`` are True. + + When wrapping is disabled, colored printing on non-Windows platforms will + continue to work as normal. To do cross-platform colored output, you can + use Colorama's ``AnsiToWin32`` proxy directly: + + .. code-block:: python + + import sys + from colorama import init, AnsiToWin32 + init(wrap=False) + stream = AnsiToWin32(sys.stderr).stream + + # Python 2 + print >>stream, Fore.BLUE + 'blue text on stderr' + + # Python 3 + print(Fore.BLUE + 'blue text on stderr', file=stream) + +Recognised ANSI Sequences +......................... + +ANSI sequences generally take the form:: + + ESC [ ; ... + +Where ```` is an integer, and ```` is a single letter. Zero or +more params are passed to a ````. If no params are passed, it is +generally synonymous with passing a single zero. No spaces exist in the +sequence; they have been inserted here simply to read more easily. + +The only ANSI sequences that Colorama converts into win32 calls are:: + + ESC [ 0 m # reset all (colors and brightness) + ESC [ 1 m # bright + ESC [ 2 m # dim (looks same as normal brightness) + ESC [ 22 m # normal brightness + + # FOREGROUND: + ESC [ 30 m # black + ESC [ 31 m # red + ESC [ 32 m # green + ESC [ 33 m # yellow + ESC [ 34 m # blue + ESC [ 35 m # magenta + ESC [ 36 m # cyan + ESC [ 37 m # white + ESC [ 39 m # reset + + # BACKGROUND + ESC [ 40 m # black + ESC [ 41 m # red + ESC [ 42 m # green + ESC [ 43 m # yellow + ESC [ 44 m # blue + ESC [ 45 m # magenta + ESC [ 46 m # cyan + ESC [ 47 m # white + ESC [ 49 m # reset + + # cursor positioning + ESC [ y;x H # position cursor at x across, y down + ESC [ y;x f # position cursor at x across, y down + ESC [ n A # move cursor n lines up + ESC [ n B # move cursor n lines down + ESC [ n C # move cursor n characters forward + ESC [ n D # move cursor n characters backward + + # clear the screen + ESC [ mode J # clear the screen + + # clear the line + ESC [ mode K # clear the line + +Multiple numeric params to the ``'m'`` command can be combined into a single +sequence:: + + ESC [ 36 ; 45 ; 1 m # bright cyan text on magenta background + +All other ANSI sequences of the form ``ESC [ ; ... `` +are silently stripped from the output on Windows. + +Any other form of ANSI sequence, such as single-character codes or alternative +initial characters, are not recognised or stripped. It would be cool to add +them though. Let me know if it would be useful for you, via the Issues on +GitHub. + +Status & Known Problems +----------------------- + +I've personally only tested it on Windows XP (CMD, Console2), Ubuntu +(gnome-terminal, xterm), and OS X. + +Some valid ANSI sequences aren't recognised. + +If you're hacking on the code, see `README-hacking.md`_. ESPECIALLY, see the +explanation there of why we do not want PRs that allow Colorama to generate new +types of ANSI codes. + +See outstanding issues and wish-list: +https://github.com/tartley/colorama/issues + +If anything doesn't work for you, or doesn't do what you expected or hoped for, +I'd love to hear about it on that issues list, would be delighted by patches, +and would be happy to grant commit access to anyone who submits a working patch +or two. + +.. _README-hacking.md: README-hacking.md + +License +------- + +Copyright Jonathan Hartley & Arnon Yaari, 2013-2020. BSD 3-Clause license; see +LICENSE file. + +Professional support +-------------------- + +.. |tideliftlogo| image:: https://cdn2.hubspot.net/hubfs/4008838/website/logos/logos_for_download/Tidelift_primary-shorthand-logo.png + :alt: Tidelift + :target: https://tidelift.com/subscription/pkg/pypi-colorama?utm_source=pypi-colorama&utm_medium=referral&utm_campaign=readme + +.. list-table:: + :widths: 10 100 + + * - |tideliftlogo| + - Professional support for colorama is available as part of the + `Tidelift Subscription`_. + Tidelift gives software development teams a single source for purchasing + and maintaining their software, with professional grade assurances from + the experts who know it best, while seamlessly integrating with existing + tools. + +.. _Tidelift Subscription: https://tidelift.com/subscription/pkg/pypi-colorama?utm_source=pypi-colorama&utm_medium=referral&utm_campaign=readme + +Thanks +------ + +See the CHANGELOG for more thanks! + +* Marc Schlaich (schlamar) for a ``setup.py`` fix for Python2.5. +* Marc Abramowitz, reported & fixed a crash on exit with closed ``stdout``, + providing a solution to issue #7's setuptools/distutils debate, + and other fixes. +* User 'eryksun', for guidance on correctly instantiating ``ctypes.windll``. +* Matthew McCormick for politely pointing out a longstanding crash on non-Win. +* Ben Hoyt, for a magnificent fix under 64-bit Windows. +* Jesse at Empty Square for submitting a fix for examples in the README. +* User 'jamessp', an observant documentation fix for cursor positioning. +* User 'vaal1239', Dave Mckee & Lackner Kristof for a tiny but much-needed Win7 + fix. +* Julien Stuyck, for wisely suggesting Python3 compatible updates to README. +* Daniel Griffith for multiple fabulous patches. +* Oscar Lesta for a valuable fix to stop ANSI chars being sent to non-tty + output. +* Roger Binns, for many suggestions, valuable feedback, & bug reports. +* Tim Golden for thought and much appreciated feedback on the initial idea. +* User 'Zearin' for updates to the README file. +* John Szakmeister for adding support for light colors +* Charles Merriam for adding documentation to demos +* Jurko for a fix on 64-bit Windows CPython2.5 w/o ctypes +* Florian Bruhin for a fix when stdout or stderr are None +* Thomas Weininger for fixing ValueError on Windows +* Remi Rampin for better Github integration and fixes to the README file +* Simeon Visser for closing a file handle using 'with' and updating classifiers + to include Python 3.3 and 3.4 +* Andy Neff for fixing RESET of LIGHT_EX colors. +* Jonathan Hartley for the initial idea and implementation. diff --git a/backend/venv/Lib/site-packages/colorama-0.4.6.dist-info/RECORD b/backend/venv/Lib/site-packages/colorama-0.4.6.dist-info/RECORD new file mode 100644 index 0000000..cd6b130 --- /dev/null +++ b/backend/venv/Lib/site-packages/colorama-0.4.6.dist-info/RECORD @@ -0,0 +1,31 @@ +colorama-0.4.6.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +colorama-0.4.6.dist-info/METADATA,sha256=e67SnrUMOym9sz_4TjF3vxvAV4T3aF7NyqRHHH3YEMw,17158 +colorama-0.4.6.dist-info/RECORD,, +colorama-0.4.6.dist-info/WHEEL,sha256=cdcF4Fbd0FPtw2EMIOwH-3rSOTUdTCeOSXRMD1iLUb8,105 +colorama-0.4.6.dist-info/licenses/LICENSE.txt,sha256=ysNcAmhuXQSlpxQL-zs25zrtSWZW6JEQLkKIhteTAxg,1491 +colorama/__init__.py,sha256=wePQA4U20tKgYARySLEC047ucNX-g8pRLpYBuiHlLb8,266 +colorama/__pycache__/__init__.cpython-312.pyc,, +colorama/__pycache__/ansi.cpython-312.pyc,, +colorama/__pycache__/ansitowin32.cpython-312.pyc,, +colorama/__pycache__/initialise.cpython-312.pyc,, +colorama/__pycache__/win32.cpython-312.pyc,, +colorama/__pycache__/winterm.cpython-312.pyc,, +colorama/ansi.py,sha256=Top4EeEuaQdBWdteKMEcGOTeKeF19Q-Wo_6_Cj5kOzQ,2522 +colorama/ansitowin32.py,sha256=vPNYa3OZbxjbuFyaVo0Tmhmy1FZ1lKMWCnT7odXpItk,11128 +colorama/initialise.py,sha256=-hIny86ClXo39ixh5iSCfUIa2f_h_bgKRDW7gqs-KLU,3325 +colorama/tests/__init__.py,sha256=MkgPAEzGQd-Rq0w0PZXSX2LadRWhUECcisJY8lSrm4Q,75 +colorama/tests/__pycache__/__init__.cpython-312.pyc,, +colorama/tests/__pycache__/ansi_test.cpython-312.pyc,, +colorama/tests/__pycache__/ansitowin32_test.cpython-312.pyc,, +colorama/tests/__pycache__/initialise_test.cpython-312.pyc,, +colorama/tests/__pycache__/isatty_test.cpython-312.pyc,, +colorama/tests/__pycache__/utils.cpython-312.pyc,, +colorama/tests/__pycache__/winterm_test.cpython-312.pyc,, +colorama/tests/ansi_test.py,sha256=FeViDrUINIZcr505PAxvU4AjXz1asEiALs9GXMhwRaE,2839 +colorama/tests/ansitowin32_test.py,sha256=RN7AIhMJ5EqDsYaCjVo-o4u8JzDD4ukJbmevWKS70rY,10678 +colorama/tests/initialise_test.py,sha256=BbPy-XfyHwJ6zKozuQOvNvQZzsx9vdb_0bYXn7hsBTc,6741 +colorama/tests/isatty_test.py,sha256=Pg26LRpv0yQDB5Ac-sxgVXG7hsA1NYvapFgApZfYzZg,1866 +colorama/tests/utils.py,sha256=1IIRylG39z5-dzq09R_ngufxyPZxgldNbrxKxUGwGKE,1079 +colorama/tests/winterm_test.py,sha256=qoWFPEjym5gm2RuMwpf3pOis3a5r_PJZFCzK254JL8A,3709 +colorama/win32.py,sha256=YQOKwMTwtGBbsY4dL5HYTvwTeP9wIQra5MvPNddpxZs,6181 +colorama/winterm.py,sha256=XCQFDHjPi6AHYNdZwy0tA02H-Jh48Jp-HvCjeLeLp3U,7134 diff --git a/backend/venv/Lib/site-packages/colorama-0.4.6.dist-info/WHEEL b/backend/venv/Lib/site-packages/colorama-0.4.6.dist-info/WHEEL new file mode 100644 index 0000000..d79189f --- /dev/null +++ b/backend/venv/Lib/site-packages/colorama-0.4.6.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: hatchling 1.11.1 +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any diff --git a/backend/venv/Lib/site-packages/colorama-0.4.6.dist-info/licenses/LICENSE.txt b/backend/venv/Lib/site-packages/colorama-0.4.6.dist-info/licenses/LICENSE.txt new file mode 100644 index 0000000..3105888 --- /dev/null +++ b/backend/venv/Lib/site-packages/colorama-0.4.6.dist-info/licenses/LICENSE.txt @@ -0,0 +1,27 @@ +Copyright (c) 2010 Jonathan Hartley +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holders, nor those of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/backend/venv/Lib/site-packages/colorama/__init__.py b/backend/venv/Lib/site-packages/colorama/__init__.py new file mode 100644 index 0000000..383101c --- /dev/null +++ b/backend/venv/Lib/site-packages/colorama/__init__.py @@ -0,0 +1,7 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +from .initialise import init, deinit, reinit, colorama_text, just_fix_windows_console +from .ansi import Fore, Back, Style, Cursor +from .ansitowin32 import AnsiToWin32 + +__version__ = '0.4.6' + diff --git a/backend/venv/Lib/site-packages/colorama/__pycache__/__init__.cpython-312.pyc b/backend/venv/Lib/site-packages/colorama/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f9c151f4b40f98829bc26641d5b8272a0321059c GIT binary patch literal 499 zcmXv~O=}cE5bfUSnf;jE97I9yUWVW%OpFH+As++}!H97Ynucbw)6sVOW9gpV&3f}! z_#6B!If|DCQ4kEd1#*#`Qf-ntysCPS?pIZ(gFz2L{QYUxp!kYv zRAYrSrdYRVOD8nZgc6<76i2P4GTo+a-Ju=brCr^l@FDPt%5|Uip(b>&OpELsd{B`F zB8_Z9R*ReLZt`Gkm35V_cq2}l@bJ^jH~d(h@P#zBU3fmW##G0X>VkPvVnXHub!X+?=BN5UFS%fw~AQilI zo!ECH#1pwZDtS~I3$tvLuK%Cmd@h`q)^Pp}T>^!!j(4835g2$@u9xM69T>6e<41C0sDX`TC;o03));NzFa6X(a uL+6FI^-PJE?mpPYv-(E>7YWAr42^!E(J!?69j*REkAJT`_>#MOpk4z2?vMZg literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/colorama/__pycache__/ansi.cpython-312.pyc b/backend/venv/Lib/site-packages/colorama/__pycache__/ansi.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3bdb63e6bf183579a59254d4326806fc17e9c4ab GIT binary patch literal 3952 zcmcgu&2JmW6`%d$_lHFKOLCgfvD1`^BiU}#rgBk-A}LuhMGB%+*BiQ9nmdtbQKUM% zwo6q3Xh4S;_CZC0T1Nx*A%-vgKXS1UBya}41xT?sJLDngsqf8_G%3_T(Yjq=e)Ha& z*_k(Qes5;J2!{g%zVCkc`zrSn@+~U8PwNWpuR*v=OrjH0(j`;YWmC}=Q{5)IYHEO* z88+S>1hi0Ji-H#JYa^fq`r2qSmOQZ83M{Qwt;Bl6yjG)$6m4*pMyOG#n)w*4+uYjf2V8R6L>(zR>W=#Z&lujj9ZF^&Ca+203 zZdBK*8`P|pCmL*J617Pj*PvFVyg>~dG_WZj{SeA!E_o|bcNJKvP%w1ulK^*#4d{M$ zH=u-Uk%!$sHlfLs5Q`)!=ee~0K;}xiIL8&sW=V;wVgcAY@sBI%snW7VnN>P->dcw7 zQlU;Wta_c6GSphL8yls?LUAEixOy!yOx#AGH40qiY*| zyh|v7(}BS0Ai8rL`!JsOJ$zBX93$ zPeu;!s=Ma>`Mw!xp;T}5*1_8L&76xpav}Lb0C59C(6)^U{UcR+|2Bv{M_rk7Aa4UFC8EO@31!@gy z6>5*^gPQ_whNdU!=K&FjYs_k}N^d-z;NMBA{>Edz4;^_aH>qUyI<#=9ZsE|qU67X- zHp9=SomgJLNc4`QXza7%?&zn#xwW-h*^3@~hf`cxC=@p%1A7Si zJK&0S8~|>Vee}AY{#^R&%wF`Z&x?D}Q;&S7x*04vcn&6ImV!z^(#L*`vfu+=gX|On zrXKqR!W6>$2x6CzEpA$iXd#?{VqubFT1(pNZFLAbpq_S99eWR@dhb+jFF?ycs$-hV zkm3rYw+gAP>0Z;L`%JIyH+_1*^y@)0poh$$9yUXI#0=|EGop`}QGL`L(PQSQ9*3t_ zocl0hGYv+aS78F@HG~AhF$BzF2LtHf5*$od2jk%A2p=Mp5H2J94#7b9Jwh2E|KPyB z;Bjp_2Snn^Vm8CI*~M%&&pns2xm@8QSEqB!S?--r&1UmUDXyk3rSe?6cz$jv%eBR9 zF}uXWxw+Z%OJWEk`&%9qDh!2++a`uYH6q&Fp-~TYe_hU^78P1|s^`r(C2HYaBp~W=3EFEOLgT!{;LO_B#ClN5Y96U>%NdydqVyOV74aQwK~%>us$&>cSL#I-=la)CeFa)xoNP@k>2Y6G zMY~y};*@akesJ)u=s+R)q<25@J=2TGU9M#2=D8VF`ty!7SzcY_Zo)Ts2B$GfX*Ta__`L)CGpl4uUhf6 z+z`Efk(A zk|aG-6-j*>Al^tzdF%-z1X{}X9!WZeaH5TpfR4{6P3?F(1gg%VfOLB2P=`R(8IMb2 zpENrJs?N!{H15jdos+5*+wpe@RL?>r5W79zQor$!x>fA<(U$g&KYsg_n;sFXe*y>- BJ0<`C literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/colorama/__pycache__/ansitowin32.cpython-312.pyc b/backend/venv/Lib/site-packages/colorama/__pycache__/ansitowin32.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..72acdc1b69262efb282dbb1474561ce2f3bc7a9b GIT binary patch literal 16419 zcmcgTe{2-jnKS!)y<_j%>t8Ik8H0Z<7(;+S0tVurKrklQP9ToMcJYj1&Hiv^#(5ilgf^zp)u!dj(o)5~PyrGWsjj+G<^IU&PP$!;YiEkCky^Eve@+f?Qd*sK_kC}6 zX4mVn&s9$Mq!z;14aEFZ`5K=UOf2;T#Qp3 z#nC~kTluHEX>xDqHgE>c7&L}V-KLPa+Z?iVTSC@uYsl7ZqbY!yg7#2WcUH*J?Fcd5 zOeniMo3xvQIU#4aGvw-a!9Cq==bc}-8YtfJVe+xvb_2DK;w*1doR!c0(5N(b=aE($ zwA#~J-9xlD>vKeD|D1-}YnE*dVKLAe5qRaQ(cgPowqskTG!*1zv+`$bY-#hFP2}T5RMS6M-vgK?b%mst81OEL30iVQ+ zQm-;hr8XpQp1cGX;}lOJ*MMVmw~;fvO?8_%Bh+Tj1hs`TLv6+P?Y41NsO=oQWp@^5 zhuXn2T-Mu^#+&RRhnJDFJ0*elhmH#VfdO6^zMI8D!8?)lvm$}9HR53JDb_E-Jr^02 zytS;qSAv(rCO<0){;)XU7x=Km!i%39V*4Tj>kkGADZeBMffIug4}Fj)tRGM%woizJ z*bpzBig0Z8Ss@_tHQwr4_Ux$uJSiZu93SLQ`X!!Yr3f1t6bP-RNcapdNW8!X!lL94 z_wse5y*D|rgjL8eynn(%HBLq8DCL7Ir9=&Ihm%Xn5H&@&!z2{>7BIo*J4?91$*VE} zy~+q8g4ZaUL_XLjTUA_p62=Q6J|4LEmq63bo|i>v=-IM)%a+qUhr@ic5IDp4H1pzV zDKgO0ak%rPww|**fBM-TAtDY0pY1sTGRB9wo-=&-Oix?jM2`r(**E~L{*%1e(~A=1 z5BWC%&jV5fq-N`ux`83t=JN%@0m~b!vMdj7fAub%C08aamR<#ukUqmqdiIugV;|1}XvEikr+@QZlYp+7yK(_mQAmO~=^Gz9(FXIXd#DJ-=QLdU%>Amw8&(Aum6VB?%{J8VE+l2||b8*{q z|35DVqQjp<(GkjVU`gRs-lGy)7E6?Zjxe!|yvCffN_~l{gtKbW6nE~pZAmzH#BDp2 zmq-^Hye7hhl9H*RLy7=R(J0bfpclra3Xd6d9_(Yf^e{f3$V;Rh#K)7#@D!{D2WwXb zTUl6lWL^$n25>O2NQWQX&J@1!~Ue zesARBNZeMkm{&L+GA2cm^~cnY7#RgrGN}4L^UL_-2&wlTA|;)Jbu)>f9Vl}$)9wu;3Z)y&8P=(H3^M`(_gH2LVqJ{jc< zB~(Z0uUAHC$)bY#ZR%C(e~=RM7T}P;Bn8K-K}w*940bSC{mA`{GGYK*VNhLUC$)}} za#WNGN-)yYtJIM3EOpNKDs`6jn%d=@mtJk!-_UW$xBqZwS4(qOtJkL33qwSdtzg6h zLL@93#UWA70%0W%)aOfH^8%O?*%A=JP!7pC4XUqf5d?HGikY#9#0$&W%D+#+UZ|(f z!yt$A7fzXi_Y6S96HvjNlJ@+kXLxDD1opG+85}+UTDZI;L(Yz3hvAmQbK&_Iw6f%C>_R|{6v=#_-5wQMBJLLV-2R)i=v z5Da4M92j65+B*-hy{G&FM9jPr#ftnJgFM8pq7np4r+5}kFa*_Mjt%rdv?~n^N+iC9 z*cak!X(&lD8DX-}B?KX`6d}VSF(BJF7>1Y}M$rqAx2VL$!zJ|I)jhA()a>2a!$o&_ z*L!PT^KTq(*x3EL*RXdu7oo4$yms9BIzX(@)ZUAclUg)gg?U)yr=zCyNLteRVZ5yd zgMgt503~VmT6fav)8L^;%u(|>TF9a)DO(+cYKuoK#3o==mr*nfYt+n8=V;LZ{W0hy zC2CbgWyA*FQ}Z7xoTB>CDP|O;BY0?x0rYwlWuU{YHVS*x0)4?#L~RT;k`*;xutu|B zRM=vN7Gu;1e9?SQ)NsLqaKV7^5d&GFXm1bCFJ1asKu6<;eqQ(B05Z=#+ zMw^r&^meGhq<}p&<05;+`YLtl=c-Nh8rx+SEZwek%wnxI~SmDy^ATE=POLz$%a2TsL#LfaNpobbN=POSUVH`eja9|(; zi%L#5^l@?_IBJOx`A+#ou*woF)_l0ql5MB_aEV^p8RmJ;mm(lKfI6)9)S?(!w9~`+ zX|_aLh#dilXa(~H{-dZ2mSGI8$JXI`4BSRhMQq<>*L2|)xOe=aplJN)<)bmvW#4Gl zd=|y7f3RlP&C?%-AXJ<;814CUxy9(wr*q3k8-YsI=2+Q-@`Dez?)$_rz4c(+Rt6q? z{LRa6&K7wSMc%mE`@r2e$=y0Vb$Yh$g+$#8({+ubwmDDT1J9xOjzjUShen-1hRGe> zJ(s`kLH^ds=VH;(mbn5Cj3x^q?$Nz-g_REqw@lWI?wiwwU&79=-jrCqX?pcDqo#+p zVtk{rYb94oZn|%IrabXgTOs1k`SPika;-v-2m^P&(}+GXKN&R`Tuoc3kGD9QDdWd` zX{Z-O4HyZaC3(^T)lyLd=$N9hI&lNQ7^2Nu>;Qz4rIYf~{(hJcVoh-xyM#d=EwOY8 zb|QL%e%Q5u3$Wnekb^@k3INa5u?PCtK7UZ;YtbNwu}a!*jgS(tDgGcFk=PTk3)0ue zgDc=_*)Z&q5Ko~Pa3bZ15fH^ego}!K#{rQ&2HbE_;zt|}lG8>cfJ+GoIHoQfGNF2s z5Ay;U?+IQTP%DlXeN{LT-gs2e26iCmmte~#1fFX!9K=1E2vJdgQ1dGOU_csTgMrg2 zQkvGYperzL-~bK-_OD>mW)SzjSY>65J2<#EQRCHy0io?e?G$QZGSb&k4)IiEFvyXe znBk&yJxT)%VJ8+USV+4lSN?m^i_r(pT@w<FXrEyLbYG7b2jeSK*Zgol`jw25MjiK!GKz#tc2e~ElCh_#<6crmSuu5;z8Tap zIL|06rmoXBgF2f*8g5riU8ipbb)6Vt#ng5BW>ByA3S-yln?b$mD^SobVM?TYE^=ueXV9+j$|)lZ}Uf{K^=UtR--5c_t|P%KrmoXBgF2gf zXZ32u)OGr1P}h;&6;s#gn?YSia#u`Ur*8&z9l2dGb)CK$)R*@dFQ{{o`cIQc9f{AN zzP!iKp-wzTN}`wd7&`saMyC^LqCQZul;$5{ReI+}w|NTa^IzgV8Sj^<=gU*20RPhCfIGN>=_E0(9Oqd7=DVEP%H z=SodfvZ%XtaGHlR;$2JDqi~oHyQ+|^Ay}YMws*92wsiR#+S+70+28WPa$2@Db{yEZ zze|Pn-3h4E$xRp4mGq1CTuY`wly>zlufX%<^^1A%EpeCX4$;2qot)? zw!GTX)^_-)Y-((Kxka`fYS`D(-qj$RnqF;am(54_ALwe4O@R8UY$junv)k~Qgr=|M znCu|8KoD;f7$Jwmm&-cX&N^T@So*0nC-T6g2*Y}JlL z)sA@O&UqsM{(t~B;bL#>_+a<--FIv5ZMw55zP54R3_v_s@r-9*&c0#&Ap3gu&2zWj zntCg~X79Wefi?i@_q8K9i^^R!o^v_pM$rc)*Gr)9`Kj}9cF(*6feZqf%goiY*P>UV zH;>)wnd*s`?VQg>V9pXfod|Rx(0SQ;qxyr|>$P`n_ndc}@$whua}k(_KxMqlb>`-& zTcN2?d`@y9CXBzNr3lO1jiQYvBEJk4Z>x@i|#M#~Rs}Sf} z0F1Mn=T~EM33*~w!c}#%=vK*8$=!4J&fhtIUy9eX&6grV89}H>xGHX({UCZhdiU79 zo;yAFx5caW&#yrQb{Pugh_IF*R3}{3H>+>ePSyU>_ABQvoS)>!z3pGDLxc)~P?>O5 z-n8CgrkJ~@?uG7z?svtjU!1Q*gernilW^7C+;OXZs{WV7v(Fz$Jb&PmZSnOl%~vBz z%`!B+h_Id@EO^n8J0thGc+J824Tw++2n)EE6o!omtV5uVFl<8L<|TSQgTO5a)DecQ z2;7E19btGDf!hJNlrZc-gy)v%{X7D9B2Y&db|J8S0T6{@H#YAfPh7wwO&Inf!V5IP z(3ge=8c`Y*6n!F11f^L)(U*u8g3_v>=*q++SMjWC31J|xrF$(Hl{)=j9KuJ=Q`Oly zPhX;8*YMplqse3t0~jl{;O3yRK?oO1Z4inK9J{3VO7<4=pj|r>Q%RCMDJ>}@{4C(0 zpUEiwcrcPt(vvxs=!HHeqo_`fY<%l%CknYhOFKYHbx!pg(o#ok%1H|D+RC{k83fKn z)MF4yIdIv8KyzPkP&`GBT!gPdgMg9Xf}?dr8_rGl8HC;~#CsVk#Z&BjXXixzwUQr} z%rUN6W^IC58{0O+)O^Oc-fO$qHp`SH7|1$#$W#D4)$)*G(ar36XAd^FUu>UYO6H9e z<5|1|jBc7t@FTcbYJvqfun4g-3P-~+b#me{zXq_7UPcicmY6KkTUmP#r6jk+ZRmX)xm3TU3qJU*#z@exnnFjbLmQk!y+?R3vUWZ#Wb9nQh0!qSyE~< z0;ke?in_d#HdC*|i{OcEKRz>~sA|#!V;eES*)^rFx^SXvQd5sm5(oL|9F6rRlvkc{8(5XouK$Sj-9pq?Yap;_`=7inne3vf^cSr!_pw9ExO^dj=w z?zPE|WM5xI?1lUc$f)o&!LOr5w)Mdg7QBW4$+!dlu738zB)_L=%m}NhYicZ^Hd> zX}ahyGKcp8MI40+&ZQVC&kY$@PWP;HO~Sb*W}0?Zj+*8QR?QYvCJHKN3+fUDb(7L> z3bw&P>#DMAo-3Xom0Wyrv}J57sKqQ(o?yyj6_b|R=7$U@O6h3xEK{0bN+$*}PW{pO z1XDLxP<*j<-cA)h3unak>{(lB!d5!L#aeGR-8OxAV8*sxv3}_m3Y`dny;-8Kjw4j%8f~YVooGyX5g`f#fZQ$285VGYgiBa` z7b+3oA~hS|hP&aC#j}wTfjD-;#Wva_*Vxu~b}cYB6H=^Ya^1vR51CC1+GiMc-b^t? z3hUBc01kk#t`9DjbR3nyjPzcBiv?Jw!oyZ4?^!|`2 zTmZ63Udaxn4b&AsJ?M>uLg1xki_)6Gy6-^0;o@}GrR&OX04m}xQOb;?%+@3dY9@Dkn=$Qy3H~@kRGqe_IgYu zI5!~d8Qz#KEepl4u09w611|2V)6oA7=!#WP{X6yL1uE`2mS{NoQNxYS$=sj5GWo_& zUc0(=;*G1@Z~LcL?*Pc3iFkgavYM9ZU7wR!1=6UXw?1o76*Shsj^1*t5$Q{Lddx{O zh6TpZgfRxi=Lq9KT(|;NIwORu(C}BX;P*(Q9I7M>jwCiT#Qgu*`AP1_uYB^x$Aksf zwnO8eMT`l*;jW^8;HpwWHQD&$!I1D4G|Q%j#-?WYvAoHdg$?pT2 za2c!jp~}$oF=!h0EIoG^0gFF|3UxhijJvq^QGqAnId*^bY(qz)p(Eb;%EN}E)1G6~ z1;<8PALSK{^}W9#Mt^_PXRFr4Dz21{S)Q6HccIey{wBx|brp_gKh32IS0_A2CU?zl zs84LD|ETlfhK6a+k?DdXK*X6hw*B2VC;ShbYd&*(CisMV-CSw;SSx-J0iEZqRAFh% zk|?Mmt)Dpy)J2*mCpd=vdMC;n428iAEqyA&Iot{TK1L-E0aG3^VGE3Bm z>02YFsEIR>D>GafIm$zgSkmN3H|D=-(kv8wiWW6TE$}^w6~89|6?_pS4M%AP3s9NL zUe=B0;G;NvHjEI>K}Lb6poTyps}Gv9WKeV{(DXX`*HN?r#kFZ;)QL{PnXPPeXaV=C z&mXaIhN#U!^}%?ewm$fA2CN;BZ3u1ltEMQ8Z%*QB`$$&W7_|5{^|m3V(yJ>rlbBd~}0MH_CLAOgBS5e+NQ_utId&9%WlYo^eOSAZy*9+X+f5uoSkg&bNz#&q~<9Stwn{E&BR5^ zc1+{-k?)F3cqy#K2d+a5IxN%YWO_(H-|zyU3>T)Wcxr+79{>}}z{@G>-TTg-->zCS zW}b5wPc+Y#)Fw)5AGmAh*os+pbAsJ`yCA{t7&`#phQ*FtsUK@57qO0s-DAy!yKK%?IQGV6`)I>wp4AiniH?b)NqX{`*qPf$KB8~8-hbx)+WY?dMG5zT zPpT8{j*HEs4Wn-mk|dxmj~%&Paj)(U5G|i!8X$PiS)+t5Nwor&DW8#{2tC;k%v&nb z(+gZu{uj*9H^G!ZTCd(xQw@WOs2joHz_*ry2S<#}+ zT{K~tC>X1cRm8-Y6kDHg*N!&Nt*iL}Hu!(K2Xtce;6%}!v+(M=chAqc%Vymb33o-T zbK32lJTmRBn=7rEEv-wG)=i4jrCW(VEH0byUml7zKPaksRJ>-k*qbQ!PFCH{o$}5U zZ<{Z|bsu=#{85J@!7yO0pfnQ+#`D0xMuJtzMAMo4qElI(;mT~$b`Ul$+|nbvfceO~ zJb(f3Y|MMiMfhgSldySal3%*P&QyD=H(zK#nvGaBVbu(kY=DohaRD;`iQ~dIvH2cW z=oo|^td3xXdx^r=u)<}z@NKMcT_a$~Lsmut&MsL`3axnM!3r}71qct63NJ*A1Crmt zz$)5ZI<|Iv{pI!X($?v`eHRYS<&~%n_0xH~FC2VgsxohT{1R<5*FVl*Z!Ua%jJCoz zGWjO+=EphN<{gh&qq+PsV}x&M7$<-$+~!95ac#Ca{|O5p(Wsof6e1?!yA p9yb6@4;kswv8w;1@SnWs{{T!0Sit}Q literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/colorama/__pycache__/initialise.cpython-312.pyc b/backend/venv/Lib/site-packages/colorama/__pycache__/initialise.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c925d7905261b7cffb25c77ccf2c49d8edd0b15f GIT binary patch literal 3557 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
nk@Ni^smX$sx+2rni0z1Wu?xjby7+F5?6| zFh%Tj$^qtBr$$SZ$#CWhSmZOjEmAn>L4==1^_HXzi)~YmMWM)I)=9D;oZ&Kp#Qw}- z-nk*-Kmea?TvSgV{ z!S{tVg2^}}R>Ta08lves)0{ilGtf)92n1G&9R|_(rcLv;-G67@cOWZnG`Hh9ab?fa z`z!B#5nc`de9!9pYfW#ii47F43`4ISJpG%x--;vOTt$d4)YcCHkDqI61N)(ik!*46 zx$DQWIhWz=Y;J37dr2E>7PgKWAt556d%XI}c__PFn!{yFg*3Mkcor!4hX^E_fjc_#k?6r^I*l1|Z zHFRkWUD>xcnh&fU?A4lkZ-+K2sz1B%@x+scmgUB!#`_mm*!70}DDmodv>mt|qFdbW zF(%umiThS|J@h?H{%ZP>c%hhA`}Zw>-Ln2#&#z9dja_~uzMr4T?>*Hy&we-xt{i=M z^s(poQ=ah{_sFs07{fxxKl#5vM-w}a+oKspIUD4$!!G*~>?A1`3CT|^Eb1v*l{VN1 z_qX;~YlBit%Hw!!m7AvtIv#Q)Y@UQmlLmlwlIA;bTVVdajo0Q2}#%p(z4*#S>! z2!mlgL0lt$goMU1Q7lowyMiT*8Yyh$V;dqN<1`Ws_=$|n3178yHq@1oX z!3n8NFy72vnE+rbqAw&e;1pvDAa49|_*}kRc>^1UEwJcd>LC$uyD#l364rKl{Cc zJS0u<=11`g#g?ac}K_UUa;l-2D*?0tg!c*z*`+DV| zb@6i!0x7++;Q6%vaxm1>I~Gc-DWv1d3k9vnS46oSI}(UHF3*w|2Lkf23%*Z9J$ zZ2VursXL}51KcEN+If*tD<`8@;Me)}_F88*ZsjA!20if{n_FT*YYmmh~?-%}^!Iq}stoa<{p zpI9q@=^4ZFb-#lLJ0bs?{xtrVJqLUJ%&-04-u=#B2UwsX_}79kqg;=Xyi&`DW@b}F zrP|Pq>o#3TU740+s_`F!R(MOg^5~0~tV>;d)A$F&N%F@a2evm3t1t(aeadlc=f7}m z|LI}a+HFB(tFqU(8OXMGIoX%64B57O%)z#2r?wf)w-Q`6Tldw|%RD3co-q!#bKAl4 aoll)m`dUFZ{zy2?{H=J>`H$>L=YIhWOq{C# literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/colorama/ansi.py b/backend/venv/Lib/site-packages/colorama/ansi.py new file mode 100644 index 0000000..11ec695 --- /dev/null +++ b/backend/venv/Lib/site-packages/colorama/ansi.py @@ -0,0 +1,102 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +''' +This module generates ANSI character codes to printing colors to terminals. +See: http://en.wikipedia.org/wiki/ANSI_escape_code +''' + +CSI = '\033[' +OSC = '\033]' +BEL = '\a' + + +def code_to_chars(code): + return CSI + str(code) + 'm' + +def set_title(title): + return OSC + '2;' + title + BEL + +def clear_screen(mode=2): + return CSI + str(mode) + 'J' + +def clear_line(mode=2): + return CSI + str(mode) + 'K' + + +class AnsiCodes(object): + def __init__(self): + # the subclasses declare class attributes which are numbers. + # Upon instantiation we define instance attributes, which are the same + # as the class attributes but wrapped with the ANSI escape sequence + for name in dir(self): + if not name.startswith('_'): + value = getattr(self, name) + setattr(self, name, code_to_chars(value)) + + +class AnsiCursor(object): + def UP(self, n=1): + return CSI + str(n) + 'A' + def DOWN(self, n=1): + return CSI + str(n) + 'B' + def FORWARD(self, n=1): + return CSI + str(n) + 'C' + def BACK(self, n=1): + return CSI + str(n) + 'D' + def POS(self, x=1, y=1): + return CSI + str(y) + ';' + str(x) + 'H' + + +class AnsiFore(AnsiCodes): + BLACK = 30 + RED = 31 + GREEN = 32 + YELLOW = 33 + BLUE = 34 + MAGENTA = 35 + CYAN = 36 + WHITE = 37 + RESET = 39 + + # These are fairly well supported, but not part of the standard. + LIGHTBLACK_EX = 90 + LIGHTRED_EX = 91 + LIGHTGREEN_EX = 92 + LIGHTYELLOW_EX = 93 + LIGHTBLUE_EX = 94 + LIGHTMAGENTA_EX = 95 + LIGHTCYAN_EX = 96 + LIGHTWHITE_EX = 97 + + +class AnsiBack(AnsiCodes): + BLACK = 40 + RED = 41 + GREEN = 42 + YELLOW = 43 + BLUE = 44 + MAGENTA = 45 + CYAN = 46 + WHITE = 47 + RESET = 49 + + # These are fairly well supported, but not part of the standard. + LIGHTBLACK_EX = 100 + LIGHTRED_EX = 101 + LIGHTGREEN_EX = 102 + LIGHTYELLOW_EX = 103 + LIGHTBLUE_EX = 104 + LIGHTMAGENTA_EX = 105 + LIGHTCYAN_EX = 106 + LIGHTWHITE_EX = 107 + + +class AnsiStyle(AnsiCodes): + BRIGHT = 1 + DIM = 2 + NORMAL = 22 + RESET_ALL = 0 + +Fore = AnsiFore() +Back = AnsiBack() +Style = AnsiStyle() +Cursor = AnsiCursor() diff --git a/backend/venv/Lib/site-packages/colorama/ansitowin32.py b/backend/venv/Lib/site-packages/colorama/ansitowin32.py new file mode 100644 index 0000000..abf209e --- /dev/null +++ b/backend/venv/Lib/site-packages/colorama/ansitowin32.py @@ -0,0 +1,277 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +import re +import sys +import os + +from .ansi import AnsiFore, AnsiBack, AnsiStyle, Style, BEL +from .winterm import enable_vt_processing, WinTerm, WinColor, WinStyle +from .win32 import windll, winapi_test + + +winterm = None +if windll is not None: + winterm = WinTerm() + + +class StreamWrapper(object): + ''' + Wraps a stream (such as stdout), acting as a transparent proxy for all + attribute access apart from method 'write()', which is delegated to our + Converter instance. + ''' + def __init__(self, wrapped, converter): + # double-underscore everything to prevent clashes with names of + # attributes on the wrapped stream object. + self.__wrapped = wrapped + self.__convertor = converter + + def __getattr__(self, name): + return getattr(self.__wrapped, name) + + def __enter__(self, *args, **kwargs): + # special method lookup bypasses __getattr__/__getattribute__, see + # https://stackoverflow.com/questions/12632894/why-doesnt-getattr-work-with-exit + # thus, contextlib magic methods are not proxied via __getattr__ + return self.__wrapped.__enter__(*args, **kwargs) + + def __exit__(self, *args, **kwargs): + return self.__wrapped.__exit__(*args, **kwargs) + + def __setstate__(self, state): + self.__dict__ = state + + def __getstate__(self): + return self.__dict__ + + def write(self, text): + self.__convertor.write(text) + + def isatty(self): + stream = self.__wrapped + if 'PYCHARM_HOSTED' in os.environ: + if stream is not None and (stream is sys.__stdout__ or stream is sys.__stderr__): + return True + try: + stream_isatty = stream.isatty + except AttributeError: + return False + else: + return stream_isatty() + + @property + def closed(self): + stream = self.__wrapped + try: + return stream.closed + # AttributeError in the case that the stream doesn't support being closed + # ValueError for the case that the stream has already been detached when atexit runs + except (AttributeError, ValueError): + return True + + +class AnsiToWin32(object): + ''' + Implements a 'write()' method which, on Windows, will strip ANSI character + sequences from the text, and if outputting to a tty, will convert them into + win32 function calls. + ''' + ANSI_CSI_RE = re.compile('\001?\033\\[((?:\\d|;)*)([a-zA-Z])\002?') # Control Sequence Introducer + ANSI_OSC_RE = re.compile('\001?\033\\]([^\a]*)(\a)\002?') # Operating System Command + + def __init__(self, wrapped, convert=None, strip=None, autoreset=False): + # The wrapped stream (normally sys.stdout or sys.stderr) + self.wrapped = wrapped + + # should we reset colors to defaults after every .write() + self.autoreset = autoreset + + # create the proxy wrapping our output stream + self.stream = StreamWrapper(wrapped, self) + + on_windows = os.name == 'nt' + # We test if the WinAPI works, because even if we are on Windows + # we may be using a terminal that doesn't support the WinAPI + # (e.g. Cygwin Terminal). In this case it's up to the terminal + # to support the ANSI codes. + conversion_supported = on_windows and winapi_test() + try: + fd = wrapped.fileno() + except Exception: + fd = -1 + system_has_native_ansi = not on_windows or enable_vt_processing(fd) + have_tty = not self.stream.closed and self.stream.isatty() + need_conversion = conversion_supported and not system_has_native_ansi + + # should we strip ANSI sequences from our output? + if strip is None: + strip = need_conversion or not have_tty + self.strip = strip + + # should we should convert ANSI sequences into win32 calls? + if convert is None: + convert = need_conversion and have_tty + self.convert = convert + + # dict of ansi codes to win32 functions and parameters + self.win32_calls = self.get_win32_calls() + + # are we wrapping stderr? + self.on_stderr = self.wrapped is sys.stderr + + def should_wrap(self): + ''' + True if this class is actually needed. If false, then the output + stream will not be affected, nor will win32 calls be issued, so + wrapping stdout is not actually required. This will generally be + False on non-Windows platforms, unless optional functionality like + autoreset has been requested using kwargs to init() + ''' + return self.convert or self.strip or self.autoreset + + def get_win32_calls(self): + if self.convert and winterm: + return { + AnsiStyle.RESET_ALL: (winterm.reset_all, ), + AnsiStyle.BRIGHT: (winterm.style, WinStyle.BRIGHT), + AnsiStyle.DIM: (winterm.style, WinStyle.NORMAL), + AnsiStyle.NORMAL: (winterm.style, WinStyle.NORMAL), + AnsiFore.BLACK: (winterm.fore, WinColor.BLACK), + AnsiFore.RED: (winterm.fore, WinColor.RED), + AnsiFore.GREEN: (winterm.fore, WinColor.GREEN), + AnsiFore.YELLOW: (winterm.fore, WinColor.YELLOW), + AnsiFore.BLUE: (winterm.fore, WinColor.BLUE), + AnsiFore.MAGENTA: (winterm.fore, WinColor.MAGENTA), + AnsiFore.CYAN: (winterm.fore, WinColor.CYAN), + AnsiFore.WHITE: (winterm.fore, WinColor.GREY), + AnsiFore.RESET: (winterm.fore, ), + AnsiFore.LIGHTBLACK_EX: (winterm.fore, WinColor.BLACK, True), + AnsiFore.LIGHTRED_EX: (winterm.fore, WinColor.RED, True), + AnsiFore.LIGHTGREEN_EX: (winterm.fore, WinColor.GREEN, True), + AnsiFore.LIGHTYELLOW_EX: (winterm.fore, WinColor.YELLOW, True), + AnsiFore.LIGHTBLUE_EX: (winterm.fore, WinColor.BLUE, True), + AnsiFore.LIGHTMAGENTA_EX: (winterm.fore, WinColor.MAGENTA, True), + AnsiFore.LIGHTCYAN_EX: (winterm.fore, WinColor.CYAN, True), + AnsiFore.LIGHTWHITE_EX: (winterm.fore, WinColor.GREY, True), + AnsiBack.BLACK: (winterm.back, WinColor.BLACK), + AnsiBack.RED: (winterm.back, WinColor.RED), + AnsiBack.GREEN: (winterm.back, WinColor.GREEN), + AnsiBack.YELLOW: (winterm.back, WinColor.YELLOW), + AnsiBack.BLUE: (winterm.back, WinColor.BLUE), + AnsiBack.MAGENTA: (winterm.back, WinColor.MAGENTA), + AnsiBack.CYAN: (winterm.back, WinColor.CYAN), + AnsiBack.WHITE: (winterm.back, WinColor.GREY), + AnsiBack.RESET: (winterm.back, ), + AnsiBack.LIGHTBLACK_EX: (winterm.back, WinColor.BLACK, True), + AnsiBack.LIGHTRED_EX: (winterm.back, WinColor.RED, True), + AnsiBack.LIGHTGREEN_EX: (winterm.back, WinColor.GREEN, True), + AnsiBack.LIGHTYELLOW_EX: (winterm.back, WinColor.YELLOW, True), + AnsiBack.LIGHTBLUE_EX: (winterm.back, WinColor.BLUE, True), + AnsiBack.LIGHTMAGENTA_EX: (winterm.back, WinColor.MAGENTA, True), + AnsiBack.LIGHTCYAN_EX: (winterm.back, WinColor.CYAN, True), + AnsiBack.LIGHTWHITE_EX: (winterm.back, WinColor.GREY, True), + } + return dict() + + def write(self, text): + if self.strip or self.convert: + self.write_and_convert(text) + else: + self.wrapped.write(text) + self.wrapped.flush() + if self.autoreset: + self.reset_all() + + + def reset_all(self): + if self.convert: + self.call_win32('m', (0,)) + elif not self.strip and not self.stream.closed: + self.wrapped.write(Style.RESET_ALL) + + + def write_and_convert(self, text): + ''' + Write the given text to our wrapped stream, stripping any ANSI + sequences from the text, and optionally converting them into win32 + calls. + ''' + cursor = 0 + text = self.convert_osc(text) + for match in self.ANSI_CSI_RE.finditer(text): + start, end = match.span() + self.write_plain_text(text, cursor, start) + self.convert_ansi(*match.groups()) + cursor = end + self.write_plain_text(text, cursor, len(text)) + + + def write_plain_text(self, text, start, end): + if start < end: + self.wrapped.write(text[start:end]) + self.wrapped.flush() + + + def convert_ansi(self, paramstring, command): + if self.convert: + params = self.extract_params(command, paramstring) + self.call_win32(command, params) + + + def extract_params(self, command, paramstring): + if command in 'Hf': + params = tuple(int(p) if len(p) != 0 else 1 for p in paramstring.split(';')) + while len(params) < 2: + # defaults: + params = params + (1,) + else: + params = tuple(int(p) for p in paramstring.split(';') if len(p) != 0) + if len(params) == 0: + # defaults: + if command in 'JKm': + params = (0,) + elif command in 'ABCD': + params = (1,) + + return params + + + def call_win32(self, command, params): + if command == 'm': + for param in params: + if param in self.win32_calls: + func_args = self.win32_calls[param] + func = func_args[0] + args = func_args[1:] + kwargs = dict(on_stderr=self.on_stderr) + func(*args, **kwargs) + elif command in 'J': + winterm.erase_screen(params[0], on_stderr=self.on_stderr) + elif command in 'K': + winterm.erase_line(params[0], on_stderr=self.on_stderr) + elif command in 'Hf': # cursor position - absolute + winterm.set_cursor_position(params, on_stderr=self.on_stderr) + elif command in 'ABCD': # cursor position - relative + n = params[0] + # A - up, B - down, C - forward, D - back + x, y = {'A': (0, -n), 'B': (0, n), 'C': (n, 0), 'D': (-n, 0)}[command] + winterm.cursor_adjust(x, y, on_stderr=self.on_stderr) + + + def convert_osc(self, text): + for match in self.ANSI_OSC_RE.finditer(text): + start, end = match.span() + text = text[:start] + text[end:] + paramstring, command = match.groups() + if command == BEL: + if paramstring.count(";") == 1: + params = paramstring.split(";") + # 0 - change title and icon (we will only change title) + # 1 - change icon (we don't support this) + # 2 - change title + if params[0] in '02': + winterm.set_title(params[1]) + return text + + + def flush(self): + self.wrapped.flush() diff --git a/backend/venv/Lib/site-packages/colorama/initialise.py b/backend/venv/Lib/site-packages/colorama/initialise.py new file mode 100644 index 0000000..d5fd4b7 --- /dev/null +++ b/backend/venv/Lib/site-packages/colorama/initialise.py @@ -0,0 +1,121 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +import atexit +import contextlib +import sys + +from .ansitowin32 import AnsiToWin32 + + +def _wipe_internal_state_for_tests(): + global orig_stdout, orig_stderr + orig_stdout = None + orig_stderr = None + + global wrapped_stdout, wrapped_stderr + wrapped_stdout = None + wrapped_stderr = None + + global atexit_done + atexit_done = False + + global fixed_windows_console + fixed_windows_console = False + + try: + # no-op if it wasn't registered + atexit.unregister(reset_all) + except AttributeError: + # python 2: no atexit.unregister. Oh well, we did our best. + pass + + +def reset_all(): + if AnsiToWin32 is not None: # Issue #74: objects might become None at exit + AnsiToWin32(orig_stdout).reset_all() + + +def init(autoreset=False, convert=None, strip=None, wrap=True): + + if not wrap and any([autoreset, convert, strip]): + raise ValueError('wrap=False conflicts with any other arg=True') + + global wrapped_stdout, wrapped_stderr + global orig_stdout, orig_stderr + + orig_stdout = sys.stdout + orig_stderr = sys.stderr + + if sys.stdout is None: + wrapped_stdout = None + else: + sys.stdout = wrapped_stdout = \ + wrap_stream(orig_stdout, convert, strip, autoreset, wrap) + if sys.stderr is None: + wrapped_stderr = None + else: + sys.stderr = wrapped_stderr = \ + wrap_stream(orig_stderr, convert, strip, autoreset, wrap) + + global atexit_done + if not atexit_done: + atexit.register(reset_all) + atexit_done = True + + +def deinit(): + if orig_stdout is not None: + sys.stdout = orig_stdout + if orig_stderr is not None: + sys.stderr = orig_stderr + + +def just_fix_windows_console(): + global fixed_windows_console + + if sys.platform != "win32": + return + if fixed_windows_console: + return + if wrapped_stdout is not None or wrapped_stderr is not None: + # Someone already ran init() and it did stuff, so we won't second-guess them + return + + # On newer versions of Windows, AnsiToWin32.__init__ will implicitly enable the + # native ANSI support in the console as a side-effect. We only need to actually + # replace sys.stdout/stderr if we're in the old-style conversion mode. + new_stdout = AnsiToWin32(sys.stdout, convert=None, strip=None, autoreset=False) + if new_stdout.convert: + sys.stdout = new_stdout + new_stderr = AnsiToWin32(sys.stderr, convert=None, strip=None, autoreset=False) + if new_stderr.convert: + sys.stderr = new_stderr + + fixed_windows_console = True + +@contextlib.contextmanager +def colorama_text(*args, **kwargs): + init(*args, **kwargs) + try: + yield + finally: + deinit() + + +def reinit(): + if wrapped_stdout is not None: + sys.stdout = wrapped_stdout + if wrapped_stderr is not None: + sys.stderr = wrapped_stderr + + +def wrap_stream(stream, convert, strip, autoreset, wrap): + if wrap: + wrapper = AnsiToWin32(stream, + convert=convert, strip=strip, autoreset=autoreset) + if wrapper.should_wrap(): + stream = wrapper.stream + return stream + + +# Use this for initial setup as well, to reduce code duplication +_wipe_internal_state_for_tests() diff --git a/backend/venv/Lib/site-packages/colorama/tests/__init__.py b/backend/venv/Lib/site-packages/colorama/tests/__init__.py new file mode 100644 index 0000000..8c5661e --- /dev/null +++ b/backend/venv/Lib/site-packages/colorama/tests/__init__.py @@ -0,0 +1 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. diff --git a/backend/venv/Lib/site-packages/colorama/tests/__pycache__/__init__.cpython-312.pyc b/backend/venv/Lib/site-packages/colorama/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..59bd4c33940c3d1f627ba7eefe876feba03bf3c2 GIT binary patch literal 205 zcmX@j%ge<81kZjv&+rD)k3k%C@Rc8q^ss!LI3S!#?+YH@Z+enCu-e{g_LOnGW*wrNaJesMvLX-raLa&~H7N=#X5 zURjJ!W>QRXW=X1U0Z=qCJ+(L{IX@@AC^0utza+J|q*y;bJ~J<~BtBlRpz;=nO>TZl aX-=wL5i8JgMj$Q*F+MUgGBOr116cqaJ32oA literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/colorama/tests/__pycache__/ansi_test.cpython-312.pyc b/backend/venv/Lib/site-packages/colorama/tests/__pycache__/ansi_test.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..acac7a677969a86ee83d687484b239567803244c GIT binary patch literal 5474 zcmeHL-ES0C6u+}Gvpem!g;FZrZq*{7F7$I*C|d|x+ND&MttoAg?IxS0Gs3p}QSVH_ zt;X~h0OMS$Se_+s6vWFQ9DvX+7Wf6#i%F{RaB*v zl$N7%+8K4GT~Qaa$tfjW7p)VBMrQXHU6ys!4feKjxtNPKI>;zdop*@p(j03dw?~__ zJ*qPIHX&4T5KUYwG#5xt$O*o>XIPH-9Hug<>BewE*Gws$NM@cn!0r=G>0DxF&Xmq) zsbb%2yq5u~h2 zAf2iV(v@@iT&BWY!VqSPKF}2|Bu-@edk{84XR)a-&m z>%bo?Xp}w_Oi9;LAL=;h&cD;cgRv>V>oI?y-#-@{&uAkwc~gsxX!@LyosUh7Uw%Iv zyQOJ!Ct@_K&!9Lt?DoYdTM6Us>uJ0#w27>a%p#BH+aBz29C6mMSf-XHm<<=ghJ+kfup`fhGr z8GNiXSX68%gWG^4Rojcp&$jnn$Se^9Bu_?RV+e_taz<%OD{4y{o+Gpous+#z^VN)J zY4SSV3pUyef|+4mxp^O&TR`yTrLEXPF|-67$==E=HkamIG~susqqE!O*VfK^;=OvN zzO1JQz*sdY91@$<2;^RPW=qqWElmM%g`^7qdNRxS(y|oM1b#C%@TISz0x#OYTYL|y zWCPz&?zfmzWgB=rl{HCq+Q8$k)+E(s1CM8^CaH=Iyu~kGt+RoDrKWQzs`WPT7F43T zZQ$E2`fsp-@36o(+Q7eNfp4;b@3g@0v4MZX0>9S={;&nUxs1;d-@eGA?43T|mu9M; zD?eAqxe9P~f~%8U4R94?D#+nM4i9p8ki&x<9^~*KhX)7Jz82HXX^U|db-_?g`CNEt z_@XIJghotxbRrarn9i%AaCrO*1PkG*km(^F#VCMP_;Nsha@mpJ7X}iDwLHlz1N_1W6tF*N(x2+7W zD?ODqt9IUH@5=1D(qGxmv+P-UZ(ZrFv~?_ZtSqi8{z{uwJF7m5wgO%AQ9tq=%X^Nk z!njXW_9D?10ER^$6(!- z_qL&&+U3<J@T${0-QNdzrojQz;DKpy!8G__8k{fbyh-an9 zqU4?CADSN&6#COXnSTp-9W}*~u}h{iGCpx>C~P{Hp<1Dve49A|NDh_i;RS;KG z8^Y6k7DQzf*ZKgXsj;evt@XjqsEgZj8%jUhqliy2m3TapNNe%9Ss#z5v+6<$^9}Jh zzVPrGiq|vhMSpNsilH}7{4G#I>R(*>c-0EtP z2e-RK+0StZ!2#f7T|DmF%bq$+Wg(L^a9t=qK~M=BNeOt`;r|#6;3->SHyVxXEquab z4^Qlsgkqda+3N^i>-e|^FgJ(--#Q9!C1?0_&(e3mhHq5*D2Po_5QHbB{&#ZdDLI@c zhkqkS{%C6cYW9oS+wRB3%yZ`%!GHJT=LFQ|X9AHL?k@f$dVZ0V&(Cj)L~3Up{R5a{ Bi7NmA literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/colorama/tests/__pycache__/ansitowin32_test.cpython-312.pyc b/backend/venv/Lib/site-packages/colorama/tests/__pycache__/ansitowin32_test.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d10d96ead17e627090cfdc85e644f326a2d6007f GIT binary patch literal 18013 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 A8vp{9$`kdZgs1@5oEJ&dYa=fb znZHP6mttFG&8I{g6rb##IzR~JZA4*Liw|eWJTuRPJoj*ZI%L!N2}RXTNUEaSQ&J** z&jxx>d&f1ZNU67|G(D|Q-4jl$iHXcxiS$7KJqDL>x^sGd@|;9dx|=G~Noi7vpPAR2 zt#O7X&L+}Q5|u8~*u+Fc7tG=5Od4jBXvu1J7~tkNkAk>Lw9>T;;G$LB7PRxl*E46P zv|eqTtT6CK)B$SUkx(T~n-4L%Lp9z+MSJaAnG-{?Kd1^-WBq;o{Zp~Av@%K)vr24K zQKz)bbnMNs@i$(J%_+*%V2oze>EvMSj5Il=q~+MGlAevdmN*kr6Pj{(8nn_`MU72n zk{K$cq+Sg?srH%=j^m_fdS2%fYFvuLR%kP9zy&`w0OA93#}l}=dwEyRv%lauob?>e zd3tZ!dpF@4nM7eV%MV4rC?v|rBx;ixfS#3YAnh^>l9TNq9Wn>fDLX*&MtHd9`H)L@ zzijve!LIT;I?M3-cQB~*y5-gPmkRBEI zL->+Ta)hYNoQ)w7u!)*?*$A0qs1KePvQq&%-7TqrvNl0y6vOcpJ-=ep?W&Uelg5~h9^+^s$j0>Ef$`&-YV6Tm3&fh-?b z3M_Z!S`OyFwpSxnNIT=q*D+gJ7aQ4u6L$^-|$+LRiCuGTM3G8kKu1 zL9G7KDN$k1I9bZJaAeuBdN>jO&2(`XpirbF10$VP=T+oPS)tVEGc(!>V_;@dsF^T+ z1F5-$cJ2-H6j*4jg{$HsBCZ|>0hm=~%JuOtqn}4}Vqac3Qc9mnR0EOr$Uh%5c#Zm{z4wYb`L4N@KGCWMOxiX1SIFS0am%&wST>TR7O-?0|be7Q!v;=dEEc_bm^j8(uEF+jXPKiQ^V7{M7#y zen^NF_@RSMN^FNw6@G2C_?e|r3Bu405LPeUi>99gQ6fqU#bdVu-2h`9a%?$-02Tt> zHv`=!mb4ozRPiLHfRSqN!?9m4)i8a^$p*z+u{<#JrLv(~52eA5=~iBCSu?nE$9pt9 zb&X~vymhbD8#WM|npRG84T}n+ZEvGC%^x+dLj!y2)4+#q_4U;y4_^^k_{y{#UPjy* zQg(0*$3!=#GcN$x-joxbP$afz7M!VHHeA~aP;BU|R z+ph<{+WSRY-rrZDSv$1alk0dk?;ir?Ro`EI*ZH-U)z)15VBUZ9fs^cguF%+F9NUYL zyPd-~JBPPGakH^wtEk*khv3ndg^>aFsxZ>UeGz_gq}91@<6*q+=0UyQ%8l&xthYN+ z)5VSSxz-OkQ9ra!w01^F`M}itmi9ar(KYSA^3IR@d@KrU+V6jUZ5}_Ix7B&*si>upn9NhV5l84L zGcApbL~5q{QS3ueo0h@aw5|_JMKrGY~ap*Q;x;RZmWQx*#6UipLA$ zNLC!liKBVpWcgJ1p2)>XFzEB9B$_7v6f-mKTm#qTe)iw5O_li3w4iv

@CY{g_FN(2B?Wpre@U=wC z%;DD(<8uVXaL~CKEs<1f$=V=hBPxvlNX8!f(bOP{(&lx3*mT146!{L1RCO4{eU@RE zUx@oI>HL*EeV0t!A`=@9hUxpw5n@g<9|e9R*x!GfA$DPL;U~7`XFLDrQ}%9YX z8%U5WF^wjrFXF#I(8M=ieBs#_n%GDNOiZj_Z!}BN()i#xGqWF1V(P1RGUuNAyPxNG z&$;J^`uZS&^84dIt`B+$`4t=G;&qkMSD>sDg(y@bIhv#tbwLwyVp6nqQS&4{fQgzn z=@rN*Q9MPWcvW#zbk<1vY}5y+zXtWIRFR5g)7>a3K|4^>4nR9t(+)zruBKgA5Tl{L zaCVeh4H-i>)thE6t*2*H28c9avaCMy{&*te?qFBcZIqfoStlwO-zFp6Y+SzkfD0 zuB#&~JFlijR6c7O`P8-XiK|yq3#vLhkYWbUYXhn2bY@o7mDIed&!?_rr&By@s;}h% z1ygt`V`v6T=hD5V%1z!oXJ$1X%NHzPmZwd#aI3L$-k5^~;3ORHZ<*|z3YS13i4Bh> z$+Di#sj_SZWjSXka~kR)S^i`$tvNj`1Y?#Z3SU_u&ix>Yq$E&pvoi*}|0Ba8 z=fnv^e-@J8a}H!%Ws~e23y*p$T)UEMKAyZ{zH`U~YXI=LVPV8j;8Hb)wK#@h&k+w0 z0O*3h^bv^5gn}2CpgH9R_8u!sbg^cHT=6D_d`Z_KkQQlmezmtiz7ZGb22Df-OE9?Q z!MlkH?0Hz-@)#^T!*Q=j#OA^B85{?&HozL;=MfNplE=&BL0$cw!P|q&BRdUE#S6vJ zT~EN)R!0vxI`PV@F?zCrUqkP+8CW&o1}=H5ED0wQa0IOo_wTeU3e~;j${dF*_8e>s zp)2wNw|v}Gj5*V;RmL_%)G(s0IwVhayDJSC!!fWUWk!Qc&1>n5Do+;}-ghhfd=P}g zYE#R4&)uHo%X?*I=X7gvxH#rk$nxoS2Y_mI?68C(vJ!8KH~+urX6;}XJ|+&M&cgya z5Gu>;46=5F*KnCvyoRiv){x+rVOS>)JwkBoZpPq_{98Xqig6*VWRfO{})-30}N?uwbCaz|eMY8Dz@c@LsiBHlAIQX%M z;SD(vzD?IxpKe$E`Q-DwLkeI-AK`RCpkxYmq~wdPo8lB%pikl54vtSpR7_a3&uX|j zHGC<4?F0GJ_{8MJk*JrUBU^sRGFfKm_RDAcw|xhYG5xxs%aBo=ROY-c{(K>GJoY8~b!@`_!3xp2%K9+voc7=w2YaHhMqM{$oeqx83(UhIXa; zMK{m{;gg=;L(s3bW^{Uoo487mXI|VK1Q~G+D1D$%zp3j znXFoEn{_NNSkieXJHE^MU@%@dFM!w=DW$)Wb3c>TT@u_SfdijFo7bcR0@Z;e(3Z8g wP;c3nh|u^@@X&Bc1Z^L+{g93M>5DD~+J2LZbyl!W7xU6{Hug{e%}z)E0Mg&x#Q*>R literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/colorama/tests/__pycache__/winterm_test.cpython-312.pyc b/backend/venv/Lib/site-packages/colorama/tests/__pycache__/winterm_test.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c916541d6ebe36fb966b3319ade94c51b89b4efc GIT binary patch literal 6619 zcmeHMOKcm*8J>NRT#_rAwe_|uONkAeLG&;kKUxPh^opv&mQsm^Yl6Un;;t-Gd?>Rk zDCeBQzAG(U7$bMRSp{D(*FOFyIfH# zDR9&xKs$$jX6NzG&-uUqF~dL9)c6RLzkdF=iQ54}KE)5SxXO*K_n`5B$V6t+B#Jeg zW-@G)&2UjJ!$*0Bc(IpDyE5*mJL8FZ7$WnsEA7kpqyCH-6*D!_8iufBfXMDUMD{4` zW3I$K8c+_&!sKZ}sK641dtBa>A+yXZ^DA)=^SZ(LP$J`+!7b)Pz!oVu1xE2ZYxSrl4k9z!1%nY}~IpAh9?%%!+faIn=S z^^NKtSj$;l_{S(66xn6t=dIccj?&u8cK~~NZ2bHOz)!I86Ayr&*T%1=>MVS=u|ULE=Ut010_1wsrqZx2DnL*tDjodh>vy_2#l_F0G6v zsG?+hrpLz>I+z{L=^|CMX_}R8#naOY#UHQxa#OL9;n6p*#AXy_@?4DO)T#8j7;dIy<=8DHdnIf*8H&f(f3z{Q~UKDeR%Xy{3GG? z7VJWF4g|~xsq)rzk}7H|$Ry`x)P#jqn1f0)@cm=Jh9kZiz&BIDxAA3Ji1B418_;NB z8wDs8um=Zho7e{zYN1lI(C*|q?NYqRPJ45Al)}LpKnm;EAG{Pc86EbP**pZJJRGY{ z+Qa5Kr)tesr3Pugl6GwJICvD>=$_JQd&;=|_kf4thA1BKI`Rzp4c|Z;piLW*G$E-6 zqI+*DniL1iS1H0yci-s0a%K3s?z!4M&_5LErkLXB?w*msf$v6^Sb7v!wg6F)eQPT{ zj^iSlCpao}A!@#{+HlPg+*bWF5HQ}7eST6`KhNLwt(B|#2Ke&Z4YcK9%Suz|gEOl_ z`?I=lK9KH9#(bMumu7r;@fVkuF0TrgU{U*2EWib z0R9HthNFWxkN~(du+DLknR!8W1z+f@jADFY_^Eth2r>$U%p+#IQk%}k2z+&wezUbp zpxquYo!2>-g*{+`i*R1&WH7FZS?{{eNZU=hOLYpZp{mI43NJ7z&(L}ZW~~1U$~yXg ziYG?VE+Zk)2;CIVjiL{sC~-L?t6*Y@QV6fILEQ^61r0ErE}5e{0Zm1w&9K^v!ZsTl z!Rg)U^iCTyM>=uk`#`>2fP8lJ_)pKz^Q%JRS{)i6m}04_Z$u;bL=f)<76LE~trv@= ztHNoUK^L1sg{DxksjJY`_2k4y!iAEx*uyC%A4WL+J2V`vh0!dBY@*U0QmO(f;}lRK z0W9yiYa+*_ENcNl%H>NWj*h9TV-jk!jajn9mt8hmY$W6<`D_${qD~Fu=sYHL22|)7 z>_k9r^TbB_^af1YnLc4}56s`X2E_8fPi+7&d@-uryWm}HyDRRa^Z)A-4zgVA7lT}hLNwU&R~r09{?Y9H{&U#E@(Wy1>a)$ZoqClc%>Ly6+-(vLMtzZy{vmh3%Dvr zNBCbz8z8LLfGkzTbi0Q0#5-A4f%}R>a86k{Y-KvkbjrE86lSYc#oTqAO_Fij4IY9s zTXLRz#bGzxKF-SugG^E>0^AY2N)t3tDdsx`5$D7F{G_M&*9AYNDt zG!z3Zg+R+A{{6tu11qgv%Qa`7gqOwhpSd`%Z)Z+wf$OEO9k^unL+dr~YXh*dkBNjB z-J8q8Q;Mumx(D27Hv-1O8pX&K_@|6;buu5jC70HTKHCv^%oQIS4Lw2FQyd z?9pq>LL+2sUj=4Ep`b2EQZ}AZBuV#4QYI%)r?D+c62427MkwAsXe$!TcyvykRdr!1 z9oHbo$-v{Y7N?pzlhh{YD>x~PDkM=}UxsT2*3Oqrs;G6*)*X2ACy@)wtH z+5hs2>%=DOafP-x;y$^7tI2tGuw%KaXT{aK$sTbHFgUl5 z*)ZChuMoH2CO&P|wc=|cPdLzXVUYyVWk!$)BFZ}3@4ft&Sd}D?q!jXRv e23NKg_*P`u_JxY!Yf-pFep}P+=YH>Ffc_iQ(~6=1 literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/colorama/tests/ansi_test.py b/backend/venv/Lib/site-packages/colorama/tests/ansi_test.py new file mode 100644 index 0000000..0a20c80 --- /dev/null +++ b/backend/venv/Lib/site-packages/colorama/tests/ansi_test.py @@ -0,0 +1,76 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +import sys +from unittest import TestCase, main + +from ..ansi import Back, Fore, Style +from ..ansitowin32 import AnsiToWin32 + +stdout_orig = sys.stdout +stderr_orig = sys.stderr + + +class AnsiTest(TestCase): + + def setUp(self): + # sanity check: stdout should be a file or StringIO object. + # It will only be AnsiToWin32 if init() has previously wrapped it + self.assertNotEqual(type(sys.stdout), AnsiToWin32) + self.assertNotEqual(type(sys.stderr), AnsiToWin32) + + def tearDown(self): + sys.stdout = stdout_orig + sys.stderr = stderr_orig + + + def testForeAttributes(self): + self.assertEqual(Fore.BLACK, '\033[30m') + self.assertEqual(Fore.RED, '\033[31m') + self.assertEqual(Fore.GREEN, '\033[32m') + self.assertEqual(Fore.YELLOW, '\033[33m') + self.assertEqual(Fore.BLUE, '\033[34m') + self.assertEqual(Fore.MAGENTA, '\033[35m') + self.assertEqual(Fore.CYAN, '\033[36m') + self.assertEqual(Fore.WHITE, '\033[37m') + self.assertEqual(Fore.RESET, '\033[39m') + + # Check the light, extended versions. + self.assertEqual(Fore.LIGHTBLACK_EX, '\033[90m') + self.assertEqual(Fore.LIGHTRED_EX, '\033[91m') + self.assertEqual(Fore.LIGHTGREEN_EX, '\033[92m') + self.assertEqual(Fore.LIGHTYELLOW_EX, '\033[93m') + self.assertEqual(Fore.LIGHTBLUE_EX, '\033[94m') + self.assertEqual(Fore.LIGHTMAGENTA_EX, '\033[95m') + self.assertEqual(Fore.LIGHTCYAN_EX, '\033[96m') + self.assertEqual(Fore.LIGHTWHITE_EX, '\033[97m') + + + def testBackAttributes(self): + self.assertEqual(Back.BLACK, '\033[40m') + self.assertEqual(Back.RED, '\033[41m') + self.assertEqual(Back.GREEN, '\033[42m') + self.assertEqual(Back.YELLOW, '\033[43m') + self.assertEqual(Back.BLUE, '\033[44m') + self.assertEqual(Back.MAGENTA, '\033[45m') + self.assertEqual(Back.CYAN, '\033[46m') + self.assertEqual(Back.WHITE, '\033[47m') + self.assertEqual(Back.RESET, '\033[49m') + + # Check the light, extended versions. + self.assertEqual(Back.LIGHTBLACK_EX, '\033[100m') + self.assertEqual(Back.LIGHTRED_EX, '\033[101m') + self.assertEqual(Back.LIGHTGREEN_EX, '\033[102m') + self.assertEqual(Back.LIGHTYELLOW_EX, '\033[103m') + self.assertEqual(Back.LIGHTBLUE_EX, '\033[104m') + self.assertEqual(Back.LIGHTMAGENTA_EX, '\033[105m') + self.assertEqual(Back.LIGHTCYAN_EX, '\033[106m') + self.assertEqual(Back.LIGHTWHITE_EX, '\033[107m') + + + def testStyleAttributes(self): + self.assertEqual(Style.DIM, '\033[2m') + self.assertEqual(Style.NORMAL, '\033[22m') + self.assertEqual(Style.BRIGHT, '\033[1m') + + +if __name__ == '__main__': + main() diff --git a/backend/venv/Lib/site-packages/colorama/tests/ansitowin32_test.py b/backend/venv/Lib/site-packages/colorama/tests/ansitowin32_test.py new file mode 100644 index 0000000..91ca551 --- /dev/null +++ b/backend/venv/Lib/site-packages/colorama/tests/ansitowin32_test.py @@ -0,0 +1,294 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +from io import StringIO, TextIOWrapper +from unittest import TestCase, main +try: + from contextlib import ExitStack +except ImportError: + # python 2 + from contextlib2 import ExitStack + +try: + from unittest.mock import MagicMock, Mock, patch +except ImportError: + from mock import MagicMock, Mock, patch + +from ..ansitowin32 import AnsiToWin32, StreamWrapper +from ..win32 import ENABLE_VIRTUAL_TERMINAL_PROCESSING +from .utils import osname + + +class StreamWrapperTest(TestCase): + + def testIsAProxy(self): + mockStream = Mock() + wrapper = StreamWrapper(mockStream, None) + self.assertTrue( wrapper.random_attr is mockStream.random_attr ) + + def testDelegatesWrite(self): + mockStream = Mock() + mockConverter = Mock() + wrapper = StreamWrapper(mockStream, mockConverter) + wrapper.write('hello') + self.assertTrue(mockConverter.write.call_args, (('hello',), {})) + + def testDelegatesContext(self): + mockConverter = Mock() + s = StringIO() + with StreamWrapper(s, mockConverter) as fp: + fp.write(u'hello') + self.assertTrue(s.closed) + + def testProxyNoContextManager(self): + mockStream = MagicMock() + mockStream.__enter__.side_effect = AttributeError() + mockConverter = Mock() + with self.assertRaises(AttributeError) as excinfo: + with StreamWrapper(mockStream, mockConverter) as wrapper: + wrapper.write('hello') + + def test_closed_shouldnt_raise_on_closed_stream(self): + stream = StringIO() + stream.close() + wrapper = StreamWrapper(stream, None) + self.assertEqual(wrapper.closed, True) + + def test_closed_shouldnt_raise_on_detached_stream(self): + stream = TextIOWrapper(StringIO()) + stream.detach() + wrapper = StreamWrapper(stream, None) + self.assertEqual(wrapper.closed, True) + +class AnsiToWin32Test(TestCase): + + def testInit(self): + mockStdout = Mock() + auto = Mock() + stream = AnsiToWin32(mockStdout, autoreset=auto) + self.assertEqual(stream.wrapped, mockStdout) + self.assertEqual(stream.autoreset, auto) + + @patch('colorama.ansitowin32.winterm', None) + @patch('colorama.ansitowin32.winapi_test', lambda *_: True) + def testStripIsTrueOnWindows(self): + with osname('nt'): + mockStdout = Mock() + stream = AnsiToWin32(mockStdout) + self.assertTrue(stream.strip) + + def testStripIsFalseOffWindows(self): + with osname('posix'): + mockStdout = Mock(closed=False) + stream = AnsiToWin32(mockStdout) + self.assertFalse(stream.strip) + + def testWriteStripsAnsi(self): + mockStdout = Mock() + stream = AnsiToWin32(mockStdout) + stream.wrapped = Mock() + stream.write_and_convert = Mock() + stream.strip = True + + stream.write('abc') + + self.assertFalse(stream.wrapped.write.called) + self.assertEqual(stream.write_and_convert.call_args, (('abc',), {})) + + def testWriteDoesNotStripAnsi(self): + mockStdout = Mock() + stream = AnsiToWin32(mockStdout) + stream.wrapped = Mock() + stream.write_and_convert = Mock() + stream.strip = False + stream.convert = False + + stream.write('abc') + + self.assertFalse(stream.write_and_convert.called) + self.assertEqual(stream.wrapped.write.call_args, (('abc',), {})) + + def assert_autoresets(self, convert, autoreset=True): + stream = AnsiToWin32(Mock()) + stream.convert = convert + stream.reset_all = Mock() + stream.autoreset = autoreset + stream.winterm = Mock() + + stream.write('abc') + + self.assertEqual(stream.reset_all.called, autoreset) + + def testWriteAutoresets(self): + self.assert_autoresets(convert=True) + self.assert_autoresets(convert=False) + self.assert_autoresets(convert=True, autoreset=False) + self.assert_autoresets(convert=False, autoreset=False) + + def testWriteAndConvertWritesPlainText(self): + stream = AnsiToWin32(Mock()) + stream.write_and_convert( 'abc' ) + self.assertEqual( stream.wrapped.write.call_args, (('abc',), {}) ) + + def testWriteAndConvertStripsAllValidAnsi(self): + stream = AnsiToWin32(Mock()) + stream.call_win32 = Mock() + data = [ + 'abc\033[mdef', + 'abc\033[0mdef', + 'abc\033[2mdef', + 'abc\033[02mdef', + 'abc\033[002mdef', + 'abc\033[40mdef', + 'abc\033[040mdef', + 'abc\033[0;1mdef', + 'abc\033[40;50mdef', + 'abc\033[50;30;40mdef', + 'abc\033[Adef', + 'abc\033[0Gdef', + 'abc\033[1;20;128Hdef', + ] + for datum in data: + stream.wrapped.write.reset_mock() + stream.write_and_convert( datum ) + self.assertEqual( + [args[0] for args in stream.wrapped.write.call_args_list], + [ ('abc',), ('def',) ] + ) + + def testWriteAndConvertSkipsEmptySnippets(self): + stream = AnsiToWin32(Mock()) + stream.call_win32 = Mock() + stream.write_and_convert( '\033[40m\033[41m' ) + self.assertFalse( stream.wrapped.write.called ) + + def testWriteAndConvertCallsWin32WithParamsAndCommand(self): + stream = AnsiToWin32(Mock()) + stream.convert = True + stream.call_win32 = Mock() + stream.extract_params = Mock(return_value='params') + data = { + 'abc\033[adef': ('a', 'params'), + 'abc\033[;;bdef': ('b', 'params'), + 'abc\033[0cdef': ('c', 'params'), + 'abc\033[;;0;;Gdef': ('G', 'params'), + 'abc\033[1;20;128Hdef': ('H', 'params'), + } + for datum, expected in data.items(): + stream.call_win32.reset_mock() + stream.write_and_convert( datum ) + self.assertEqual( stream.call_win32.call_args[0], expected ) + + def test_reset_all_shouldnt_raise_on_closed_orig_stdout(self): + stream = StringIO() + converter = AnsiToWin32(stream) + stream.close() + + converter.reset_all() + + def test_wrap_shouldnt_raise_on_closed_orig_stdout(self): + stream = StringIO() + stream.close() + with \ + patch("colorama.ansitowin32.os.name", "nt"), \ + patch("colorama.ansitowin32.winapi_test", lambda: True): + converter = AnsiToWin32(stream) + self.assertTrue(converter.strip) + self.assertFalse(converter.convert) + + def test_wrap_shouldnt_raise_on_missing_closed_attr(self): + with \ + patch("colorama.ansitowin32.os.name", "nt"), \ + patch("colorama.ansitowin32.winapi_test", lambda: True): + converter = AnsiToWin32(object()) + self.assertTrue(converter.strip) + self.assertFalse(converter.convert) + + def testExtractParams(self): + stream = AnsiToWin32(Mock()) + data = { + '': (0,), + ';;': (0,), + '2': (2,), + ';;002;;': (2,), + '0;1': (0, 1), + ';;003;;456;;': (3, 456), + '11;22;33;44;55': (11, 22, 33, 44, 55), + } + for datum, expected in data.items(): + self.assertEqual(stream.extract_params('m', datum), expected) + + def testCallWin32UsesLookup(self): + listener = Mock() + stream = AnsiToWin32(listener) + stream.win32_calls = { + 1: (lambda *_, **__: listener(11),), + 2: (lambda *_, **__: listener(22),), + 3: (lambda *_, **__: listener(33),), + } + stream.call_win32('m', (3, 1, 99, 2)) + self.assertEqual( + [a[0][0] for a in listener.call_args_list], + [33, 11, 22] ) + + def test_osc_codes(self): + mockStdout = Mock() + stream = AnsiToWin32(mockStdout, convert=True) + with patch('colorama.ansitowin32.winterm') as winterm: + data = [ + '\033]0\x07', # missing arguments + '\033]0;foo\x08', # wrong OSC command + '\033]0;colorama_test_title\x07', # should work + '\033]1;colorama_test_title\x07', # wrong set command + '\033]2;colorama_test_title\x07', # should work + '\033]' + ';' * 64 + '\x08', # see issue #247 + ] + for code in data: + stream.write(code) + self.assertEqual(winterm.set_title.call_count, 2) + + def test_native_windows_ansi(self): + with ExitStack() as stack: + def p(a, b): + stack.enter_context(patch(a, b, create=True)) + # Pretend to be on Windows + p("colorama.ansitowin32.os.name", "nt") + p("colorama.ansitowin32.winapi_test", lambda: True) + p("colorama.win32.winapi_test", lambda: True) + p("colorama.winterm.win32.windll", "non-None") + p("colorama.winterm.get_osfhandle", lambda _: 1234) + + # Pretend that our mock stream has native ANSI support + p( + "colorama.winterm.win32.GetConsoleMode", + lambda _: ENABLE_VIRTUAL_TERMINAL_PROCESSING, + ) + SetConsoleMode = Mock() + p("colorama.winterm.win32.SetConsoleMode", SetConsoleMode) + + stdout = Mock() + stdout.closed = False + stdout.isatty.return_value = True + stdout.fileno.return_value = 1 + + # Our fake console says it has native vt support, so AnsiToWin32 should + # enable that support and do nothing else. + stream = AnsiToWin32(stdout) + SetConsoleMode.assert_called_with(1234, ENABLE_VIRTUAL_TERMINAL_PROCESSING) + self.assertFalse(stream.strip) + self.assertFalse(stream.convert) + self.assertFalse(stream.should_wrap()) + + # Now let's pretend we're on an old Windows console, that doesn't have + # native ANSI support. + p("colorama.winterm.win32.GetConsoleMode", lambda _: 0) + SetConsoleMode = Mock() + p("colorama.winterm.win32.SetConsoleMode", SetConsoleMode) + + stream = AnsiToWin32(stdout) + SetConsoleMode.assert_called_with(1234, ENABLE_VIRTUAL_TERMINAL_PROCESSING) + self.assertTrue(stream.strip) + self.assertTrue(stream.convert) + self.assertTrue(stream.should_wrap()) + + +if __name__ == '__main__': + main() diff --git a/backend/venv/Lib/site-packages/colorama/tests/initialise_test.py b/backend/venv/Lib/site-packages/colorama/tests/initialise_test.py new file mode 100644 index 0000000..89f9b07 --- /dev/null +++ b/backend/venv/Lib/site-packages/colorama/tests/initialise_test.py @@ -0,0 +1,189 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +import sys +from unittest import TestCase, main, skipUnless + +try: + from unittest.mock import patch, Mock +except ImportError: + from mock import patch, Mock + +from ..ansitowin32 import StreamWrapper +from ..initialise import init, just_fix_windows_console, _wipe_internal_state_for_tests +from .utils import osname, replace_by + +orig_stdout = sys.stdout +orig_stderr = sys.stderr + + +class InitTest(TestCase): + + @skipUnless(sys.stdout.isatty(), "sys.stdout is not a tty") + def setUp(self): + # sanity check + self.assertNotWrapped() + + def tearDown(self): + _wipe_internal_state_for_tests() + sys.stdout = orig_stdout + sys.stderr = orig_stderr + + def assertWrapped(self): + self.assertIsNot(sys.stdout, orig_stdout, 'stdout should be wrapped') + self.assertIsNot(sys.stderr, orig_stderr, 'stderr should be wrapped') + self.assertTrue(isinstance(sys.stdout, StreamWrapper), + 'bad stdout wrapper') + self.assertTrue(isinstance(sys.stderr, StreamWrapper), + 'bad stderr wrapper') + + def assertNotWrapped(self): + self.assertIs(sys.stdout, orig_stdout, 'stdout should not be wrapped') + self.assertIs(sys.stderr, orig_stderr, 'stderr should not be wrapped') + + @patch('colorama.initialise.reset_all') + @patch('colorama.ansitowin32.winapi_test', lambda *_: True) + @patch('colorama.ansitowin32.enable_vt_processing', lambda *_: False) + def testInitWrapsOnWindows(self, _): + with osname("nt"): + init() + self.assertWrapped() + + @patch('colorama.initialise.reset_all') + @patch('colorama.ansitowin32.winapi_test', lambda *_: False) + def testInitDoesntWrapOnEmulatedWindows(self, _): + with osname("nt"): + init() + self.assertNotWrapped() + + def testInitDoesntWrapOnNonWindows(self): + with osname("posix"): + init() + self.assertNotWrapped() + + def testInitDoesntWrapIfNone(self): + with replace_by(None): + init() + # We can't use assertNotWrapped here because replace_by(None) + # changes stdout/stderr already. + self.assertIsNone(sys.stdout) + self.assertIsNone(sys.stderr) + + def testInitAutoresetOnWrapsOnAllPlatforms(self): + with osname("posix"): + init(autoreset=True) + self.assertWrapped() + + def testInitWrapOffDoesntWrapOnWindows(self): + with osname("nt"): + init(wrap=False) + self.assertNotWrapped() + + def testInitWrapOffIncompatibleWithAutoresetOn(self): + self.assertRaises(ValueError, lambda: init(autoreset=True, wrap=False)) + + @patch('colorama.win32.SetConsoleTextAttribute') + @patch('colorama.initialise.AnsiToWin32') + def testAutoResetPassedOn(self, mockATW32, _): + with osname("nt"): + init(autoreset=True) + self.assertEqual(len(mockATW32.call_args_list), 2) + self.assertEqual(mockATW32.call_args_list[1][1]['autoreset'], True) + self.assertEqual(mockATW32.call_args_list[0][1]['autoreset'], True) + + @patch('colorama.initialise.AnsiToWin32') + def testAutoResetChangeable(self, mockATW32): + with osname("nt"): + init() + + init(autoreset=True) + self.assertEqual(len(mockATW32.call_args_list), 4) + self.assertEqual(mockATW32.call_args_list[2][1]['autoreset'], True) + self.assertEqual(mockATW32.call_args_list[3][1]['autoreset'], True) + + init() + self.assertEqual(len(mockATW32.call_args_list), 6) + self.assertEqual( + mockATW32.call_args_list[4][1]['autoreset'], False) + self.assertEqual( + mockATW32.call_args_list[5][1]['autoreset'], False) + + + @patch('colorama.initialise.atexit.register') + def testAtexitRegisteredOnlyOnce(self, mockRegister): + init() + self.assertTrue(mockRegister.called) + mockRegister.reset_mock() + init() + self.assertFalse(mockRegister.called) + + +class JustFixWindowsConsoleTest(TestCase): + def _reset(self): + _wipe_internal_state_for_tests() + sys.stdout = orig_stdout + sys.stderr = orig_stderr + + def tearDown(self): + self._reset() + + @patch("colorama.ansitowin32.winapi_test", lambda: True) + def testJustFixWindowsConsole(self): + if sys.platform != "win32": + # just_fix_windows_console should be a no-op + just_fix_windows_console() + self.assertIs(sys.stdout, orig_stdout) + self.assertIs(sys.stderr, orig_stderr) + else: + def fake_std(): + # Emulate stdout=not a tty, stderr=tty + # to check that we handle both cases correctly + stdout = Mock() + stdout.closed = False + stdout.isatty.return_value = False + stdout.fileno.return_value = 1 + sys.stdout = stdout + + stderr = Mock() + stderr.closed = False + stderr.isatty.return_value = True + stderr.fileno.return_value = 2 + sys.stderr = stderr + + for native_ansi in [False, True]: + with patch( + 'colorama.ansitowin32.enable_vt_processing', + lambda *_: native_ansi + ): + self._reset() + fake_std() + + # Regular single-call test + prev_stdout = sys.stdout + prev_stderr = sys.stderr + just_fix_windows_console() + self.assertIs(sys.stdout, prev_stdout) + if native_ansi: + self.assertIs(sys.stderr, prev_stderr) + else: + self.assertIsNot(sys.stderr, prev_stderr) + + # second call without resetting is always a no-op + prev_stdout = sys.stdout + prev_stderr = sys.stderr + just_fix_windows_console() + self.assertIs(sys.stdout, prev_stdout) + self.assertIs(sys.stderr, prev_stderr) + + self._reset() + fake_std() + + # If init() runs first, just_fix_windows_console should be a no-op + init() + prev_stdout = sys.stdout + prev_stderr = sys.stderr + just_fix_windows_console() + self.assertIs(prev_stdout, sys.stdout) + self.assertIs(prev_stderr, sys.stderr) + + +if __name__ == '__main__': + main() diff --git a/backend/venv/Lib/site-packages/colorama/tests/isatty_test.py b/backend/venv/Lib/site-packages/colorama/tests/isatty_test.py new file mode 100644 index 0000000..0f84e4b --- /dev/null +++ b/backend/venv/Lib/site-packages/colorama/tests/isatty_test.py @@ -0,0 +1,57 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +import sys +from unittest import TestCase, main + +from ..ansitowin32 import StreamWrapper, AnsiToWin32 +from .utils import pycharm, replace_by, replace_original_by, StreamTTY, StreamNonTTY + + +def is_a_tty(stream): + return StreamWrapper(stream, None).isatty() + +class IsattyTest(TestCase): + + def test_TTY(self): + tty = StreamTTY() + self.assertTrue(is_a_tty(tty)) + with pycharm(): + self.assertTrue(is_a_tty(tty)) + + def test_nonTTY(self): + non_tty = StreamNonTTY() + self.assertFalse(is_a_tty(non_tty)) + with pycharm(): + self.assertFalse(is_a_tty(non_tty)) + + def test_withPycharm(self): + with pycharm(): + self.assertTrue(is_a_tty(sys.stderr)) + self.assertTrue(is_a_tty(sys.stdout)) + + def test_withPycharmTTYOverride(self): + tty = StreamTTY() + with pycharm(), replace_by(tty): + self.assertTrue(is_a_tty(tty)) + + def test_withPycharmNonTTYOverride(self): + non_tty = StreamNonTTY() + with pycharm(), replace_by(non_tty): + self.assertFalse(is_a_tty(non_tty)) + + def test_withPycharmNoneOverride(self): + with pycharm(): + with replace_by(None), replace_original_by(None): + self.assertFalse(is_a_tty(None)) + self.assertFalse(is_a_tty(StreamNonTTY())) + self.assertTrue(is_a_tty(StreamTTY())) + + def test_withPycharmStreamWrapped(self): + with pycharm(): + self.assertTrue(AnsiToWin32(StreamTTY()).stream.isatty()) + self.assertFalse(AnsiToWin32(StreamNonTTY()).stream.isatty()) + self.assertTrue(AnsiToWin32(sys.stdout).stream.isatty()) + self.assertTrue(AnsiToWin32(sys.stderr).stream.isatty()) + + +if __name__ == '__main__': + main() diff --git a/backend/venv/Lib/site-packages/colorama/tests/utils.py b/backend/venv/Lib/site-packages/colorama/tests/utils.py new file mode 100644 index 0000000..472fafb --- /dev/null +++ b/backend/venv/Lib/site-packages/colorama/tests/utils.py @@ -0,0 +1,49 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +from contextlib import contextmanager +from io import StringIO +import sys +import os + + +class StreamTTY(StringIO): + def isatty(self): + return True + +class StreamNonTTY(StringIO): + def isatty(self): + return False + +@contextmanager +def osname(name): + orig = os.name + os.name = name + yield + os.name = orig + +@contextmanager +def replace_by(stream): + orig_stdout = sys.stdout + orig_stderr = sys.stderr + sys.stdout = stream + sys.stderr = stream + yield + sys.stdout = orig_stdout + sys.stderr = orig_stderr + +@contextmanager +def replace_original_by(stream): + orig_stdout = sys.__stdout__ + orig_stderr = sys.__stderr__ + sys.__stdout__ = stream + sys.__stderr__ = stream + yield + sys.__stdout__ = orig_stdout + sys.__stderr__ = orig_stderr + +@contextmanager +def pycharm(): + os.environ["PYCHARM_HOSTED"] = "1" + non_tty = StreamNonTTY() + with replace_by(non_tty), replace_original_by(non_tty): + yield + del os.environ["PYCHARM_HOSTED"] diff --git a/backend/venv/Lib/site-packages/colorama/tests/winterm_test.py b/backend/venv/Lib/site-packages/colorama/tests/winterm_test.py new file mode 100644 index 0000000..d0955f9 --- /dev/null +++ b/backend/venv/Lib/site-packages/colorama/tests/winterm_test.py @@ -0,0 +1,131 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +import sys +from unittest import TestCase, main, skipUnless + +try: + from unittest.mock import Mock, patch +except ImportError: + from mock import Mock, patch + +from ..winterm import WinColor, WinStyle, WinTerm + + +class WinTermTest(TestCase): + + @patch('colorama.winterm.win32') + def testInit(self, mockWin32): + mockAttr = Mock() + mockAttr.wAttributes = 7 + 6 * 16 + 8 + mockWin32.GetConsoleScreenBufferInfo.return_value = mockAttr + term = WinTerm() + self.assertEqual(term._fore, 7) + self.assertEqual(term._back, 6) + self.assertEqual(term._style, 8) + + @skipUnless(sys.platform.startswith("win"), "requires Windows") + def testGetAttrs(self): + term = WinTerm() + + term._fore = 0 + term._back = 0 + term._style = 0 + self.assertEqual(term.get_attrs(), 0) + + term._fore = WinColor.YELLOW + self.assertEqual(term.get_attrs(), WinColor.YELLOW) + + term._back = WinColor.MAGENTA + self.assertEqual( + term.get_attrs(), + WinColor.YELLOW + WinColor.MAGENTA * 16) + + term._style = WinStyle.BRIGHT + self.assertEqual( + term.get_attrs(), + WinColor.YELLOW + WinColor.MAGENTA * 16 + WinStyle.BRIGHT) + + @patch('colorama.winterm.win32') + def testResetAll(self, mockWin32): + mockAttr = Mock() + mockAttr.wAttributes = 1 + 2 * 16 + 8 + mockWin32.GetConsoleScreenBufferInfo.return_value = mockAttr + term = WinTerm() + + term.set_console = Mock() + term._fore = -1 + term._back = -1 + term._style = -1 + + term.reset_all() + + self.assertEqual(term._fore, 1) + self.assertEqual(term._back, 2) + self.assertEqual(term._style, 8) + self.assertEqual(term.set_console.called, True) + + @skipUnless(sys.platform.startswith("win"), "requires Windows") + def testFore(self): + term = WinTerm() + term.set_console = Mock() + term._fore = 0 + + term.fore(5) + + self.assertEqual(term._fore, 5) + self.assertEqual(term.set_console.called, True) + + @skipUnless(sys.platform.startswith("win"), "requires Windows") + def testBack(self): + term = WinTerm() + term.set_console = Mock() + term._back = 0 + + term.back(5) + + self.assertEqual(term._back, 5) + self.assertEqual(term.set_console.called, True) + + @skipUnless(sys.platform.startswith("win"), "requires Windows") + def testStyle(self): + term = WinTerm() + term.set_console = Mock() + term._style = 0 + + term.style(22) + + self.assertEqual(term._style, 22) + self.assertEqual(term.set_console.called, True) + + @patch('colorama.winterm.win32') + def testSetConsole(self, mockWin32): + mockAttr = Mock() + mockAttr.wAttributes = 0 + mockWin32.GetConsoleScreenBufferInfo.return_value = mockAttr + term = WinTerm() + term.windll = Mock() + + term.set_console() + + self.assertEqual( + mockWin32.SetConsoleTextAttribute.call_args, + ((mockWin32.STDOUT, term.get_attrs()), {}) + ) + + @patch('colorama.winterm.win32') + def testSetConsoleOnStderr(self, mockWin32): + mockAttr = Mock() + mockAttr.wAttributes = 0 + mockWin32.GetConsoleScreenBufferInfo.return_value = mockAttr + term = WinTerm() + term.windll = Mock() + + term.set_console(on_stderr=True) + + self.assertEqual( + mockWin32.SetConsoleTextAttribute.call_args, + ((mockWin32.STDERR, term.get_attrs()), {}) + ) + + +if __name__ == '__main__': + main() diff --git a/backend/venv/Lib/site-packages/colorama/win32.py b/backend/venv/Lib/site-packages/colorama/win32.py new file mode 100644 index 0000000..841b0e2 --- /dev/null +++ b/backend/venv/Lib/site-packages/colorama/win32.py @@ -0,0 +1,180 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. + +# from winbase.h +STDOUT = -11 +STDERR = -12 + +ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004 + +try: + import ctypes + from ctypes import LibraryLoader + windll = LibraryLoader(ctypes.WinDLL) + from ctypes import wintypes +except (AttributeError, ImportError): + windll = None + SetConsoleTextAttribute = lambda *_: None + winapi_test = lambda *_: None +else: + from ctypes import byref, Structure, c_char, POINTER + + COORD = wintypes._COORD + + class CONSOLE_SCREEN_BUFFER_INFO(Structure): + """struct in wincon.h.""" + _fields_ = [ + ("dwSize", COORD), + ("dwCursorPosition", COORD), + ("wAttributes", wintypes.WORD), + ("srWindow", wintypes.SMALL_RECT), + ("dwMaximumWindowSize", COORD), + ] + def __str__(self): + return '(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)' % ( + self.dwSize.Y, self.dwSize.X + , self.dwCursorPosition.Y, self.dwCursorPosition.X + , self.wAttributes + , self.srWindow.Top, self.srWindow.Left, self.srWindow.Bottom, self.srWindow.Right + , self.dwMaximumWindowSize.Y, self.dwMaximumWindowSize.X + ) + + _GetStdHandle = windll.kernel32.GetStdHandle + _GetStdHandle.argtypes = [ + wintypes.DWORD, + ] + _GetStdHandle.restype = wintypes.HANDLE + + _GetConsoleScreenBufferInfo = windll.kernel32.GetConsoleScreenBufferInfo + _GetConsoleScreenBufferInfo.argtypes = [ + wintypes.HANDLE, + POINTER(CONSOLE_SCREEN_BUFFER_INFO), + ] + _GetConsoleScreenBufferInfo.restype = wintypes.BOOL + + _SetConsoleTextAttribute = windll.kernel32.SetConsoleTextAttribute + _SetConsoleTextAttribute.argtypes = [ + wintypes.HANDLE, + wintypes.WORD, + ] + _SetConsoleTextAttribute.restype = wintypes.BOOL + + _SetConsoleCursorPosition = windll.kernel32.SetConsoleCursorPosition + _SetConsoleCursorPosition.argtypes = [ + wintypes.HANDLE, + COORD, + ] + _SetConsoleCursorPosition.restype = wintypes.BOOL + + _FillConsoleOutputCharacterA = windll.kernel32.FillConsoleOutputCharacterA + _FillConsoleOutputCharacterA.argtypes = [ + wintypes.HANDLE, + c_char, + wintypes.DWORD, + COORD, + POINTER(wintypes.DWORD), + ] + _FillConsoleOutputCharacterA.restype = wintypes.BOOL + + _FillConsoleOutputAttribute = windll.kernel32.FillConsoleOutputAttribute + _FillConsoleOutputAttribute.argtypes = [ + wintypes.HANDLE, + wintypes.WORD, + wintypes.DWORD, + COORD, + POINTER(wintypes.DWORD), + ] + _FillConsoleOutputAttribute.restype = wintypes.BOOL + + _SetConsoleTitleW = windll.kernel32.SetConsoleTitleW + _SetConsoleTitleW.argtypes = [ + wintypes.LPCWSTR + ] + _SetConsoleTitleW.restype = wintypes.BOOL + + _GetConsoleMode = windll.kernel32.GetConsoleMode + _GetConsoleMode.argtypes = [ + wintypes.HANDLE, + POINTER(wintypes.DWORD) + ] + _GetConsoleMode.restype = wintypes.BOOL + + _SetConsoleMode = windll.kernel32.SetConsoleMode + _SetConsoleMode.argtypes = [ + wintypes.HANDLE, + wintypes.DWORD + ] + _SetConsoleMode.restype = wintypes.BOOL + + def _winapi_test(handle): + csbi = CONSOLE_SCREEN_BUFFER_INFO() + success = _GetConsoleScreenBufferInfo( + handle, byref(csbi)) + return bool(success) + + def winapi_test(): + return any(_winapi_test(h) for h in + (_GetStdHandle(STDOUT), _GetStdHandle(STDERR))) + + def GetConsoleScreenBufferInfo(stream_id=STDOUT): + handle = _GetStdHandle(stream_id) + csbi = CONSOLE_SCREEN_BUFFER_INFO() + success = _GetConsoleScreenBufferInfo( + handle, byref(csbi)) + return csbi + + def SetConsoleTextAttribute(stream_id, attrs): + handle = _GetStdHandle(stream_id) + return _SetConsoleTextAttribute(handle, attrs) + + def SetConsoleCursorPosition(stream_id, position, adjust=True): + position = COORD(*position) + # If the position is out of range, do nothing. + if position.Y <= 0 or position.X <= 0: + return + # Adjust for Windows' SetConsoleCursorPosition: + # 1. being 0-based, while ANSI is 1-based. + # 2. expecting (x,y), while ANSI uses (y,x). + adjusted_position = COORD(position.Y - 1, position.X - 1) + if adjust: + # Adjust for viewport's scroll position + sr = GetConsoleScreenBufferInfo(STDOUT).srWindow + adjusted_position.Y += sr.Top + adjusted_position.X += sr.Left + # Resume normal processing + handle = _GetStdHandle(stream_id) + return _SetConsoleCursorPosition(handle, adjusted_position) + + def FillConsoleOutputCharacter(stream_id, char, length, start): + handle = _GetStdHandle(stream_id) + char = c_char(char.encode()) + length = wintypes.DWORD(length) + num_written = wintypes.DWORD(0) + # Note that this is hard-coded for ANSI (vs wide) bytes. + success = _FillConsoleOutputCharacterA( + handle, char, length, start, byref(num_written)) + return num_written.value + + def FillConsoleOutputAttribute(stream_id, attr, length, start): + ''' FillConsoleOutputAttribute( hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten )''' + handle = _GetStdHandle(stream_id) + attribute = wintypes.WORD(attr) + length = wintypes.DWORD(length) + num_written = wintypes.DWORD(0) + # Note that this is hard-coded for ANSI (vs wide) bytes. + return _FillConsoleOutputAttribute( + handle, attribute, length, start, byref(num_written)) + + def SetConsoleTitle(title): + return _SetConsoleTitleW(title) + + def GetConsoleMode(handle): + mode = wintypes.DWORD() + success = _GetConsoleMode(handle, byref(mode)) + if not success: + raise ctypes.WinError() + return mode.value + + def SetConsoleMode(handle, mode): + success = _SetConsoleMode(handle, mode) + if not success: + raise ctypes.WinError() diff --git a/backend/venv/Lib/site-packages/colorama/winterm.py b/backend/venv/Lib/site-packages/colorama/winterm.py new file mode 100644 index 0000000..aad867e --- /dev/null +++ b/backend/venv/Lib/site-packages/colorama/winterm.py @@ -0,0 +1,195 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +try: + from msvcrt import get_osfhandle +except ImportError: + def get_osfhandle(_): + raise OSError("This isn't windows!") + + +from . import win32 + +# from wincon.h +class WinColor(object): + BLACK = 0 + BLUE = 1 + GREEN = 2 + CYAN = 3 + RED = 4 + MAGENTA = 5 + YELLOW = 6 + GREY = 7 + +# from wincon.h +class WinStyle(object): + NORMAL = 0x00 # dim text, dim background + BRIGHT = 0x08 # bright text, dim background + BRIGHT_BACKGROUND = 0x80 # dim text, bright background + +class WinTerm(object): + + def __init__(self): + self._default = win32.GetConsoleScreenBufferInfo(win32.STDOUT).wAttributes + self.set_attrs(self._default) + self._default_fore = self._fore + self._default_back = self._back + self._default_style = self._style + # In order to emulate LIGHT_EX in windows, we borrow the BRIGHT style. + # So that LIGHT_EX colors and BRIGHT style do not clobber each other, + # we track them separately, since LIGHT_EX is overwritten by Fore/Back + # and BRIGHT is overwritten by Style codes. + self._light = 0 + + def get_attrs(self): + return self._fore + self._back * 16 + (self._style | self._light) + + def set_attrs(self, value): + self._fore = value & 7 + self._back = (value >> 4) & 7 + self._style = value & (WinStyle.BRIGHT | WinStyle.BRIGHT_BACKGROUND) + + def reset_all(self, on_stderr=None): + self.set_attrs(self._default) + self.set_console(attrs=self._default) + self._light = 0 + + def fore(self, fore=None, light=False, on_stderr=False): + if fore is None: + fore = self._default_fore + self._fore = fore + # Emulate LIGHT_EX with BRIGHT Style + if light: + self._light |= WinStyle.BRIGHT + else: + self._light &= ~WinStyle.BRIGHT + self.set_console(on_stderr=on_stderr) + + def back(self, back=None, light=False, on_stderr=False): + if back is None: + back = self._default_back + self._back = back + # Emulate LIGHT_EX with BRIGHT_BACKGROUND Style + if light: + self._light |= WinStyle.BRIGHT_BACKGROUND + else: + self._light &= ~WinStyle.BRIGHT_BACKGROUND + self.set_console(on_stderr=on_stderr) + + def style(self, style=None, on_stderr=False): + if style is None: + style = self._default_style + self._style = style + self.set_console(on_stderr=on_stderr) + + def set_console(self, attrs=None, on_stderr=False): + if attrs is None: + attrs = self.get_attrs() + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + win32.SetConsoleTextAttribute(handle, attrs) + + def get_position(self, handle): + position = win32.GetConsoleScreenBufferInfo(handle).dwCursorPosition + # Because Windows coordinates are 0-based, + # and win32.SetConsoleCursorPosition expects 1-based. + position.X += 1 + position.Y += 1 + return position + + def set_cursor_position(self, position=None, on_stderr=False): + if position is None: + # I'm not currently tracking the position, so there is no default. + # position = self.get_position() + return + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + win32.SetConsoleCursorPosition(handle, position) + + def cursor_adjust(self, x, y, on_stderr=False): + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + position = self.get_position(handle) + adjusted_position = (position.Y + y, position.X + x) + win32.SetConsoleCursorPosition(handle, adjusted_position, adjust=False) + + def erase_screen(self, mode=0, on_stderr=False): + # 0 should clear from the cursor to the end of the screen. + # 1 should clear from the cursor to the beginning of the screen. + # 2 should clear the entire screen, and move cursor to (1,1) + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + csbi = win32.GetConsoleScreenBufferInfo(handle) + # get the number of character cells in the current buffer + cells_in_screen = csbi.dwSize.X * csbi.dwSize.Y + # get number of character cells before current cursor position + cells_before_cursor = csbi.dwSize.X * csbi.dwCursorPosition.Y + csbi.dwCursorPosition.X + if mode == 0: + from_coord = csbi.dwCursorPosition + cells_to_erase = cells_in_screen - cells_before_cursor + elif mode == 1: + from_coord = win32.COORD(0, 0) + cells_to_erase = cells_before_cursor + elif mode == 2: + from_coord = win32.COORD(0, 0) + cells_to_erase = cells_in_screen + else: + # invalid mode + return + # fill the entire screen with blanks + win32.FillConsoleOutputCharacter(handle, ' ', cells_to_erase, from_coord) + # now set the buffer's attributes accordingly + win32.FillConsoleOutputAttribute(handle, self.get_attrs(), cells_to_erase, from_coord) + if mode == 2: + # put the cursor where needed + win32.SetConsoleCursorPosition(handle, (1, 1)) + + def erase_line(self, mode=0, on_stderr=False): + # 0 should clear from the cursor to the end of the line. + # 1 should clear from the cursor to the beginning of the line. + # 2 should clear the entire line. + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + csbi = win32.GetConsoleScreenBufferInfo(handle) + if mode == 0: + from_coord = csbi.dwCursorPosition + cells_to_erase = csbi.dwSize.X - csbi.dwCursorPosition.X + elif mode == 1: + from_coord = win32.COORD(0, csbi.dwCursorPosition.Y) + cells_to_erase = csbi.dwCursorPosition.X + elif mode == 2: + from_coord = win32.COORD(0, csbi.dwCursorPosition.Y) + cells_to_erase = csbi.dwSize.X + else: + # invalid mode + return + # fill the entire screen with blanks + win32.FillConsoleOutputCharacter(handle, ' ', cells_to_erase, from_coord) + # now set the buffer's attributes accordingly + win32.FillConsoleOutputAttribute(handle, self.get_attrs(), cells_to_erase, from_coord) + + def set_title(self, title): + win32.SetConsoleTitle(title) + + +def enable_vt_processing(fd): + if win32.windll is None or not win32.winapi_test(): + return False + + try: + handle = get_osfhandle(fd) + mode = win32.GetConsoleMode(handle) + win32.SetConsoleMode( + handle, + mode | win32.ENABLE_VIRTUAL_TERMINAL_PROCESSING, + ) + + mode = win32.GetConsoleMode(handle) + if mode & win32.ENABLE_VIRTUAL_TERMINAL_PROCESSING: + return True + # Can get TypeError in testsuite where 'fd' is a Mock() + except (OSError, TypeError): + return False diff --git a/backend/venv/Lib/site-packages/dotenv/__init__.py b/backend/venv/Lib/site-packages/dotenv/__init__.py new file mode 100644 index 0000000..7f4c631 --- /dev/null +++ b/backend/venv/Lib/site-packages/dotenv/__init__.py @@ -0,0 +1,49 @@ +from typing import Any, Optional + +from .main import (dotenv_values, find_dotenv, get_key, load_dotenv, set_key, + unset_key) + + +def load_ipython_extension(ipython: Any) -> None: + from .ipython import load_ipython_extension + load_ipython_extension(ipython) + + +def get_cli_string( + path: Optional[str] = None, + action: Optional[str] = None, + key: Optional[str] = None, + value: Optional[str] = None, + quote: Optional[str] = None, +): + """Returns a string suitable for running as a shell script. + + Useful for converting a arguments passed to a fabric task + to be passed to a `local` or `run` command. + """ + command = ['dotenv'] + if quote: + command.append(f'-q {quote}') + if path: + command.append(f'-f {path}') + if action: + command.append(action) + if key: + command.append(key) + if value: + if ' ' in value: + command.append(f'"{value}"') + else: + command.append(value) + + return ' '.join(command).strip() + + +__all__ = ['get_cli_string', + 'load_dotenv', + 'dotenv_values', + 'get_key', + 'set_key', + 'unset_key', + 'find_dotenv', + 'load_ipython_extension'] diff --git a/backend/venv/Lib/site-packages/dotenv/__main__.py b/backend/venv/Lib/site-packages/dotenv/__main__.py new file mode 100644 index 0000000..3977f55 --- /dev/null +++ b/backend/venv/Lib/site-packages/dotenv/__main__.py @@ -0,0 +1,6 @@ +"""Entry point for cli, enables execution with `python -m dotenv`""" + +from .cli import cli + +if __name__ == "__main__": + cli() diff --git a/backend/venv/Lib/site-packages/dotenv/__pycache__/__init__.cpython-312.pyc b/backend/venv/Lib/site-packages/dotenv/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7e112d9c2a842b0353aeeaab493ba861ed8814cb GIT binary patch literal 1706 zcmZ`(&ube;6rS1N(n_)ut8P*!@#5G8QS1Z<(@@+%v8gYqQpe3j2-a)ONM37yWp<@j zVGS<$P@Sw4N(3QbdP+$DlU`clP-&sm&_c;gtq&-r{YcAlPC-w55V%%LUn1 z3W}X5BhsM9mqxvgtK~P1lJef`b}y@+FpjXgqb;=SZVKC4z`!5^X~WI1s`RJRh(j zXn-7_CsbpQgVA_gc92@fU(rT=+Wa$)Fww~fgHZ}TM?us6MN1zQ@A;Vc#rf;=^VQ-V z2QL$|j*H9KuLiDHynAQu^V`KQF|IBYiR*jTLUF?=Rk4GLbt*#fwz*OC%>d7OG-_0^ zU+gP!P1jAw40L_YYxK*q+A=GhrmzEk6|QxK_u3!66s{i80Eh(72sR_hC^5Aoo{1>N z5=Y|w8dbc+jyN>t$NDT&9hg29xGjbP$%f+AX&ncA#D&6R@Ps>2Ed+1n@*#MG3(4x) zc|&+ABS&t%g>||vPd-3G$kzcGKbwujkbex2_=G>n?VLNC8=m4IVT&p9hK1rV%hqZA z2CV0U=Ng^s2S4162hrCI%@2s_R5ZV42F8YkwX#bzQga*@G-ARgwk*vr5z`Cil1Ysk z9iwv1im4^nsbdnvY|S8*nvI>n*F3}bG13B;Rwx@A#4Krn;aB5t)8GdFA7kBeONOV-P}lQ2!r)6Q~A+$l*=pRh9#g#r6NCMpAV3*$SP6Z6b+nMev69{srpn;;@khy>d( zo&MKjew-std6I}->4>N5#04W+*A2_k^=BaNqc5VeXuGIp;alW=%4T=d-=)ywA%wpH z?X>{mmDhkmPvPM7{!$On$J6B__UNU+#AN4^*134OL!F7qztjmh(@CCh-DuACc?e1?(#p=l$LY= literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/dotenv/__pycache__/__main__.cpython-312.pyc b/backend/venv/Lib/site-packages/dotenv/__pycache__/__main__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..802f8fc449daf730a2a7ec8add316a3c97c81980 GIT binary patch literal 370 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 y8hB5>DL46nC-BPy|ELzYO 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 TZ0G6^)^29@4QykXMlSyYR>Eip literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/dotenv/__pycache__/variables.cpython-312.pyc b/backend/venv/Lib/site-packages/dotenv/__pycache__/variables.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..43a338f9b737ed70cd51a18c934a5f4237411fc0 GIT binary patch literal 5038 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 n%3B;Zx%nxjIjMF Optional[str]: + """ + Return a path for the ${pwd}/.env file. + + If pwd does not exist, return None. + """ + try: + cwd = os.getcwd() + except FileNotFoundError: + return None + path = os.path.join(cwd, '.env') + return path + + +@click.group() +@click.option('-f', '--file', default=enumerate_env(), + type=click.Path(file_okay=True), + help="Location of the .env file, defaults to .env file in current working directory.") +@click.option('-q', '--quote', default='always', + type=click.Choice(['always', 'never', 'auto']), + help="Whether to quote or not the variable values. Default mode is always. This does not affect parsing.") +@click.option('-e', '--export', default=False, + type=click.BOOL, + help="Whether to write the dot file as an executable bash script.") +@click.version_option(version=__version__) +@click.pass_context +def cli(ctx: click.Context, file: Any, quote: Any, export: Any) -> None: + """This script is used to set, get or unset values from a .env file.""" + ctx.obj = {'QUOTE': quote, 'EXPORT': export, 'FILE': file} + + +@contextmanager +def stream_file(path: os.PathLike) -> Iterator[IO[str]]: + """ + Open a file and yield the corresponding (decoded) stream. + + Exits with error code 2 if the file cannot be opened. + """ + + try: + with open(path) as stream: + yield stream + except OSError as exc: + print(f"Error opening env file: {exc}", file=sys.stderr) + exit(2) + + +@cli.command() +@click.pass_context +@click.option('--format', default='simple', + type=click.Choice(['simple', 'json', 'shell', 'export']), + help="The format in which to display the list. Default format is simple, " + "which displays name=value without quotes.") +def list(ctx: click.Context, format: bool) -> None: + """Display all the stored key/value.""" + file = ctx.obj['FILE'] + + with stream_file(file) as stream: + values = dotenv_values(stream=stream) + + if format == 'json': + click.echo(json.dumps(values, indent=2, sort_keys=True)) + else: + prefix = 'export ' if format == 'export' else '' + for k in sorted(values): + v = values[k] + if v is not None: + if format in ('export', 'shell'): + v = shlex.quote(v) + click.echo(f'{prefix}{k}={v}') + + +@cli.command() +@click.pass_context +@click.argument('key', required=True) +@click.argument('value', required=True) +def set(ctx: click.Context, key: Any, value: Any) -> None: + """Store the given key/value.""" + file = ctx.obj['FILE'] + quote = ctx.obj['QUOTE'] + export = ctx.obj['EXPORT'] + success, key, value = set_key(file, key, value, quote, export) + if success: + click.echo(f'{key}={value}') + else: + exit(1) + + +@cli.command() +@click.pass_context +@click.argument('key', required=True) +def get(ctx: click.Context, key: Any) -> None: + """Retrieve the value for the given key.""" + file = ctx.obj['FILE'] + + with stream_file(file) as stream: + values = dotenv_values(stream=stream) + + stored_value = values.get(key) + if stored_value: + click.echo(stored_value) + else: + exit(1) + + +@cli.command() +@click.pass_context +@click.argument('key', required=True) +def unset(ctx: click.Context, key: Any) -> None: + """Removes the given key.""" + file = ctx.obj['FILE'] + quote = ctx.obj['QUOTE'] + success, key = unset_key(file, key, quote) + if success: + click.echo(f"Successfully removed {key}") + else: + exit(1) + + +@cli.command(context_settings={'ignore_unknown_options': True}) +@click.pass_context +@click.option( + "--override/--no-override", + default=True, + help="Override variables from the environment file with those from the .env file.", +) +@click.argument('commandline', nargs=-1, type=click.UNPROCESSED) +def run(ctx: click.Context, override: bool, commandline: List[str]) -> None: + """Run command with environment variables present.""" + file = ctx.obj['FILE'] + if not os.path.isfile(file): + raise click.BadParameter( + f'Invalid value for \'-f\' "{file}" does not exist.', + ctx=ctx + ) + dotenv_as_dict = { + k: v + for (k, v) in dotenv_values(file).items() + if v is not None and (override or k not in os.environ) + } + + if not commandline: + click.echo('No command given.') + exit(1) + run_command(commandline, dotenv_as_dict) + + +def run_command(command: List[str], env: Dict[str, str]) -> None: + """Replace the current process with the specified command. + + Replaces the current process with the specified command and the variables from `env` + added in the current environment variables. + + Parameters + ---------- + command: List[str] + The command and it's parameters + env: Dict + The additional environment variables + + Returns + ------- + None + This function does not return any value. It replaces the current process with the new one. + + """ + # copy the current environment variables and add the vales from + # `env` + cmd_env = os.environ.copy() + cmd_env.update(env) + + if sys.platform == 'win32': + # execvpe on Windows returns control immediately + # rather than once the command has finished. + p = Popen(command, + universal_newlines=True, + bufsize=0, + shell=False, + env=cmd_env) + _, _ = p.communicate() + + exit(p.returncode) + else: + os.execvpe(command[0], args=command, env=cmd_env) diff --git a/backend/venv/Lib/site-packages/dotenv/ipython.py b/backend/venv/Lib/site-packages/dotenv/ipython.py new file mode 100644 index 0000000..7df727c --- /dev/null +++ b/backend/venv/Lib/site-packages/dotenv/ipython.py @@ -0,0 +1,39 @@ +from IPython.core.magic import Magics, line_magic, magics_class # type: ignore +from IPython.core.magic_arguments import (argument, magic_arguments, # type: ignore + parse_argstring) # type: ignore + +from .main import find_dotenv, load_dotenv + + +@magics_class +class IPythonDotEnv(Magics): + + @magic_arguments() + @argument( + '-o', '--override', action='store_true', + help="Indicate to override existing variables" + ) + @argument( + '-v', '--verbose', action='store_true', + help="Indicate function calls to be verbose" + ) + @argument('dotenv_path', nargs='?', type=str, default='.env', + help='Search in increasingly higher folders for the `dotenv_path`') + @line_magic + def dotenv(self, line): + args = parse_argstring(self.dotenv, line) + # Locate the .env file + dotenv_path = args.dotenv_path + try: + dotenv_path = find_dotenv(dotenv_path, True, True) + except IOError: + print("cannot find .env file") + return + + # Load the .env file + load_dotenv(dotenv_path, verbose=args.verbose, override=args.override) + + +def load_ipython_extension(ipython): + """Register the %dotenv magic.""" + ipython.register_magics(IPythonDotEnv) diff --git a/backend/venv/Lib/site-packages/dotenv/main.py b/backend/venv/Lib/site-packages/dotenv/main.py new file mode 100644 index 0000000..8e6a7cf --- /dev/null +++ b/backend/venv/Lib/site-packages/dotenv/main.py @@ -0,0 +1,400 @@ +import io +import logging +import os +import pathlib +import shutil +import sys +import tempfile +from collections import OrderedDict +from contextlib import contextmanager +from typing import IO, Dict, Iterable, Iterator, Mapping, Optional, Tuple, Union + +from .parser import Binding, parse_stream +from .variables import parse_variables + +# A type alias for a string path to be used for the paths in this file. +# These paths may flow to `open()` and `shutil.move()`; `shutil.move()` +# only accepts string paths, not byte paths or file descriptors. See +# https://github.com/python/typeshed/pull/6832. +StrPath = Union[str, "os.PathLike[str]"] + +logger = logging.getLogger(__name__) + + +def with_warn_for_invalid_lines(mappings: Iterator[Binding]) -> Iterator[Binding]: + for mapping in mappings: + if mapping.error: + logger.warning( + "python-dotenv could not parse statement starting at line %s", + mapping.original.line, + ) + yield mapping + + +class DotEnv: + def __init__( + self, + dotenv_path: Optional[StrPath], + stream: Optional[IO[str]] = None, + verbose: bool = False, + encoding: Optional[str] = None, + interpolate: bool = True, + override: bool = True, + ) -> None: + self.dotenv_path: Optional[StrPath] = dotenv_path + self.stream: Optional[IO[str]] = stream + self._dict: Optional[Dict[str, Optional[str]]] = None + self.verbose: bool = verbose + self.encoding: Optional[str] = encoding + self.interpolate: bool = interpolate + self.override: bool = override + + @contextmanager + def _get_stream(self) -> Iterator[IO[str]]: + if self.dotenv_path and os.path.isfile(self.dotenv_path): + with open(self.dotenv_path, encoding=self.encoding) as stream: + yield stream + elif self.stream is not None: + yield self.stream + else: + if self.verbose: + logger.info( + "python-dotenv could not find configuration file %s.", + self.dotenv_path or ".env", + ) + yield io.StringIO("") + + def dict(self) -> Dict[str, Optional[str]]: + """Return dotenv as dict""" + if self._dict: + return self._dict + + raw_values = self.parse() + + if self.interpolate: + self._dict = OrderedDict( + resolve_variables(raw_values, override=self.override) + ) + else: + self._dict = OrderedDict(raw_values) + + return self._dict + + def parse(self) -> Iterator[Tuple[str, Optional[str]]]: + with self._get_stream() as stream: + for mapping in with_warn_for_invalid_lines(parse_stream(stream)): + if mapping.key is not None: + yield mapping.key, mapping.value + + def set_as_environment_variables(self) -> bool: + """ + Load the current dotenv as system environment variable. + """ + if not self.dict(): + return False + + for k, v in self.dict().items(): + if k in os.environ and not self.override: + continue + if v is not None: + os.environ[k] = v + + return True + + def get(self, key: str) -> Optional[str]: + """ """ + data = self.dict() + + if key in data: + return data[key] + + if self.verbose: + logger.warning("Key %s not found in %s.", key, self.dotenv_path) + + return None + + +def get_key( + dotenv_path: StrPath, + key_to_get: str, + encoding: Optional[str] = "utf-8", +) -> Optional[str]: + """ + Get the value of a given key from the given .env. + + Returns `None` if the key isn't found or doesn't have a value. + """ + return DotEnv(dotenv_path, verbose=True, encoding=encoding).get(key_to_get) + + +@contextmanager +def rewrite( + path: StrPath, + encoding: Optional[str], +) -> Iterator[Tuple[IO[str], IO[str]]]: + pathlib.Path(path).touch() + + with tempfile.NamedTemporaryFile(mode="w", encoding=encoding, delete=False) as dest: + error = None + try: + with open(path, encoding=encoding) as source: + yield (source, dest) + except BaseException as err: + error = err + + if error is None: + shutil.move(dest.name, path) + else: + os.unlink(dest.name) + raise error from None + + +def set_key( + dotenv_path: StrPath, + key_to_set: str, + value_to_set: str, + quote_mode: str = "always", + export: bool = False, + encoding: Optional[str] = "utf-8", +) -> Tuple[Optional[bool], str, str]: + """ + Adds or Updates a key/value to the given .env + + If the .env path given doesn't exist, fails instead of risking creating + an orphan .env somewhere in the filesystem + """ + if quote_mode not in ("always", "auto", "never"): + raise ValueError(f"Unknown quote_mode: {quote_mode}") + + quote = quote_mode == "always" or ( + quote_mode == "auto" and not value_to_set.isalnum() + ) + + if quote: + value_out = "'{}'".format(value_to_set.replace("'", "\\'")) + else: + value_out = value_to_set + if export: + line_out = f"export {key_to_set}={value_out}\n" + else: + line_out = f"{key_to_set}={value_out}\n" + + with rewrite(dotenv_path, encoding=encoding) as (source, dest): + replaced = False + missing_newline = False + for mapping in with_warn_for_invalid_lines(parse_stream(source)): + if mapping.key == key_to_set: + dest.write(line_out) + replaced = True + else: + dest.write(mapping.original.string) + missing_newline = not mapping.original.string.endswith("\n") + if not replaced: + if missing_newline: + dest.write("\n") + dest.write(line_out) + + return True, key_to_set, value_to_set + + +def unset_key( + dotenv_path: StrPath, + key_to_unset: str, + quote_mode: str = "always", + encoding: Optional[str] = "utf-8", +) -> Tuple[Optional[bool], str]: + """ + Removes a given key from the given `.env` file. + + If the .env path given doesn't exist, fails. + If the given key doesn't exist in the .env, fails. + """ + if not os.path.exists(dotenv_path): + logger.warning("Can't delete from %s - it doesn't exist.", dotenv_path) + return None, key_to_unset + + removed = False + with rewrite(dotenv_path, encoding=encoding) as (source, dest): + for mapping in with_warn_for_invalid_lines(parse_stream(source)): + if mapping.key == key_to_unset: + removed = True + else: + dest.write(mapping.original.string) + + if not removed: + logger.warning( + "Key %s not removed from %s - key doesn't exist.", key_to_unset, dotenv_path + ) + return None, key_to_unset + + return removed, key_to_unset + + +def resolve_variables( + values: Iterable[Tuple[str, Optional[str]]], + override: bool, +) -> Mapping[str, Optional[str]]: + new_values: Dict[str, Optional[str]] = {} + + for name, value in values: + if value is None: + result = None + else: + atoms = parse_variables(value) + env: Dict[str, Optional[str]] = {} + if override: + env.update(os.environ) # type: ignore + env.update(new_values) + else: + env.update(new_values) + env.update(os.environ) # type: ignore + result = "".join(atom.resolve(env) for atom in atoms) + + new_values[name] = result + + return new_values + + +def _walk_to_root(path: str) -> Iterator[str]: + """ + Yield directories starting from the given directory up to the root + """ + if not os.path.exists(path): + raise IOError("Starting path not found") + + if os.path.isfile(path): + path = os.path.dirname(path) + + last_dir = None + current_dir = os.path.abspath(path) + while last_dir != current_dir: + yield current_dir + parent_dir = os.path.abspath(os.path.join(current_dir, os.path.pardir)) + last_dir, current_dir = current_dir, parent_dir + + +def find_dotenv( + filename: str = ".env", + raise_error_if_not_found: bool = False, + usecwd: bool = False, +) -> str: + """ + Search in increasingly higher folders for the given file + + Returns path to the file if found, or an empty string otherwise + """ + + def _is_interactive(): + """Decide whether this is running in a REPL or IPython notebook""" + if hasattr(sys, "ps1") or hasattr(sys, "ps2"): + return True + try: + main = __import__("__main__", None, None, fromlist=["__file__"]) + except ModuleNotFoundError: + return False + return not hasattr(main, "__file__") + + def _is_debugger(): + return sys.gettrace() is not None + + if usecwd or _is_interactive() or _is_debugger() or getattr(sys, "frozen", False): + # Should work without __file__, e.g. in REPL or IPython notebook. + path = os.getcwd() + else: + # will work for .py files + frame = sys._getframe() + current_file = __file__ + + while frame.f_code.co_filename == current_file or not os.path.exists( + frame.f_code.co_filename + ): + assert frame.f_back is not None + frame = frame.f_back + frame_filename = frame.f_code.co_filename + path = os.path.dirname(os.path.abspath(frame_filename)) + + for dirname in _walk_to_root(path): + check_path = os.path.join(dirname, filename) + if os.path.isfile(check_path): + return check_path + + if raise_error_if_not_found: + raise IOError("File not found") + + return "" + + +def load_dotenv( + dotenv_path: Optional[StrPath] = None, + stream: Optional[IO[str]] = None, + verbose: bool = False, + override: bool = False, + interpolate: bool = True, + encoding: Optional[str] = "utf-8", +) -> bool: + """Parse a .env file and then load all the variables found as environment variables. + + Parameters: + dotenv_path: Absolute or relative path to .env file. + stream: Text stream (such as `io.StringIO`) with .env content, used if + `dotenv_path` is `None`. + verbose: Whether to output a warning the .env file is missing. + override: Whether to override the system environment variables with the variables + from the `.env` file. + encoding: Encoding to be used to read the file. + Returns: + Bool: True if at least one environment variable is set else False + + If both `dotenv_path` and `stream` are `None`, `find_dotenv()` is used to find the + .env file with it's default parameters. If you need to change the default parameters + of `find_dotenv()`, you can explicitly call `find_dotenv()` and pass the result + to this function as `dotenv_path`. + """ + if dotenv_path is None and stream is None: + dotenv_path = find_dotenv() + + dotenv = DotEnv( + dotenv_path=dotenv_path, + stream=stream, + verbose=verbose, + interpolate=interpolate, + override=override, + encoding=encoding, + ) + return dotenv.set_as_environment_variables() + + +def dotenv_values( + dotenv_path: Optional[StrPath] = None, + stream: Optional[IO[str]] = None, + verbose: bool = False, + interpolate: bool = True, + encoding: Optional[str] = "utf-8", +) -> Dict[str, Optional[str]]: + """ + Parse a .env file and return its content as a dict. + + The returned dict will have `None` values for keys without values in the .env file. + For example, `foo=bar` results in `{"foo": "bar"}` whereas `foo` alone results in + `{"foo": None}` + + Parameters: + dotenv_path: Absolute or relative path to the .env file. + stream: `StringIO` object with .env content, used if `dotenv_path` is `None`. + verbose: Whether to output a warning if the .env file is missing. + encoding: Encoding to be used to read the file. + + If both `dotenv_path` and `stream` are `None`, `find_dotenv()` is used to find the + .env file. + """ + if dotenv_path is None and stream is None: + dotenv_path = find_dotenv() + + return DotEnv( + dotenv_path=dotenv_path, + stream=stream, + verbose=verbose, + interpolate=interpolate, + override=True, + encoding=encoding, + ).dict() diff --git a/backend/venv/Lib/site-packages/dotenv/parser.py b/backend/venv/Lib/site-packages/dotenv/parser.py new file mode 100644 index 0000000..735f14a --- /dev/null +++ b/backend/venv/Lib/site-packages/dotenv/parser.py @@ -0,0 +1,175 @@ +import codecs +import re +from typing import (IO, Iterator, Match, NamedTuple, Optional, # noqa:F401 + Pattern, Sequence, Tuple) + + +def make_regex(string: str, extra_flags: int = 0) -> Pattern[str]: + return re.compile(string, re.UNICODE | extra_flags) + + +_newline = make_regex(r"(\r\n|\n|\r)") +_multiline_whitespace = make_regex(r"\s*", extra_flags=re.MULTILINE) +_whitespace = make_regex(r"[^\S\r\n]*") +_export = make_regex(r"(?:export[^\S\r\n]+)?") +_single_quoted_key = make_regex(r"'([^']+)'") +_unquoted_key = make_regex(r"([^=\#\s]+)") +_equal_sign = make_regex(r"(=[^\S\r\n]*)") +_single_quoted_value = make_regex(r"'((?:\\'|[^'])*)'") +_double_quoted_value = make_regex(r'"((?:\\"|[^"])*)"') +_unquoted_value = make_regex(r"([^\r\n]*)") +_comment = make_regex(r"(?:[^\S\r\n]*#[^\r\n]*)?") +_end_of_line = make_regex(r"[^\S\r\n]*(?:\r\n|\n|\r|$)") +_rest_of_line = make_regex(r"[^\r\n]*(?:\r|\n|\r\n)?") +_double_quote_escapes = make_regex(r"\\[\\'\"abfnrtv]") +_single_quote_escapes = make_regex(r"\\[\\']") + + +class Original(NamedTuple): + string: str + line: int + + +class Binding(NamedTuple): + key: Optional[str] + value: Optional[str] + original: Original + error: bool + + +class Position: + def __init__(self, chars: int, line: int) -> None: + self.chars = chars + self.line = line + + @classmethod + def start(cls) -> "Position": + return cls(chars=0, line=1) + + def set(self, other: "Position") -> None: + self.chars = other.chars + self.line = other.line + + def advance(self, string: str) -> None: + self.chars += len(string) + self.line += len(re.findall(_newline, string)) + + +class Error(Exception): + pass + + +class Reader: + def __init__(self, stream: IO[str]) -> None: + self.string = stream.read() + self.position = Position.start() + self.mark = Position.start() + + def has_next(self) -> bool: + return self.position.chars < len(self.string) + + def set_mark(self) -> None: + self.mark.set(self.position) + + def get_marked(self) -> Original: + return Original( + string=self.string[self.mark.chars:self.position.chars], + line=self.mark.line, + ) + + def peek(self, count: int) -> str: + return self.string[self.position.chars:self.position.chars + count] + + def read(self, count: int) -> str: + result = self.string[self.position.chars:self.position.chars + count] + if len(result) < count: + raise Error("read: End of string") + self.position.advance(result) + return result + + def read_regex(self, regex: Pattern[str]) -> Sequence[str]: + match = regex.match(self.string, self.position.chars) + if match is None: + raise Error("read_regex: Pattern not found") + self.position.advance(self.string[match.start():match.end()]) + return match.groups() + + +def decode_escapes(regex: Pattern[str], string: str) -> str: + def decode_match(match: Match[str]) -> str: + return codecs.decode(match.group(0), 'unicode-escape') # type: ignore + + return regex.sub(decode_match, string) + + +def parse_key(reader: Reader) -> Optional[str]: + char = reader.peek(1) + if char == "#": + return None + elif char == "'": + (key,) = reader.read_regex(_single_quoted_key) + else: + (key,) = reader.read_regex(_unquoted_key) + return key + + +def parse_unquoted_value(reader: Reader) -> str: + (part,) = reader.read_regex(_unquoted_value) + return re.sub(r"\s+#.*", "", part).rstrip() + + +def parse_value(reader: Reader) -> str: + char = reader.peek(1) + if char == u"'": + (value,) = reader.read_regex(_single_quoted_value) + return decode_escapes(_single_quote_escapes, value) + elif char == u'"': + (value,) = reader.read_regex(_double_quoted_value) + return decode_escapes(_double_quote_escapes, value) + elif char in (u"", u"\n", u"\r"): + return u"" + else: + return parse_unquoted_value(reader) + + +def parse_binding(reader: Reader) -> Binding: + reader.set_mark() + try: + reader.read_regex(_multiline_whitespace) + if not reader.has_next(): + return Binding( + key=None, + value=None, + original=reader.get_marked(), + error=False, + ) + reader.read_regex(_export) + key = parse_key(reader) + reader.read_regex(_whitespace) + if reader.peek(1) == "=": + reader.read_regex(_equal_sign) + value: Optional[str] = parse_value(reader) + else: + value = None + reader.read_regex(_comment) + reader.read_regex(_end_of_line) + return Binding( + key=key, + value=value, + original=reader.get_marked(), + error=False, + ) + except Error: + reader.read_regex(_rest_of_line) + return Binding( + key=None, + value=None, + original=reader.get_marked(), + error=True, + ) + + +def parse_stream(stream: IO[str]) -> Iterator[Binding]: + reader = Reader(stream) + while reader.has_next(): + yield parse_binding(reader) diff --git a/backend/venv/Lib/site-packages/dotenv/py.typed b/backend/venv/Lib/site-packages/dotenv/py.typed new file mode 100644 index 0000000..7632ecf --- /dev/null +++ b/backend/venv/Lib/site-packages/dotenv/py.typed @@ -0,0 +1 @@ +# Marker file for PEP 561 diff --git a/backend/venv/Lib/site-packages/dotenv/variables.py b/backend/venv/Lib/site-packages/dotenv/variables.py new file mode 100644 index 0000000..667f2f2 --- /dev/null +++ b/backend/venv/Lib/site-packages/dotenv/variables.py @@ -0,0 +1,86 @@ +import re +from abc import ABCMeta, abstractmethod +from typing import Iterator, Mapping, Optional, Pattern + +_posix_variable: Pattern[str] = re.compile( + r""" + \$\{ + (?P[^\}:]*) + (?::- + (?P[^\}]*) + )? + \} + """, + re.VERBOSE, +) + + +class Atom(metaclass=ABCMeta): + def __ne__(self, other: object) -> bool: + result = self.__eq__(other) + if result is NotImplemented: + return NotImplemented + return not result + + @abstractmethod + def resolve(self, env: Mapping[str, Optional[str]]) -> str: ... + + +class Literal(Atom): + def __init__(self, value: str) -> None: + self.value = value + + def __repr__(self) -> str: + return f"Literal(value={self.value})" + + def __eq__(self, other: object) -> bool: + if not isinstance(other, self.__class__): + return NotImplemented + return self.value == other.value + + def __hash__(self) -> int: + return hash((self.__class__, self.value)) + + def resolve(self, env: Mapping[str, Optional[str]]) -> str: + return self.value + + +class Variable(Atom): + def __init__(self, name: str, default: Optional[str]) -> None: + self.name = name + self.default = default + + def __repr__(self) -> str: + return f"Variable(name={self.name}, default={self.default})" + + def __eq__(self, other: object) -> bool: + if not isinstance(other, self.__class__): + return NotImplemented + return (self.name, self.default) == (other.name, other.default) + + def __hash__(self) -> int: + return hash((self.__class__, self.name, self.default)) + + def resolve(self, env: Mapping[str, Optional[str]]) -> str: + default = self.default if self.default is not None else "" + result = env.get(self.name, default) + return result if result is not None else "" + + +def parse_variables(value: str) -> Iterator[Atom]: + cursor = 0 + + for match in _posix_variable.finditer(value): + (start, end) = match.span() + name = match["name"] + default = match["default"] + + if start > cursor: + yield Literal(value=value[cursor:start]) + + yield Variable(name=name, default=default) + cursor = end + + length = len(value) + if cursor < length: + yield Literal(value=value[cursor:length]) diff --git a/backend/venv/Lib/site-packages/dotenv/version.py b/backend/venv/Lib/site-packages/dotenv/version.py new file mode 100644 index 0000000..a82b376 --- /dev/null +++ b/backend/venv/Lib/site-packages/dotenv/version.py @@ -0,0 +1 @@ +__version__ = "1.1.1" diff --git a/backend/venv/Lib/site-packages/flask-3.1.2.dist-info/INSTALLER b/backend/venv/Lib/site-packages/flask-3.1.2.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/backend/venv/Lib/site-packages/flask-3.1.2.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/backend/venv/Lib/site-packages/flask-3.1.2.dist-info/METADATA b/backend/venv/Lib/site-packages/flask-3.1.2.dist-info/METADATA new file mode 100644 index 0000000..46028fb --- /dev/null +++ b/backend/venv/Lib/site-packages/flask-3.1.2.dist-info/METADATA @@ -0,0 +1,91 @@ +Metadata-Version: 2.4 +Name: Flask +Version: 3.1.2 +Summary: A simple framework for building complex web applications. +Maintainer-email: Pallets +Requires-Python: >=3.9 +Description-Content-Type: text/markdown +License-Expression: BSD-3-Clause +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Framework :: Flask +Classifier: Intended Audience :: Developers +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Internet :: WWW/HTTP :: WSGI +Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application +Classifier: Topic :: Software Development :: Libraries :: Application Frameworks +Classifier: Typing :: Typed +License-File: LICENSE.txt +Requires-Dist: blinker>=1.9.0 +Requires-Dist: click>=8.1.3 +Requires-Dist: importlib-metadata>=3.6.0; python_version < '3.10' +Requires-Dist: itsdangerous>=2.2.0 +Requires-Dist: jinja2>=3.1.2 +Requires-Dist: markupsafe>=2.1.1 +Requires-Dist: werkzeug>=3.1.0 +Requires-Dist: asgiref>=3.2 ; extra == "async" +Requires-Dist: python-dotenv ; extra == "dotenv" +Project-URL: Changes, https://flask.palletsprojects.com/page/changes/ +Project-URL: Chat, https://discord.gg/pallets +Project-URL: Documentation, https://flask.palletsprojects.com/ +Project-URL: Donate, https://palletsprojects.com/donate +Project-URL: Source, https://github.com/pallets/flask/ +Provides-Extra: async +Provides-Extra: dotenv + +

+ +# Flask + +Flask is a lightweight [WSGI] web application framework. It is designed +to make getting started quick and easy, with the ability to scale up to +complex applications. It began as a simple wrapper around [Werkzeug] +and [Jinja], and has become one of the most popular Python web +application frameworks. + +Flask offers suggestions, but doesn't enforce any dependencies or +project layout. It is up to the developer to choose the tools and +libraries they want to use. There are many extensions provided by the +community that make adding new functionality easy. + +[WSGI]: https://wsgi.readthedocs.io/ +[Werkzeug]: https://werkzeug.palletsprojects.com/ +[Jinja]: https://jinja.palletsprojects.com/ + +## A Simple Example + +```python +# save this as app.py +from flask import Flask + +app = Flask(__name__) + +@app.route("/") +def hello(): + return "Hello, World!" +``` + +``` +$ flask run + * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) +``` + +## Donate + +The Pallets organization develops and supports Flask and the libraries +it uses. In order to grow the community of contributors and users, and +allow the maintainers to devote more time to the projects, [please +donate today]. + +[please donate today]: https://palletsprojects.com/donate + +## Contributing + +See our [detailed contributing documentation][contrib] for many ways to +contribute, including reporting issues, requesting features, asking or answering +questions, and making PRs. + +[contrib]: https://palletsprojects.com/contributing/ + diff --git a/backend/venv/Lib/site-packages/flask-3.1.2.dist-info/RECORD b/backend/venv/Lib/site-packages/flask-3.1.2.dist-info/RECORD new file mode 100644 index 0000000..70b8179 --- /dev/null +++ b/backend/venv/Lib/site-packages/flask-3.1.2.dist-info/RECORD @@ -0,0 +1,58 @@ +../../Scripts/flask.exe,sha256=1dcY4SlryXfQP235N0TWKhnCgypkc2eliwQzAyGiWkU,108428 +flask-3.1.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +flask-3.1.2.dist-info/METADATA,sha256=oRg63DAAIcoLAr7kzTgIEKfm8_4HMTRpmWmIptdY_js,3167 +flask-3.1.2.dist-info/RECORD,, +flask-3.1.2.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +flask-3.1.2.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82 +flask-3.1.2.dist-info/entry_points.txt,sha256=bBP7hTOS5fz9zLtC7sPofBZAlMkEvBxu7KqS6l5lvc4,40 +flask-3.1.2.dist-info/licenses/LICENSE.txt,sha256=SJqOEQhQntmKN7uYPhHg9-HTHwvY-Zp5yESOf_N9B-o,1475 +flask/__init__.py,sha256=mHvJN9Swtl1RDtjCqCIYyIniK_SZ_l_hqUynOzgpJ9o,2701 +flask/__main__.py,sha256=bYt9eEaoRQWdejEHFD8REx9jxVEdZptECFsV7F49Ink,30 +flask/__pycache__/__init__.cpython-312.pyc,, +flask/__pycache__/__main__.cpython-312.pyc,, +flask/__pycache__/app.cpython-312.pyc,, +flask/__pycache__/blueprints.cpython-312.pyc,, +flask/__pycache__/cli.cpython-312.pyc,, +flask/__pycache__/config.cpython-312.pyc,, +flask/__pycache__/ctx.cpython-312.pyc,, +flask/__pycache__/debughelpers.cpython-312.pyc,, +flask/__pycache__/globals.cpython-312.pyc,, +flask/__pycache__/helpers.cpython-312.pyc,, +flask/__pycache__/logging.cpython-312.pyc,, +flask/__pycache__/sessions.cpython-312.pyc,, +flask/__pycache__/signals.cpython-312.pyc,, +flask/__pycache__/templating.cpython-312.pyc,, +flask/__pycache__/testing.cpython-312.pyc,, +flask/__pycache__/typing.cpython-312.pyc,, +flask/__pycache__/views.cpython-312.pyc,, +flask/__pycache__/wrappers.cpython-312.pyc,, +flask/app.py,sha256=XGqgFRsLgBhzIoB2HSftoMTIM3hjDiH6rdV7c3g3IKc,61744 +flask/blueprints.py,sha256=p5QE2lY18GItbdr_RKRpZ8Do17g0PvQGIgZkSUDhX2k,4541 +flask/cli.py,sha256=Pfh72-BxlvoH0QHCDOc1HvXG7Kq5Xetf3zzNz2kNSHk,37184 +flask/config.py,sha256=PiqF0DPam6HW0FH4CH1hpXTBe30NSzjPEOwrz1b6kt0,13219 +flask/ctx.py,sha256=sPKzahqtgxaS7O0y9E_NzUJNUDyTD6M4GkDrVu2fU3Y,15064 +flask/debughelpers.py,sha256=PGIDhStW_efRjpaa3zHIpo-htStJOR41Ip3OJWPYBwo,6080 +flask/globals.py,sha256=XdQZmStBmPIs8t93tjx6pO7Bm3gobAaONWkFcUHaGas,1713 +flask/helpers.py,sha256=rJZge7_J288J1UQv5-kNf4oEaw332PP8NTW0QRIBbXE,23517 +flask/json/__init__.py,sha256=hLNR898paqoefdeAhraa5wyJy-bmRB2k2dV4EgVy2Z8,5602 +flask/json/__pycache__/__init__.cpython-312.pyc,, +flask/json/__pycache__/provider.cpython-312.pyc,, +flask/json/__pycache__/tag.cpython-312.pyc,, +flask/json/provider.py,sha256=5imEzY5HjV2HoUVrQbJLqXCzMNpZXfD0Y1XqdLV2XBA,7672 +flask/json/tag.py,sha256=DhaNwuIOhdt2R74oOC9Y4Z8ZprxFYiRb5dUP5byyINw,9281 +flask/logging.py,sha256=8sM3WMTubi1cBb2c_lPkWpN0J8dMAqrgKRYLLi1dCVI,2377 +flask/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +flask/sansio/README.md,sha256=-0X1tECnilmz1cogx-YhNw5d7guK7GKrq_DEV2OzlU0,228 +flask/sansio/__pycache__/app.cpython-312.pyc,, +flask/sansio/__pycache__/blueprints.cpython-312.pyc,, +flask/sansio/__pycache__/scaffold.cpython-312.pyc,, +flask/sansio/app.py,sha256=5EbxwHOchgcpZqQyalA9vyDBopknOvDg6BVwXFyFD2s,38099 +flask/sansio/blueprints.py,sha256=Tqe-7EkZ-tbWchm8iDoCfD848f0_3nLv6NNjeIPvHwM,24637 +flask/sansio/scaffold.py,sha256=wSASXYdFRWJmqcL0Xq-T7N-PDVUSiFGvjO9kPZg58bk,30371 +flask/sessions.py,sha256=duvYGmCGh_H3cgMuy2oeSjrCsCvLylF4CBKOXpN0Qms,15480 +flask/signals.py,sha256=V7lMUww7CqgJ2ThUBn1PiatZtQanOyt7OZpu2GZI-34,750 +flask/templating.py,sha256=IHsdsF-eBJPCJE0AJLCi1VhhnytOGdzHCn3yThz87c4,7536 +flask/testing.py,sha256=zzC7XxhBWOP9H697IV_4SG7Lg3Lzb5PWiyEP93_KQXE,10117 +flask/typing.py,sha256=L-L5t2jKgS0aOmVhioQ_ylqcgiVFnA6yxO-RLNhq-GU,3293 +flask/views.py,sha256=xzJx6oJqGElThtEghZN7ZQGMw5TDFyuRxUkecwRuAoA,6962 +flask/wrappers.py,sha256=jUkv4mVek2Iq4hwxd4RvqrIMb69Bv0PElDgWLmd5ORo,9406 diff --git a/backend/venv/Lib/site-packages/flask-3.1.2.dist-info/REQUESTED b/backend/venv/Lib/site-packages/flask-3.1.2.dist-info/REQUESTED new file mode 100644 index 0000000..e69de29 diff --git a/backend/venv/Lib/site-packages/flask-3.1.2.dist-info/WHEEL b/backend/venv/Lib/site-packages/flask-3.1.2.dist-info/WHEEL new file mode 100644 index 0000000..d8b9936 --- /dev/null +++ b/backend/venv/Lib/site-packages/flask-3.1.2.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: flit 3.12.0 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/backend/venv/Lib/site-packages/flask-3.1.2.dist-info/entry_points.txt b/backend/venv/Lib/site-packages/flask-3.1.2.dist-info/entry_points.txt new file mode 100644 index 0000000..eec6733 --- /dev/null +++ b/backend/venv/Lib/site-packages/flask-3.1.2.dist-info/entry_points.txt @@ -0,0 +1,3 @@ +[console_scripts] +flask=flask.cli:main + diff --git a/backend/venv/Lib/site-packages/flask-3.1.2.dist-info/licenses/LICENSE.txt b/backend/venv/Lib/site-packages/flask-3.1.2.dist-info/licenses/LICENSE.txt new file mode 100644 index 0000000..9d227a0 --- /dev/null +++ b/backend/venv/Lib/site-packages/flask-3.1.2.dist-info/licenses/LICENSE.txt @@ -0,0 +1,28 @@ +Copyright 2010 Pallets + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/backend/venv/Lib/site-packages/flask/__init__.py b/backend/venv/Lib/site-packages/flask/__init__.py new file mode 100644 index 0000000..1fdc50c --- /dev/null +++ b/backend/venv/Lib/site-packages/flask/__init__.py @@ -0,0 +1,61 @@ +from __future__ import annotations + +import typing as t + +from . import json as json +from .app import Flask as Flask +from .blueprints import Blueprint as Blueprint +from .config import Config as Config +from .ctx import after_this_request as after_this_request +from .ctx import copy_current_request_context as copy_current_request_context +from .ctx import has_app_context as has_app_context +from .ctx import has_request_context as has_request_context +from .globals import current_app as current_app +from .globals import g as g +from .globals import request as request +from .globals import session as session +from .helpers import abort as abort +from .helpers import flash as flash +from .helpers import get_flashed_messages as get_flashed_messages +from .helpers import get_template_attribute as get_template_attribute +from .helpers import make_response as make_response +from .helpers import redirect as redirect +from .helpers import send_file as send_file +from .helpers import send_from_directory as send_from_directory +from .helpers import stream_with_context as stream_with_context +from .helpers import url_for as url_for +from .json import jsonify as jsonify +from .signals import appcontext_popped as appcontext_popped +from .signals import appcontext_pushed as appcontext_pushed +from .signals import appcontext_tearing_down as appcontext_tearing_down +from .signals import before_render_template as before_render_template +from .signals import got_request_exception as got_request_exception +from .signals import message_flashed as message_flashed +from .signals import request_finished as request_finished +from .signals import request_started as request_started +from .signals import request_tearing_down as request_tearing_down +from .signals import template_rendered as template_rendered +from .templating import render_template as render_template +from .templating import render_template_string as render_template_string +from .templating import stream_template as stream_template +from .templating import stream_template_string as stream_template_string +from .wrappers import Request as Request +from .wrappers import Response as Response + +if not t.TYPE_CHECKING: + + def __getattr__(name: str) -> t.Any: + if name == "__version__": + import importlib.metadata + import warnings + + warnings.warn( + "The '__version__' attribute is deprecated and will be removed in" + " Flask 3.2. Use feature detection or" + " 'importlib.metadata.version(\"flask\")' instead.", + DeprecationWarning, + stacklevel=2, + ) + return importlib.metadata.version("flask") + + raise AttributeError(name) diff --git a/backend/venv/Lib/site-packages/flask/__main__.py b/backend/venv/Lib/site-packages/flask/__main__.py new file mode 100644 index 0000000..4e28416 --- /dev/null +++ b/backend/venv/Lib/site-packages/flask/__main__.py @@ -0,0 +1,3 @@ +from .cli import main + +main() diff --git a/backend/venv/Lib/site-packages/flask/__pycache__/__init__.cpython-312.pyc b/backend/venv/Lib/site-packages/flask/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4f96375ed67fd63526bf8cafa392411c73a8b315 GIT binary patch literal 2542 zcmZXWTW=Fb6vt94g{lw`P*ojSTCKg~WaGVccAXFu zM1?915AYFM(QnchC=Z}TD%$zeL|CY(L z6L|jq=dX?LfL`K9_(b+WdYuKjPc))Q1~DZnNyrf+LZez#iy1L9PUE0OwYZTmlQbzf zVWiA9+9o(@w3}&~7MwCV%nZ#4ZUfHJtl)Ow9L)(%19#F+!5v1I*-g6zXMpoGFE|U_ zLwf}0fO~1L;7+5@?5F*LyMPDifZ%T6K{_Zn4?IMN1or?B(_z8Az$0`-a3Am}9TnUU ze2g9wJODgK#{>@o%TyLTWW>#JIxcwFD3}v;LhuOiB%KsI3Oq%p1Rn#QrqhDQfQz&! zSO%VA{QIA`);qNK}Q7Xk-0u2yZ1 zgU9O-@&-W9I`b6q!8FB$hUz+VLGMG|W2R%M9#d4$<9fB}G4NzewZR|?*MYr2A;p=d zb5_G~+gxU8N?kY5k>CH|wyEqlu=$RVJ0*mO69*ng;{$5hC|x}w?Jxa__vgMl$Pb^BoN*{vFLFvZ}= zwe}+18<0A~ov-Vb-kLNQYObepPsGs^N=Jg|3a4#_AsR#fqapPjkrWs9-ol*bfNxlFDz)oXGF9X+UHm`S#|T+~emPK%*e%O>+wP4(1rE0CE29+^g=RD{7?NVHad zg^@u<+MyC^4TEhlWB-&jN=d)_|3mqyZIxS)Sl5ps`Q0n6sA2lg_g#J}oY+scX7;le z!n3%_Ih>ZLAG1`G`E75f;ENE6i|LSM`QO^|xe6?iyOqTgi;IoQRg0}~eT!9AnA`Ad zr*i%3jcb=H+l)0%SGesu#_38GRseNb*<#jK<+5I_xVp#Y9Z>OhsED;MC<+_{Pf^Ow z4yFk13(Nte=se84fFaxf^A&lP&i(NI?`ipY$JFzV;TIh}-(UIm%3dVWwIaPqkgkbm z!y|iXk{NnK5}E8?mh_B1%}+hfPd&}gKhDqpy#6GA=26F)Ke8haZa&Et9;FJeVOUa% z@ps_IkHP`)6P!W%tlM#~e8Ji&o%P!lrQXDhLO8e)e!|;vV6T12^9jdl_M>oJaI9dz zy&B%yE>DWaaN)qs&9RF8XwAFD+kiO!h2U7lyaOG{b;GWzhRd;Vc@|9$O{Z{fFvEdO z=UpguqsgP`LDP$-4^2Os0W^bXhR_Uy@sqB;ZsFh~D2<{yhGqhh%d_WcgG8~Yi zcqak^?}dP@3U4VOa{>8KywCtTLVI{GiU!L8IV*+&3td1z7m!P#oe9Y7i)8AXyZ7$C PiDlyxdvTKL7a{)#A)VL9 literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/flask/__pycache__/__main__.cpython-312.pyc b/backend/venv/Lib/site-packages/flask/__pycache__/__main__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b1e2da387e3c60d234d1dbf6613d29712c8fdd29 GIT binary patch literal 250 zcmX@j%ge<81h0QQ&yWMsk3k$5V1hC}gJh;Nq%fo~<}lIL64p$S6C;KQGm# zD6=dz#wE2lyClCLCdfZHz$d0WH8tBbrYOI-AjdQ&DKR-aH7_NmEH$qz#wRl=rZ}@C zRkr{rnwXwi9FvxlSe&gN9}luKK3=b&@)n0pZhlH>PO4oI2hdKCn~HgX#0O?ZM#j4g Oq7NBZTG@)&fFc0@azWYv literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/flask/__pycache__/app.cpython-312.pyc b/backend/venv/Lib/site-packages/flask/__pycache__/app.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..36fdc3e379ac22e1af4b80de5740058d90f9308d GIT binary patch literal 62427 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
Ovq`-I0fohXll~11 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 Vp7L9TXVJS!YyN)uQ$cRB``_hEIHmvq literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/flask/__pycache__/blueprints.cpython-312.pyc b/backend/venv/Lib/site-packages/flask/__pycache__/blueprints.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a92930f141398abfa10ea8e16c10b6fc78688700 GIT binary patch literal 5009 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 literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/flask/__pycache__/cli.cpython-312.pyc b/backend/venv/Lib/site-packages/flask/__pycache__/cli.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ecc465ea3b00abbecd308c0a227aed5aae9412cf GIT binary patch literal 43529 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 CLVQ;M literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/flask/__pycache__/config.cpython-312.pyc b/backend/venv/Lib/site-packages/flask/__pycache__/config.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..255a1ed8a450f28c042fdcf86f453bed6e014284 GIT binary patch literal 16218 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 literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/flask/__pycache__/ctx.cpython-312.pyc b/backend/venv/Lib/site-packages/flask/__pycache__/ctx.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..04fb444f5f3e502a92e12fc949d61ab319c847de GIT binary patch literal 19836 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 NF)rU?6O^bN{XZpr(suv= literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/flask/__pycache__/globals.cpython-312.pyc b/backend/venv/Lib/site-packages/flask/__pycache__/globals.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..82ad235f8fae60f4de000d4b1901669fabf12602 GIT binary patch literal 1874 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 U*8-6*0#$kgty1K3DlxYGPps12@c;k- literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/flask/__pycache__/logging.cpython-312.pyc b/backend/venv/Lib/site-packages/flask/__pycache__/logging.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5a270fad70b4a02aae897419845d83fdb458ac7b GIT binary patch literal 3279 zcmZuz&2JmW6`xstil3Hbsj#csgI2Oc*QNs(%7GP}wzec2QEj7EnucXSuDC;TrR6R= zGqglOPKeZits;QiLnFk>I3Vx?Z^Z_eekK`l36Es3rwBD2N!H9u+h9)Hjkb zgWb4p+m6tM>Dc@#jAJuSS+}k;XQ}m#G!0V`Mt{?!TmTvPX`@m0O~_t@FMtr+jO@lIw+L;A1dz1Bsx&Fdz1*Zhr%1H2ppBW6HD*B5IV>9WIF8XfUV2OkGey z8FLunf>FIrDnLpuV6e=x+EtcZsSurX_7Ee`OiuK&FmKW`#B!=cIHXistTq{yBSxG>o8-!t&Uvl`%B!Yb z&E8PXUDj>Gq70NvvAW(Oi@Ghqy3!`ih#Gk2Z^7G<@?P@mV4%rC8>yHUC9qG!EQ>ws zYO4e+C}m~c9u>r_Hyj2Aq*lXZv@EQaXB^fcAQcM1a)=4>fNq4^H%;c)ZUAEDhP|MDgm&ejemi$DS9pz6#tY|P zI)8qlaLuNd7#u|566FiRX%v2O?Z)+)!Xl*$;|1pMhBaQ8)5{CgHVQXEabd=sD{xcL zvkjQltCSa%v*&zg8!fl*pu;Q;#^uKe{MzWhM^QBWS$go^+pBNizqOG*yB20o z9bLimdpF)+L+H|;?8A;;hFco&9+DGW>p`smtVO%>KBcVUcPCnbOmO*wi#1waAZA6T z1Y93^?McnMg~YT~qIBX$$~9fh=z=VomepaCEb64Ia7MOFmMUeVoaE|M)N&oW~Xa;A+{I+(>7?tPiBQv_wdorJ#3vCaTn? zOAU5mdAO$Yq7o~1__Gt1#6f-`yT>&uHGB_#&;Es;wb6QNYGZuzFQa!C@7-Fx^{3E3 z(jzebAD5^5+hap`b}AEcdk;jw4d`~ujdsj%w?`tGUIip`!wpDsTY%?bFVb$L++=cU zzxO}!yzf2WGLycYlurIiI@v}$QIzc8N(^r#hBp(Z+LPO#x zeDag=NgyA^r?&gQ^Ef@Yl_sC0$#$X_MBx`g{m0j`f5_gAJV~Q?-%cM)s^nOH`PU<3 zI)}5b(+q!;jEt$^*}5Fct2HuKcZ{Y5qnxBE=a8!ze&E>QK=AGpa2HC)UP2vKE+F9! zNgF>|;M$|ZQic8S@HF8kVLlFKUugSER^o*v82Z*Q5)w;PTfzP;9{`=b{(QF=^5&`L zb7HiDp|D~7Z?NTQDiNBJDT%qVZb5o^r!Ucb58oks0njVNrqrNDrvlA_T!&YN-pkxM zSw|@0a-xIlIb8^rD}nN?R}+egeZs?eWjQNnWOl|Ru)kh|Z0|_DwV%tNbIoc=A_=wi zIg1)+2=8p5PV?-f7(*d@%IE&~`L+FTI-nF!CVze)3WD)R*z0`@eh?ABOp@=&_CHu@BEZ zik^NP?`{8Fhqpy&M(US$G{>xdwG!I`(bK51Y4hmVrq(IOjMPa7e6V5&4tT z>@@r`N8MPlSZRVbS}ZaN#Z00Vlh1QEELsgX0~ZT7wMf~*GHq7j1p*MvWZt`xs^!c9 z9(!+$^jI_iPErADj13>L4>ckP;yK@@#kNtjht8a9pZ*+Yux7qjOc6uA7x6sfA8rlvH dw5PX%0~^7C^}(x~!D~+g8rGi125_Hp>i_6JQqKSY literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/flask/__pycache__/sessions.cpython-312.pyc b/backend/venv/Lib/site-packages/flask/__pycache__/sessions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..51d3105dd6e6a52a47e5c1c84d2087a890828808 GIT binary patch literal 17191 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 literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/flask/__pycache__/signals.cpython-312.pyc b/backend/venv/Lib/site-packages/flask/__pycache__/signals.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..98265770af90910cfd2f35002e588038059d602d GIT binary patch literal 1231 zcmZ{jyKmD#7{Jd-Nb_jwK9Z&_ph7`{Acdep0r6;ocB~o%Vu>tSPW&Y`c5HL!^pSy< znJH7$sWa-vzrkY3i**tb5<&M>w32VI?>_(T`|fvl{*=k25NkjGe&75R zLFlVD@LROs;f~*O2z8N+WKKg(uEKF%KcYpN(Mps<5d_hr!JJAAVz1MFg8y$hdc<;g ztr8C*VgWG{LYxbTL4YLW#-47v;$IU`$MIUJM7~Zsi zSVdw<*ka(gAE+z3LN-|>>qjh*u%b7LvazkVa}C2{>HCvmrv|3Ckak`&&6=TGuw$_z zL;S?h2eZ{nd@5v^Cac9W1tK+|Sl1+v*(i+Dlql9)RttkDV(%i-k*cQXDqtM*MhTH9 z4PDX*jrTh=&=-AuI?x{kL|>o!`r<&J`ud`;Pknthsiz})`qa~B*?Rh7pihVNPxC{r zVqc%03ib4Vz89|*4qU?MEuT3l3xvJPul*#cn=h-w+8@S^N^WRKrbj^jR~g>UHMpEw%Ly??l$_>#TQEqBWH)q76%zKtf_*~^FX2lIB}sWbb` zM$_)(T({II*$cOw$vgYJJ9WOh(pj;uEICtmZ8YxY=ev8IJ^R{YC%nqO86C35+xrM{hLCLddX#DDR#vcXm8n?j4V_Y}qG!msO1b literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/flask/__pycache__/templating.cpython-312.pyc b/backend/venv/Lib/site-packages/flask/__pycache__/templating.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d0858d2b6c5a2a095ed99488073299ecb1554d92 GIT binary patch literal 9915 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 literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/flask/__pycache__/views.cpython-312.pyc b/backend/venv/Lib/site-packages/flask/__pycache__/views.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4ef6c6426059cdb545f314dc49254fb6211603c2 GIT binary patch literal 7015 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 GH2(!W){S!j literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/flask/app.py b/backend/venv/Lib/site-packages/flask/app.py new file mode 100644 index 0000000..1232b03 --- /dev/null +++ b/backend/venv/Lib/site-packages/flask/app.py @@ -0,0 +1,1536 @@ +from __future__ import annotations + +import collections.abc as cabc +import os +import sys +import typing as t +import weakref +from datetime import timedelta +from inspect import iscoroutinefunction +from itertools import chain +from types import TracebackType +from urllib.parse import quote as _url_quote + +import click +from werkzeug.datastructures import Headers +from werkzeug.datastructures import ImmutableDict +from werkzeug.exceptions import BadRequestKeyError +from werkzeug.exceptions import HTTPException +from werkzeug.exceptions import InternalServerError +from werkzeug.routing import BuildError +from werkzeug.routing import MapAdapter +from werkzeug.routing import RequestRedirect +from werkzeug.routing import RoutingException +from werkzeug.routing import Rule +from werkzeug.serving import is_running_from_reloader +from werkzeug.wrappers import Response as BaseResponse +from werkzeug.wsgi import get_host + +from . import cli +from . import typing as ft +from .ctx import AppContext +from .ctx import RequestContext +from .globals import _cv_app +from .globals import _cv_request +from .globals import current_app +from .globals import g +from .globals import request +from .globals import request_ctx +from .globals import session +from .helpers import get_debug_flag +from .helpers import get_flashed_messages +from .helpers import get_load_dotenv +from .helpers import send_from_directory +from .sansio.app import App +from .sansio.scaffold import _sentinel +from .sessions import SecureCookieSessionInterface +from .sessions import SessionInterface +from .signals import appcontext_tearing_down +from .signals import got_request_exception +from .signals import request_finished +from .signals import request_started +from .signals import request_tearing_down +from .templating import Environment +from .wrappers import Request +from .wrappers import Response + +if t.TYPE_CHECKING: # pragma: no cover + from _typeshed.wsgi import StartResponse + from _typeshed.wsgi import WSGIEnvironment + + from .testing import FlaskClient + from .testing import FlaskCliRunner + from .typing import HeadersValue + +T_shell_context_processor = t.TypeVar( + "T_shell_context_processor", bound=ft.ShellContextProcessorCallable +) +T_teardown = t.TypeVar("T_teardown", bound=ft.TeardownCallable) +T_template_filter = t.TypeVar("T_template_filter", bound=ft.TemplateFilterCallable) +T_template_global = t.TypeVar("T_template_global", bound=ft.TemplateGlobalCallable) +T_template_test = t.TypeVar("T_template_test", bound=ft.TemplateTestCallable) + + +def _make_timedelta(value: timedelta | int | None) -> timedelta | None: + if value is None or isinstance(value, timedelta): + return value + + return timedelta(seconds=value) + + +class Flask(App): + """The flask object implements a WSGI application and acts as the central + object. It is passed the name of the module or package of the + application. Once it is created it will act as a central registry for + the view functions, the URL rules, template configuration and much more. + + The name of the package is used to resolve resources from inside the + package or the folder the module is contained in depending on if the + package parameter resolves to an actual python package (a folder with + an :file:`__init__.py` file inside) or a standard module (just a ``.py`` file). + + For more information about resource loading, see :func:`open_resource`. + + Usually you create a :class:`Flask` instance in your main module or + in the :file:`__init__.py` file of your package like this:: + + from flask import Flask + app = Flask(__name__) + + .. admonition:: About the First Parameter + + The idea of the first parameter is to give Flask an idea of what + belongs to your application. This name is used to find resources + on the filesystem, can be used by extensions to improve debugging + information and a lot more. + + So it's important what you provide there. If you are using a single + module, `__name__` is always the correct value. If you however are + using a package, it's usually recommended to hardcode the name of + your package there. + + For example if your application is defined in :file:`yourapplication/app.py` + you should create it with one of the two versions below:: + + app = Flask('yourapplication') + app = Flask(__name__.split('.')[0]) + + Why is that? The application will work even with `__name__`, thanks + to how resources are looked up. However it will make debugging more + painful. Certain extensions can make assumptions based on the + import name of your application. For example the Flask-SQLAlchemy + extension will look for the code in your application that triggered + an SQL query in debug mode. If the import name is not properly set + up, that debugging information is lost. (For example it would only + pick up SQL queries in `yourapplication.app` and not + `yourapplication.views.frontend`) + + .. versionadded:: 0.7 + The `static_url_path`, `static_folder`, and `template_folder` + parameters were added. + + .. versionadded:: 0.8 + The `instance_path` and `instance_relative_config` parameters were + added. + + .. versionadded:: 0.11 + The `root_path` parameter was added. + + .. versionadded:: 1.0 + The ``host_matching`` and ``static_host`` parameters were added. + + .. versionadded:: 1.0 + The ``subdomain_matching`` parameter was added. Subdomain + matching needs to be enabled manually now. Setting + :data:`SERVER_NAME` does not implicitly enable it. + + :param import_name: the name of the application package + :param static_url_path: can be used to specify a different path for the + static files on the web. Defaults to the name + of the `static_folder` folder. + :param static_folder: The folder with static files that is served at + ``static_url_path``. Relative to the application ``root_path`` + or an absolute path. Defaults to ``'static'``. + :param static_host: the host to use when adding the static route. + Defaults to None. Required when using ``host_matching=True`` + with a ``static_folder`` configured. + :param host_matching: set ``url_map.host_matching`` attribute. + Defaults to False. + :param subdomain_matching: consider the subdomain relative to + :data:`SERVER_NAME` when matching routes. Defaults to False. + :param template_folder: the folder that contains the templates that should + be used by the application. Defaults to + ``'templates'`` folder in the root path of the + application. + :param instance_path: An alternative instance path for the application. + By default the folder ``'instance'`` next to the + package or module is assumed to be the instance + path. + :param instance_relative_config: if set to ``True`` relative filenames + for loading the config are assumed to + be relative to the instance path instead + of the application root. + :param root_path: The path to the root of the application files. + This should only be set manually when it can't be detected + automatically, such as for namespace packages. + """ + + default_config = ImmutableDict( + { + "DEBUG": None, + "TESTING": False, + "PROPAGATE_EXCEPTIONS": None, + "SECRET_KEY": None, + "SECRET_KEY_FALLBACKS": None, + "PERMANENT_SESSION_LIFETIME": timedelta(days=31), + "USE_X_SENDFILE": False, + "TRUSTED_HOSTS": None, + "SERVER_NAME": None, + "APPLICATION_ROOT": "/", + "SESSION_COOKIE_NAME": "session", + "SESSION_COOKIE_DOMAIN": None, + "SESSION_COOKIE_PATH": None, + "SESSION_COOKIE_HTTPONLY": True, + "SESSION_COOKIE_SECURE": False, + "SESSION_COOKIE_PARTITIONED": False, + "SESSION_COOKIE_SAMESITE": None, + "SESSION_REFRESH_EACH_REQUEST": True, + "MAX_CONTENT_LENGTH": None, + "MAX_FORM_MEMORY_SIZE": 500_000, + "MAX_FORM_PARTS": 1_000, + "SEND_FILE_MAX_AGE_DEFAULT": None, + "TRAP_BAD_REQUEST_ERRORS": None, + "TRAP_HTTP_EXCEPTIONS": False, + "EXPLAIN_TEMPLATE_LOADING": False, + "PREFERRED_URL_SCHEME": "http", + "TEMPLATES_AUTO_RELOAD": None, + "MAX_COOKIE_SIZE": 4093, + "PROVIDE_AUTOMATIC_OPTIONS": True, + } + ) + + #: The class that is used for request objects. See :class:`~flask.Request` + #: for more information. + request_class: type[Request] = Request + + #: The class that is used for response objects. See + #: :class:`~flask.Response` for more information. + response_class: type[Response] = Response + + #: the session interface to use. By default an instance of + #: :class:`~flask.sessions.SecureCookieSessionInterface` is used here. + #: + #: .. versionadded:: 0.8 + session_interface: SessionInterface = SecureCookieSessionInterface() + + def __init__( + self, + import_name: str, + static_url_path: str | None = None, + static_folder: str | os.PathLike[str] | None = "static", + static_host: str | None = None, + host_matching: bool = False, + subdomain_matching: bool = False, + template_folder: str | os.PathLike[str] | None = "templates", + instance_path: str | None = None, + instance_relative_config: bool = False, + root_path: str | None = None, + ): + super().__init__( + import_name=import_name, + static_url_path=static_url_path, + static_folder=static_folder, + static_host=static_host, + host_matching=host_matching, + subdomain_matching=subdomain_matching, + template_folder=template_folder, + instance_path=instance_path, + instance_relative_config=instance_relative_config, + root_path=root_path, + ) + + #: The Click command group for registering CLI commands for this + #: object. The commands are available from the ``flask`` command + #: once the application has been discovered and blueprints have + #: been registered. + self.cli = cli.AppGroup() + + # Set the name of the Click group in case someone wants to add + # the app's commands to another CLI tool. + self.cli.name = self.name + + # Add a static route using the provided static_url_path, static_host, + # and static_folder if there is a configured static_folder. + # Note we do this without checking if static_folder exists. + # For one, it might be created while the server is running (e.g. during + # development). Also, Google App Engine stores static files somewhere + if self.has_static_folder: + assert bool(static_host) == host_matching, ( + "Invalid static_host/host_matching combination" + ) + # Use a weakref to avoid creating a reference cycle between the app + # and the view function (see #3761). + self_ref = weakref.ref(self) + self.add_url_rule( + f"{self.static_url_path}/", + endpoint="static", + host=static_host, + view_func=lambda **kw: self_ref().send_static_file(**kw), # type: ignore # noqa: B950 + ) + + def get_send_file_max_age(self, filename: str | None) -> int | None: + """Used by :func:`send_file` to determine the ``max_age`` cache + value for a given file path if it wasn't passed. + + By default, this returns :data:`SEND_FILE_MAX_AGE_DEFAULT` from + the configuration of :data:`~flask.current_app`. This defaults + to ``None``, which tells the browser to use conditional requests + instead of a timed cache, which is usually preferable. + + Note this is a duplicate of the same method in the Flask + class. + + .. versionchanged:: 2.0 + The default configuration is ``None`` instead of 12 hours. + + .. versionadded:: 0.9 + """ + value = current_app.config["SEND_FILE_MAX_AGE_DEFAULT"] + + if value is None: + return None + + if isinstance(value, timedelta): + return int(value.total_seconds()) + + return value # type: ignore[no-any-return] + + def send_static_file(self, filename: str) -> Response: + """The view function used to serve files from + :attr:`static_folder`. A route is automatically registered for + this view at :attr:`static_url_path` if :attr:`static_folder` is + set. + + Note this is a duplicate of the same method in the Flask + class. + + .. versionadded:: 0.5 + + """ + if not self.has_static_folder: + raise RuntimeError("'static_folder' must be set to serve static_files.") + + # send_file only knows to call get_send_file_max_age on the app, + # call it here so it works for blueprints too. + max_age = self.get_send_file_max_age(filename) + return send_from_directory( + t.cast(str, self.static_folder), filename, max_age=max_age + ) + + def open_resource( + self, resource: str, mode: str = "rb", encoding: str | None = None + ) -> t.IO[t.AnyStr]: + """Open a resource file relative to :attr:`root_path` for reading. + + For example, if the file ``schema.sql`` is next to the file + ``app.py`` where the ``Flask`` app is defined, it can be opened + with: + + .. code-block:: python + + with app.open_resource("schema.sql") as f: + conn.executescript(f.read()) + + :param resource: Path to the resource relative to :attr:`root_path`. + :param mode: Open the file in this mode. Only reading is supported, + valid values are ``"r"`` (or ``"rt"``) and ``"rb"``. + :param encoding: Open the file with this encoding when opening in text + mode. This is ignored when opening in binary mode. + + .. versionchanged:: 3.1 + Added the ``encoding`` parameter. + """ + if mode not in {"r", "rt", "rb"}: + raise ValueError("Resources can only be opened for reading.") + + path = os.path.join(self.root_path, resource) + + if mode == "rb": + return open(path, mode) # pyright: ignore + + return open(path, mode, encoding=encoding) + + def open_instance_resource( + self, resource: str, mode: str = "rb", encoding: str | None = "utf-8" + ) -> t.IO[t.AnyStr]: + """Open a resource file relative to the application's instance folder + :attr:`instance_path`. Unlike :meth:`open_resource`, files in the + instance folder can be opened for writing. + + :param resource: Path to the resource relative to :attr:`instance_path`. + :param mode: Open the file in this mode. + :param encoding: Open the file with this encoding when opening in text + mode. This is ignored when opening in binary mode. + + .. versionchanged:: 3.1 + Added the ``encoding`` parameter. + """ + path = os.path.join(self.instance_path, resource) + + if "b" in mode: + return open(path, mode) + + return open(path, mode, encoding=encoding) + + def create_jinja_environment(self) -> Environment: + """Create the Jinja environment based on :attr:`jinja_options` + and the various Jinja-related methods of the app. Changing + :attr:`jinja_options` after this will have no effect. Also adds + Flask-related globals and filters to the environment. + + .. versionchanged:: 0.11 + ``Environment.auto_reload`` set in accordance with + ``TEMPLATES_AUTO_RELOAD`` configuration option. + + .. versionadded:: 0.5 + """ + options = dict(self.jinja_options) + + if "autoescape" not in options: + options["autoescape"] = self.select_jinja_autoescape + + if "auto_reload" not in options: + auto_reload = self.config["TEMPLATES_AUTO_RELOAD"] + + if auto_reload is None: + auto_reload = self.debug + + options["auto_reload"] = auto_reload + + rv = self.jinja_environment(self, **options) + rv.globals.update( + url_for=self.url_for, + get_flashed_messages=get_flashed_messages, + config=self.config, + # request, session and g are normally added with the + # context processor for efficiency reasons but for imported + # templates we also want the proxies in there. + request=request, + session=session, + g=g, + ) + rv.policies["json.dumps_function"] = self.json.dumps + return rv + + def create_url_adapter(self, request: Request | None) -> MapAdapter | None: + """Creates a URL adapter for the given request. The URL adapter + is created at a point where the request context is not yet set + up so the request is passed explicitly. + + .. versionchanged:: 3.1 + If :data:`SERVER_NAME` is set, it does not restrict requests to + only that domain, for both ``subdomain_matching`` and + ``host_matching``. + + .. versionchanged:: 1.0 + :data:`SERVER_NAME` no longer implicitly enables subdomain + matching. Use :attr:`subdomain_matching` instead. + + .. versionchanged:: 0.9 + This can be called outside a request when the URL adapter is created + for an application context. + + .. versionadded:: 0.6 + """ + if request is not None: + if (trusted_hosts := self.config["TRUSTED_HOSTS"]) is not None: + request.trusted_hosts = trusted_hosts + + # Check trusted_hosts here until bind_to_environ does. + request.host = get_host(request.environ, request.trusted_hosts) # pyright: ignore + subdomain = None + server_name = self.config["SERVER_NAME"] + + if self.url_map.host_matching: + # Don't pass SERVER_NAME, otherwise it's used and the actual + # host is ignored, which breaks host matching. + server_name = None + elif not self.subdomain_matching: + # Werkzeug doesn't implement subdomain matching yet. Until then, + # disable it by forcing the current subdomain to the default, or + # the empty string. + subdomain = self.url_map.default_subdomain or "" + + return self.url_map.bind_to_environ( + request.environ, server_name=server_name, subdomain=subdomain + ) + + # Need at least SERVER_NAME to match/build outside a request. + if self.config["SERVER_NAME"] is not None: + return self.url_map.bind( + self.config["SERVER_NAME"], + script_name=self.config["APPLICATION_ROOT"], + url_scheme=self.config["PREFERRED_URL_SCHEME"], + ) + + return None + + def raise_routing_exception(self, request: Request) -> t.NoReturn: + """Intercept routing exceptions and possibly do something else. + + In debug mode, intercept a routing redirect and replace it with + an error if the body will be discarded. + + With modern Werkzeug this shouldn't occur, since it now uses a + 308 status which tells the browser to resend the method and + body. + + .. versionchanged:: 2.1 + Don't intercept 307 and 308 redirects. + + :meta private: + :internal: + """ + if ( + not self.debug + or not isinstance(request.routing_exception, RequestRedirect) + or request.routing_exception.code in {307, 308} + or request.method in {"GET", "HEAD", "OPTIONS"} + ): + raise request.routing_exception # type: ignore[misc] + + from .debughelpers import FormDataRoutingRedirect + + raise FormDataRoutingRedirect(request) + + def update_template_context(self, context: dict[str, t.Any]) -> None: + """Update the template context with some commonly used variables. + This injects request, session, config and g into the template + context as well as everything template context processors want + to inject. Note that the as of Flask 0.6, the original values + in the context will not be overridden if a context processor + decides to return a value with the same key. + + :param context: the context as a dictionary that is updated in place + to add extra variables. + """ + names: t.Iterable[str | None] = (None,) + + # A template may be rendered outside a request context. + if request: + names = chain(names, reversed(request.blueprints)) + + # The values passed to render_template take precedence. Keep a + # copy to re-apply after all context functions. + orig_ctx = context.copy() + + for name in names: + if name in self.template_context_processors: + for func in self.template_context_processors[name]: + context.update(self.ensure_sync(func)()) + + context.update(orig_ctx) + + def make_shell_context(self) -> dict[str, t.Any]: + """Returns the shell context for an interactive shell for this + application. This runs all the registered shell context + processors. + + .. versionadded:: 0.11 + """ + rv = {"app": self, "g": g} + for processor in self.shell_context_processors: + rv.update(processor()) + return rv + + def run( + self, + host: str | None = None, + port: int | None = None, + debug: bool | None = None, + load_dotenv: bool = True, + **options: t.Any, + ) -> None: + """Runs the application on a local development server. + + Do not use ``run()`` in a production setting. It is not intended to + meet security and performance requirements for a production server. + Instead, see :doc:`/deploying/index` for WSGI server recommendations. + + If the :attr:`debug` flag is set the server will automatically reload + for code changes and show a debugger in case an exception happened. + + If you want to run the application in debug mode, but disable the + code execution on the interactive debugger, you can pass + ``use_evalex=False`` as parameter. This will keep the debugger's + traceback screen active, but disable code execution. + + It is not recommended to use this function for development with + automatic reloading as this is badly supported. Instead you should + be using the :command:`flask` command line script's ``run`` support. + + .. admonition:: Keep in Mind + + Flask will suppress any server error with a generic error page + unless it is in debug mode. As such to enable just the + interactive debugger without the code reloading, you have to + invoke :meth:`run` with ``debug=True`` and ``use_reloader=False``. + Setting ``use_debugger`` to ``True`` without being in debug mode + won't catch any exceptions because there won't be any to + catch. + + :param host: the hostname to listen on. Set this to ``'0.0.0.0'`` to + have the server available externally as well. Defaults to + ``'127.0.0.1'`` or the host in the ``SERVER_NAME`` config variable + if present. + :param port: the port of the webserver. Defaults to ``5000`` or the + port defined in the ``SERVER_NAME`` config variable if present. + :param debug: if given, enable or disable debug mode. See + :attr:`debug`. + :param load_dotenv: Load the nearest :file:`.env` and :file:`.flaskenv` + files to set environment variables. Will also change the working + directory to the directory containing the first file found. + :param options: the options to be forwarded to the underlying Werkzeug + server. See :func:`werkzeug.serving.run_simple` for more + information. + + .. versionchanged:: 1.0 + If installed, python-dotenv will be used to load environment + variables from :file:`.env` and :file:`.flaskenv` files. + + The :envvar:`FLASK_DEBUG` environment variable will override :attr:`debug`. + + Threaded mode is enabled by default. + + .. versionchanged:: 0.10 + The default port is now picked from the ``SERVER_NAME`` + variable. + """ + # Ignore this call so that it doesn't start another server if + # the 'flask run' command is used. + if os.environ.get("FLASK_RUN_FROM_CLI") == "true": + if not is_running_from_reloader(): + click.secho( + " * Ignoring a call to 'app.run()' that would block" + " the current 'flask' CLI command.\n" + " Only call 'app.run()' in an 'if __name__ ==" + ' "__main__"\' guard.', + fg="red", + ) + + return + + if get_load_dotenv(load_dotenv): + cli.load_dotenv() + + # if set, env var overrides existing value + if "FLASK_DEBUG" in os.environ: + self.debug = get_debug_flag() + + # debug passed to method overrides all other sources + if debug is not None: + self.debug = bool(debug) + + server_name = self.config.get("SERVER_NAME") + sn_host = sn_port = None + + if server_name: + sn_host, _, sn_port = server_name.partition(":") + + if not host: + if sn_host: + host = sn_host + else: + host = "127.0.0.1" + + if port or port == 0: + port = int(port) + elif sn_port: + port = int(sn_port) + else: + port = 5000 + + options.setdefault("use_reloader", self.debug) + options.setdefault("use_debugger", self.debug) + options.setdefault("threaded", True) + + cli.show_server_banner(self.debug, self.name) + + from werkzeug.serving import run_simple + + try: + run_simple(t.cast(str, host), port, self, **options) + finally: + # reset the first request information if the development server + # reset normally. This makes it possible to restart the server + # without reloader and that stuff from an interactive shell. + self._got_first_request = False + + def test_client(self, use_cookies: bool = True, **kwargs: t.Any) -> FlaskClient: + """Creates a test client for this application. For information + about unit testing head over to :doc:`/testing`. + + Note that if you are testing for assertions or exceptions in your + application code, you must set ``app.testing = True`` in order for the + exceptions to propagate to the test client. Otherwise, the exception + will be handled by the application (not visible to the test client) and + the only indication of an AssertionError or other exception will be a + 500 status code response to the test client. See the :attr:`testing` + attribute. For example:: + + app.testing = True + client = app.test_client() + + The test client can be used in a ``with`` block to defer the closing down + of the context until the end of the ``with`` block. This is useful if + you want to access the context locals for testing:: + + with app.test_client() as c: + rv = c.get('/?vodka=42') + assert request.args['vodka'] == '42' + + Additionally, you may pass optional keyword arguments that will then + be passed to the application's :attr:`test_client_class` constructor. + For example:: + + from flask.testing import FlaskClient + + class CustomClient(FlaskClient): + def __init__(self, *args, **kwargs): + self._authentication = kwargs.pop("authentication") + super(CustomClient,self).__init__( *args, **kwargs) + + app.test_client_class = CustomClient + client = app.test_client(authentication='Basic ....') + + See :class:`~flask.testing.FlaskClient` for more information. + + .. versionchanged:: 0.4 + added support for ``with`` block usage for the client. + + .. versionadded:: 0.7 + The `use_cookies` parameter was added as well as the ability + to override the client to be used by setting the + :attr:`test_client_class` attribute. + + .. versionchanged:: 0.11 + Added `**kwargs` to support passing additional keyword arguments to + the constructor of :attr:`test_client_class`. + """ + cls = self.test_client_class + if cls is None: + from .testing import FlaskClient as cls + return cls( # type: ignore + self, self.response_class, use_cookies=use_cookies, **kwargs + ) + + def test_cli_runner(self, **kwargs: t.Any) -> FlaskCliRunner: + """Create a CLI runner for testing CLI commands. + See :ref:`testing-cli`. + + Returns an instance of :attr:`test_cli_runner_class`, by default + :class:`~flask.testing.FlaskCliRunner`. The Flask app object is + passed as the first argument. + + .. versionadded:: 1.0 + """ + cls = self.test_cli_runner_class + + if cls is None: + from .testing import FlaskCliRunner as cls + + return cls(self, **kwargs) # type: ignore + + def handle_http_exception( + self, e: HTTPException + ) -> HTTPException | ft.ResponseReturnValue: + """Handles an HTTP exception. By default this will invoke the + registered error handlers and fall back to returning the + exception as response. + + .. versionchanged:: 1.0.3 + ``RoutingException``, used internally for actions such as + slash redirects during routing, is not passed to error + handlers. + + .. versionchanged:: 1.0 + Exceptions are looked up by code *and* by MRO, so + ``HTTPException`` subclasses can be handled with a catch-all + handler for the base ``HTTPException``. + + .. versionadded:: 0.3 + """ + # Proxy exceptions don't have error codes. We want to always return + # those unchanged as errors + if e.code is None: + return e + + # RoutingExceptions are used internally to trigger routing + # actions, such as slash redirects raising RequestRedirect. They + # are not raised or handled in user code. + if isinstance(e, RoutingException): + return e + + handler = self._find_error_handler(e, request.blueprints) + if handler is None: + return e + return self.ensure_sync(handler)(e) # type: ignore[no-any-return] + + def handle_user_exception( + self, e: Exception + ) -> HTTPException | ft.ResponseReturnValue: + """This method is called whenever an exception occurs that + should be handled. A special case is :class:`~werkzeug + .exceptions.HTTPException` which is forwarded to the + :meth:`handle_http_exception` method. This function will either + return a response value or reraise the exception with the same + traceback. + + .. versionchanged:: 1.0 + Key errors raised from request data like ``form`` show the + bad key in debug mode rather than a generic bad request + message. + + .. versionadded:: 0.7 + """ + if isinstance(e, BadRequestKeyError) and ( + self.debug or self.config["TRAP_BAD_REQUEST_ERRORS"] + ): + e.show_exception = True + + if isinstance(e, HTTPException) and not self.trap_http_exception(e): + return self.handle_http_exception(e) + + handler = self._find_error_handler(e, request.blueprints) + + if handler is None: + raise + + return self.ensure_sync(handler)(e) # type: ignore[no-any-return] + + def handle_exception(self, e: Exception) -> Response: + """Handle an exception that did not have an error handler + associated with it, or that was raised from an error handler. + This always causes a 500 ``InternalServerError``. + + Always sends the :data:`got_request_exception` signal. + + If :data:`PROPAGATE_EXCEPTIONS` is ``True``, such as in debug + mode, the error will be re-raised so that the debugger can + display it. Otherwise, the original exception is logged, and + an :exc:`~werkzeug.exceptions.InternalServerError` is returned. + + If an error handler is registered for ``InternalServerError`` or + ``500``, it will be used. For consistency, the handler will + always receive the ``InternalServerError``. The original + unhandled exception is available as ``e.original_exception``. + + .. versionchanged:: 1.1.0 + Always passes the ``InternalServerError`` instance to the + handler, setting ``original_exception`` to the unhandled + error. + + .. versionchanged:: 1.1.0 + ``after_request`` functions and other finalization is done + even for the default 500 response when there is no handler. + + .. versionadded:: 0.3 + """ + exc_info = sys.exc_info() + got_request_exception.send(self, _async_wrapper=self.ensure_sync, exception=e) + propagate = self.config["PROPAGATE_EXCEPTIONS"] + + if propagate is None: + propagate = self.testing or self.debug + + if propagate: + # Re-raise if called with an active exception, otherwise + # raise the passed in exception. + if exc_info[1] is e: + raise + + raise e + + self.log_exception(exc_info) + server_error: InternalServerError | ft.ResponseReturnValue + server_error = InternalServerError(original_exception=e) + handler = self._find_error_handler(server_error, request.blueprints) + + if handler is not None: + server_error = self.ensure_sync(handler)(server_error) + + return self.finalize_request(server_error, from_error_handler=True) + + def log_exception( + self, + exc_info: (tuple[type, BaseException, TracebackType] | tuple[None, None, None]), + ) -> None: + """Logs an exception. This is called by :meth:`handle_exception` + if debugging is disabled and right before the handler is called. + The default implementation logs the exception as error on the + :attr:`logger`. + + .. versionadded:: 0.8 + """ + self.logger.error( + f"Exception on {request.path} [{request.method}]", exc_info=exc_info + ) + + def dispatch_request(self) -> ft.ResponseReturnValue: + """Does the request dispatching. Matches the URL and returns the + return value of the view or error handler. This does not have to + be a response object. In order to convert the return value to a + proper response object, call :func:`make_response`. + + .. versionchanged:: 0.7 + This no longer does the exception handling, this code was + moved to the new :meth:`full_dispatch_request`. + """ + req = request_ctx.request + if req.routing_exception is not None: + self.raise_routing_exception(req) + rule: Rule = req.url_rule # type: ignore[assignment] + # if we provide automatic options for this URL and the + # request came with the OPTIONS method, reply automatically + if ( + getattr(rule, "provide_automatic_options", False) + and req.method == "OPTIONS" + ): + return self.make_default_options_response() + # otherwise dispatch to the handler for that endpoint + view_args: dict[str, t.Any] = req.view_args # type: ignore[assignment] + return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return] + + def full_dispatch_request(self) -> Response: + """Dispatches the request and on top of that performs request + pre and postprocessing as well as HTTP exception catching and + error handling. + + .. versionadded:: 0.7 + """ + self._got_first_request = True + + try: + request_started.send(self, _async_wrapper=self.ensure_sync) + rv = self.preprocess_request() + if rv is None: + rv = self.dispatch_request() + except Exception as e: + rv = self.handle_user_exception(e) + return self.finalize_request(rv) + + def finalize_request( + self, + rv: ft.ResponseReturnValue | HTTPException, + from_error_handler: bool = False, + ) -> Response: + """Given the return value from a view function this finalizes + the request by converting it into a response and invoking the + postprocessing functions. This is invoked for both normal + request dispatching as well as error handlers. + + Because this means that it might be called as a result of a + failure a special safe mode is available which can be enabled + with the `from_error_handler` flag. If enabled, failures in + response processing will be logged and otherwise ignored. + + :internal: + """ + response = self.make_response(rv) + try: + response = self.process_response(response) + request_finished.send( + self, _async_wrapper=self.ensure_sync, response=response + ) + except Exception: + if not from_error_handler: + raise + self.logger.exception( + "Request finalizing failed with an error while handling an error" + ) + return response + + def make_default_options_response(self) -> Response: + """This method is called to create the default ``OPTIONS`` response. + This can be changed through subclassing to change the default + behavior of ``OPTIONS`` responses. + + .. versionadded:: 0.7 + """ + adapter = request_ctx.url_adapter + methods = adapter.allowed_methods() # type: ignore[union-attr] + rv = self.response_class() + rv.allow.update(methods) + return rv + + def ensure_sync(self, func: t.Callable[..., t.Any]) -> t.Callable[..., t.Any]: + """Ensure that the function is synchronous for WSGI workers. + Plain ``def`` functions are returned as-is. ``async def`` + functions are wrapped to run and wait for the response. + + Override this method to change how the app runs async views. + + .. versionadded:: 2.0 + """ + if iscoroutinefunction(func): + return self.async_to_sync(func) + + return func + + def async_to_sync( + self, func: t.Callable[..., t.Coroutine[t.Any, t.Any, t.Any]] + ) -> t.Callable[..., t.Any]: + """Return a sync function that will run the coroutine function. + + .. code-block:: python + + result = app.async_to_sync(func)(*args, **kwargs) + + Override this method to change how the app converts async code + to be synchronously callable. + + .. versionadded:: 2.0 + """ + try: + from asgiref.sync import async_to_sync as asgiref_async_to_sync + except ImportError: + raise RuntimeError( + "Install Flask with the 'async' extra in order to use async views." + ) from None + + return asgiref_async_to_sync(func) + + def url_for( + self, + /, + endpoint: str, + *, + _anchor: str | None = None, + _method: str | None = None, + _scheme: str | None = None, + _external: bool | None = None, + **values: t.Any, + ) -> str: + """Generate a URL to the given endpoint with the given values. + + This is called by :func:`flask.url_for`, and can be called + directly as well. + + An *endpoint* is the name of a URL rule, usually added with + :meth:`@app.route() `, and usually the same name as the + view function. A route defined in a :class:`~flask.Blueprint` + will prepend the blueprint's name separated by a ``.`` to the + endpoint. + + In some cases, such as email messages, you want URLs to include + the scheme and domain, like ``https://example.com/hello``. When + not in an active request, URLs will be external by default, but + this requires setting :data:`SERVER_NAME` so Flask knows what + domain to use. :data:`APPLICATION_ROOT` and + :data:`PREFERRED_URL_SCHEME` should also be configured as + needed. This config is only used when not in an active request. + + Functions can be decorated with :meth:`url_defaults` to modify + keyword arguments before the URL is built. + + If building fails for some reason, such as an unknown endpoint + or incorrect values, the app's :meth:`handle_url_build_error` + method is called. If that returns a string, that is returned, + otherwise a :exc:`~werkzeug.routing.BuildError` is raised. + + :param endpoint: The endpoint name associated with the URL to + generate. If this starts with a ``.``, the current blueprint + name (if any) will be used. + :param _anchor: If given, append this as ``#anchor`` to the URL. + :param _method: If given, generate the URL associated with this + method for the endpoint. + :param _scheme: If given, the URL will have this scheme if it + is external. + :param _external: If given, prefer the URL to be internal + (False) or require it to be external (True). External URLs + include the scheme and domain. When not in an active + request, URLs are external by default. + :param values: Values to use for the variable parts of the URL + rule. Unknown keys are appended as query string arguments, + like ``?a=b&c=d``. + + .. versionadded:: 2.2 + Moved from ``flask.url_for``, which calls this method. + """ + req_ctx = _cv_request.get(None) + + if req_ctx is not None: + url_adapter = req_ctx.url_adapter + blueprint_name = req_ctx.request.blueprint + + # If the endpoint starts with "." and the request matches a + # blueprint, the endpoint is relative to the blueprint. + if endpoint[:1] == ".": + if blueprint_name is not None: + endpoint = f"{blueprint_name}{endpoint}" + else: + endpoint = endpoint[1:] + + # When in a request, generate a URL without scheme and + # domain by default, unless a scheme is given. + if _external is None: + _external = _scheme is not None + else: + app_ctx = _cv_app.get(None) + + # If called by helpers.url_for, an app context is active, + # use its url_adapter. Otherwise, app.url_for was called + # directly, build an adapter. + if app_ctx is not None: + url_adapter = app_ctx.url_adapter + else: + url_adapter = self.create_url_adapter(None) + + if url_adapter is None: + raise RuntimeError( + "Unable to build URLs outside an active request" + " without 'SERVER_NAME' configured. Also configure" + " 'APPLICATION_ROOT' and 'PREFERRED_URL_SCHEME' as" + " needed." + ) + + # When outside a request, generate a URL with scheme and + # domain by default. + if _external is None: + _external = True + + # It is an error to set _scheme when _external=False, in order + # to avoid accidental insecure URLs. + if _scheme is not None and not _external: + raise ValueError("When specifying '_scheme', '_external' must be True.") + + self.inject_url_defaults(endpoint, values) + + try: + rv = url_adapter.build( # type: ignore[union-attr] + endpoint, + values, + method=_method, + url_scheme=_scheme, + force_external=_external, + ) + except BuildError as error: + values.update( + _anchor=_anchor, _method=_method, _scheme=_scheme, _external=_external + ) + return self.handle_url_build_error(error, endpoint, values) + + if _anchor is not None: + _anchor = _url_quote(_anchor, safe="%!#$&'()*+,/:;=?@") + rv = f"{rv}#{_anchor}" + + return rv + + def make_response(self, rv: ft.ResponseReturnValue) -> Response: + """Convert the return value from a view function to an instance of + :attr:`response_class`. + + :param rv: the return value from the view function. The view function + must return a response. Returning ``None``, or the view ending + without returning, is not allowed. The following types are allowed + for ``view_rv``: + + ``str`` + A response object is created with the string encoded to UTF-8 + as the body. + + ``bytes`` + A response object is created with the bytes as the body. + + ``dict`` + A dictionary that will be jsonify'd before being returned. + + ``list`` + A list that will be jsonify'd before being returned. + + ``generator`` or ``iterator`` + A generator that returns ``str`` or ``bytes`` to be + streamed as the response. + + ``tuple`` + Either ``(body, status, headers)``, ``(body, status)``, or + ``(body, headers)``, where ``body`` is any of the other types + allowed here, ``status`` is a string or an integer, and + ``headers`` is a dictionary or a list of ``(key, value)`` + tuples. If ``body`` is a :attr:`response_class` instance, + ``status`` overwrites the exiting value and ``headers`` are + extended. + + :attr:`response_class` + The object is returned unchanged. + + other :class:`~werkzeug.wrappers.Response` class + The object is coerced to :attr:`response_class`. + + :func:`callable` + The function is called as a WSGI application. The result is + used to create a response object. + + .. versionchanged:: 2.2 + A generator will be converted to a streaming response. + A list will be converted to a JSON response. + + .. versionchanged:: 1.1 + A dict will be converted to a JSON response. + + .. versionchanged:: 0.9 + Previously a tuple was interpreted as the arguments for the + response object. + """ + + status: int | None = None + headers: HeadersValue | None = None + + # unpack tuple returns + if isinstance(rv, tuple): + len_rv = len(rv) + + # a 3-tuple is unpacked directly + if len_rv == 3: + rv, status, headers = rv # type: ignore[misc] + # decide if a 2-tuple has status or headers + elif len_rv == 2: + if isinstance(rv[1], (Headers, dict, tuple, list)): + rv, headers = rv # pyright: ignore + else: + rv, status = rv # type: ignore[assignment,misc] + # other sized tuples are not allowed + else: + raise TypeError( + "The view function did not return a valid response tuple." + " The tuple must have the form (body, status, headers)," + " (body, status), or (body, headers)." + ) + + # the body must not be None + if rv is None: + raise TypeError( + f"The view function for {request.endpoint!r} did not" + " return a valid response. The function either returned" + " None or ended without a return statement." + ) + + # make sure the body is an instance of the response class + if not isinstance(rv, self.response_class): + if isinstance(rv, (str, bytes, bytearray)) or isinstance(rv, cabc.Iterator): + # let the response class set the status and headers instead of + # waiting to do it manually, so that the class can handle any + # special logic + rv = self.response_class( + rv, # pyright: ignore + status=status, + headers=headers, # type: ignore[arg-type] + ) + status = headers = None + elif isinstance(rv, (dict, list)): + rv = self.json.response(rv) + elif isinstance(rv, BaseResponse) or callable(rv): + # evaluate a WSGI callable, or coerce a different response + # class to the correct type + try: + rv = self.response_class.force_type( + rv, # type: ignore[arg-type] + request.environ, + ) + except TypeError as e: + raise TypeError( + f"{e}\nThe view function did not return a valid" + " response. The return type must be a string," + " dict, list, tuple with headers or status," + " Response instance, or WSGI callable, but it" + f" was a {type(rv).__name__}." + ).with_traceback(sys.exc_info()[2]) from None + else: + raise TypeError( + "The view function did not return a valid" + " response. The return type must be a string," + " dict, list, tuple with headers or status," + " Response instance, or WSGI callable, but it was a" + f" {type(rv).__name__}." + ) + + rv = t.cast(Response, rv) + # prefer the status if it was provided + if status is not None: + if isinstance(status, (str, bytes, bytearray)): + rv.status = status + else: + rv.status_code = status + + # extend existing headers with provided headers + if headers: + rv.headers.update(headers) + + return rv + + def preprocess_request(self) -> ft.ResponseReturnValue | None: + """Called before the request is dispatched. Calls + :attr:`url_value_preprocessors` registered with the app and the + current blueprint (if any). Then calls :attr:`before_request_funcs` + registered with the app and the blueprint. + + If any :meth:`before_request` handler returns a non-None value, the + value is handled as if it was the return value from the view, and + further request handling is stopped. + """ + names = (None, *reversed(request.blueprints)) + + for name in names: + if name in self.url_value_preprocessors: + for url_func in self.url_value_preprocessors[name]: + url_func(request.endpoint, request.view_args) + + for name in names: + if name in self.before_request_funcs: + for before_func in self.before_request_funcs[name]: + rv = self.ensure_sync(before_func)() + + if rv is not None: + return rv # type: ignore[no-any-return] + + return None + + def process_response(self, response: Response) -> Response: + """Can be overridden in order to modify the response object + before it's sent to the WSGI server. By default this will + call all the :meth:`after_request` decorated functions. + + .. versionchanged:: 0.5 + As of Flask 0.5 the functions registered for after request + execution are called in reverse order of registration. + + :param response: a :attr:`response_class` object. + :return: a new response object or the same, has to be an + instance of :attr:`response_class`. + """ + ctx = request_ctx._get_current_object() # type: ignore[attr-defined] + + for func in ctx._after_request_functions: + response = self.ensure_sync(func)(response) + + for name in chain(request.blueprints, (None,)): + if name in self.after_request_funcs: + for func in reversed(self.after_request_funcs[name]): + response = self.ensure_sync(func)(response) + + if not self.session_interface.is_null_session(ctx.session): + self.session_interface.save_session(self, ctx.session, response) + + return response + + def do_teardown_request( + self, + exc: BaseException | None = _sentinel, # type: ignore[assignment] + ) -> None: + """Called after the request is dispatched and the response is + returned, right before the request context is popped. + + This calls all functions decorated with + :meth:`teardown_request`, and :meth:`Blueprint.teardown_request` + if a blueprint handled the request. Finally, the + :data:`request_tearing_down` signal is sent. + + This is called by + :meth:`RequestContext.pop() `, + which may be delayed during testing to maintain access to + resources. + + :param exc: An unhandled exception raised while dispatching the + request. Detected from the current exception information if + not passed. Passed to each teardown function. + + .. versionchanged:: 0.9 + Added the ``exc`` argument. + """ + if exc is _sentinel: + exc = sys.exc_info()[1] + + for name in chain(request.blueprints, (None,)): + if name in self.teardown_request_funcs: + for func in reversed(self.teardown_request_funcs[name]): + self.ensure_sync(func)(exc) + + request_tearing_down.send(self, _async_wrapper=self.ensure_sync, exc=exc) + + def do_teardown_appcontext( + self, + exc: BaseException | None = _sentinel, # type: ignore[assignment] + ) -> None: + """Called right before the application context is popped. + + When handling a request, the application context is popped + after the request context. See :meth:`do_teardown_request`. + + This calls all functions decorated with + :meth:`teardown_appcontext`. Then the + :data:`appcontext_tearing_down` signal is sent. + + This is called by + :meth:`AppContext.pop() `. + + .. versionadded:: 0.9 + """ + if exc is _sentinel: + exc = sys.exc_info()[1] + + for func in reversed(self.teardown_appcontext_funcs): + self.ensure_sync(func)(exc) + + appcontext_tearing_down.send(self, _async_wrapper=self.ensure_sync, exc=exc) + + def app_context(self) -> AppContext: + """Create an :class:`~flask.ctx.AppContext`. Use as a ``with`` + block to push the context, which will make :data:`current_app` + point at this application. + + An application context is automatically pushed by + :meth:`RequestContext.push() ` + when handling a request, and when running a CLI command. Use + this to manually create a context outside of these situations. + + :: + + with app.app_context(): + init_db() + + See :doc:`/appcontext`. + + .. versionadded:: 0.9 + """ + return AppContext(self) + + def request_context(self, environ: WSGIEnvironment) -> RequestContext: + """Create a :class:`~flask.ctx.RequestContext` representing a + WSGI environment. Use a ``with`` block to push the context, + which will make :data:`request` point at this request. + + See :doc:`/reqcontext`. + + Typically you should not call this from your own code. A request + context is automatically pushed by the :meth:`wsgi_app` when + handling a request. Use :meth:`test_request_context` to create + an environment and context instead of this method. + + :param environ: a WSGI environment + """ + return RequestContext(self, environ) + + def test_request_context(self, *args: t.Any, **kwargs: t.Any) -> RequestContext: + """Create a :class:`~flask.ctx.RequestContext` for a WSGI + environment created from the given values. This is mostly useful + during testing, where you may want to run a function that uses + request data without dispatching a full request. + + See :doc:`/reqcontext`. + + Use a ``with`` block to push the context, which will make + :data:`request` point at the request for the created + environment. :: + + with app.test_request_context(...): + generate_report() + + When using the shell, it may be easier to push and pop the + context manually to avoid indentation. :: + + ctx = app.test_request_context(...) + ctx.push() + ... + ctx.pop() + + Takes the same arguments as Werkzeug's + :class:`~werkzeug.test.EnvironBuilder`, with some defaults from + the application. See the linked Werkzeug docs for most of the + available arguments. Flask-specific behavior is listed here. + + :param path: URL path being requested. + :param base_url: Base URL where the app is being served, which + ``path`` is relative to. If not given, built from + :data:`PREFERRED_URL_SCHEME`, ``subdomain``, + :data:`SERVER_NAME`, and :data:`APPLICATION_ROOT`. + :param subdomain: Subdomain name to append to + :data:`SERVER_NAME`. + :param url_scheme: Scheme to use instead of + :data:`PREFERRED_URL_SCHEME`. + :param data: The request body, either as a string or a dict of + form keys and values. + :param json: If given, this is serialized as JSON and passed as + ``data``. Also defaults ``content_type`` to + ``application/json``. + :param args: other positional arguments passed to + :class:`~werkzeug.test.EnvironBuilder`. + :param kwargs: other keyword arguments passed to + :class:`~werkzeug.test.EnvironBuilder`. + """ + from .testing import EnvironBuilder + + builder = EnvironBuilder(self, *args, **kwargs) + + try: + return self.request_context(builder.get_environ()) + finally: + builder.close() + + def wsgi_app( + self, environ: WSGIEnvironment, start_response: StartResponse + ) -> cabc.Iterable[bytes]: + """The actual WSGI application. This is not implemented in + :meth:`__call__` so that middlewares can be applied without + losing a reference to the app object. Instead of doing this:: + + app = MyMiddleware(app) + + It's a better idea to do this instead:: + + app.wsgi_app = MyMiddleware(app.wsgi_app) + + Then you still have the original application object around and + can continue to call methods on it. + + .. versionchanged:: 0.7 + Teardown events for the request and app contexts are called + even if an unhandled error occurs. Other events may not be + called depending on when an error occurs during dispatch. + See :ref:`callbacks-and-errors`. + + :param environ: A WSGI environment. + :param start_response: A callable accepting a status code, + a list of headers, and an optional exception context to + start the response. + """ + ctx = self.request_context(environ) + error: BaseException | None = None + try: + try: + ctx.push() + response = self.full_dispatch_request() + except Exception as e: + error = e + response = self.handle_exception(e) + except: # noqa: B001 + error = sys.exc_info()[1] + raise + return response(environ, start_response) + finally: + if "werkzeug.debug.preserve_context" in environ: + environ["werkzeug.debug.preserve_context"](_cv_app.get()) + environ["werkzeug.debug.preserve_context"](_cv_request.get()) + + if error is not None and self.should_ignore_error(error): + error = None + + ctx.pop(error) + + def __call__( + self, environ: WSGIEnvironment, start_response: StartResponse + ) -> cabc.Iterable[bytes]: + """The WSGI server calls the Flask application object as the + WSGI application. This calls :meth:`wsgi_app`, which can be + wrapped to apply middleware. + """ + return self.wsgi_app(environ, start_response) diff --git a/backend/venv/Lib/site-packages/flask/blueprints.py b/backend/venv/Lib/site-packages/flask/blueprints.py new file mode 100644 index 0000000..b6d4e43 --- /dev/null +++ b/backend/venv/Lib/site-packages/flask/blueprints.py @@ -0,0 +1,128 @@ +from __future__ import annotations + +import os +import typing as t +from datetime import timedelta + +from .cli import AppGroup +from .globals import current_app +from .helpers import send_from_directory +from .sansio.blueprints import Blueprint as SansioBlueprint +from .sansio.blueprints import BlueprintSetupState as BlueprintSetupState # noqa +from .sansio.scaffold import _sentinel + +if t.TYPE_CHECKING: # pragma: no cover + from .wrappers import Response + + +class Blueprint(SansioBlueprint): + def __init__( + self, + name: str, + import_name: str, + static_folder: str | os.PathLike[str] | None = None, + static_url_path: str | None = None, + template_folder: str | os.PathLike[str] | None = None, + url_prefix: str | None = None, + subdomain: str | None = None, + url_defaults: dict[str, t.Any] | None = None, + root_path: str | None = None, + cli_group: str | None = _sentinel, # type: ignore + ) -> None: + super().__init__( + name, + import_name, + static_folder, + static_url_path, + template_folder, + url_prefix, + subdomain, + url_defaults, + root_path, + cli_group, + ) + + #: The Click command group for registering CLI commands for this + #: object. The commands are available from the ``flask`` command + #: once the application has been discovered and blueprints have + #: been registered. + self.cli = AppGroup() + + # Set the name of the Click group in case someone wants to add + # the app's commands to another CLI tool. + self.cli.name = self.name + + def get_send_file_max_age(self, filename: str | None) -> int | None: + """Used by :func:`send_file` to determine the ``max_age`` cache + value for a given file path if it wasn't passed. + + By default, this returns :data:`SEND_FILE_MAX_AGE_DEFAULT` from + the configuration of :data:`~flask.current_app`. This defaults + to ``None``, which tells the browser to use conditional requests + instead of a timed cache, which is usually preferable. + + Note this is a duplicate of the same method in the Flask + class. + + .. versionchanged:: 2.0 + The default configuration is ``None`` instead of 12 hours. + + .. versionadded:: 0.9 + """ + value = current_app.config["SEND_FILE_MAX_AGE_DEFAULT"] + + if value is None: + return None + + if isinstance(value, timedelta): + return int(value.total_seconds()) + + return value # type: ignore[no-any-return] + + def send_static_file(self, filename: str) -> Response: + """The view function used to serve files from + :attr:`static_folder`. A route is automatically registered for + this view at :attr:`static_url_path` if :attr:`static_folder` is + set. + + Note this is a duplicate of the same method in the Flask + class. + + .. versionadded:: 0.5 + + """ + if not self.has_static_folder: + raise RuntimeError("'static_folder' must be set to serve static_files.") + + # send_file only knows to call get_send_file_max_age on the app, + # call it here so it works for blueprints too. + max_age = self.get_send_file_max_age(filename) + return send_from_directory( + t.cast(str, self.static_folder), filename, max_age=max_age + ) + + def open_resource( + self, resource: str, mode: str = "rb", encoding: str | None = "utf-8" + ) -> t.IO[t.AnyStr]: + """Open a resource file relative to :attr:`root_path` for reading. The + blueprint-relative equivalent of the app's :meth:`~.Flask.open_resource` + method. + + :param resource: Path to the resource relative to :attr:`root_path`. + :param mode: Open the file in this mode. Only reading is supported, + valid values are ``"r"`` (or ``"rt"``) and ``"rb"``. + :param encoding: Open the file with this encoding when opening in text + mode. This is ignored when opening in binary mode. + + .. versionchanged:: 3.1 + Added the ``encoding`` parameter. + """ + if mode not in {"r", "rt", "rb"}: + raise ValueError("Resources can only be opened for reading.") + + path = os.path.join(self.root_path, resource) + + if mode == "rb": + return open(path, mode) # pyright: ignore + + return open(path, mode, encoding=encoding) diff --git a/backend/venv/Lib/site-packages/flask/cli.py b/backend/venv/Lib/site-packages/flask/cli.py new file mode 100644 index 0000000..ed11f25 --- /dev/null +++ b/backend/venv/Lib/site-packages/flask/cli.py @@ -0,0 +1,1135 @@ +from __future__ import annotations + +import ast +import collections.abc as cabc +import importlib.metadata +import inspect +import os +import platform +import re +import sys +import traceback +import typing as t +from functools import update_wrapper +from operator import itemgetter +from types import ModuleType + +import click +from click.core import ParameterSource +from werkzeug import run_simple +from werkzeug.serving import is_running_from_reloader +from werkzeug.utils import import_string + +from .globals import current_app +from .helpers import get_debug_flag +from .helpers import get_load_dotenv + +if t.TYPE_CHECKING: + import ssl + + from _typeshed.wsgi import StartResponse + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + + from .app import Flask + + +class NoAppException(click.UsageError): + """Raised if an application cannot be found or loaded.""" + + +def find_best_app(module: ModuleType) -> Flask: + """Given a module instance this tries to find the best possible + application in the module or raises an exception. + """ + from . import Flask + + # Search for the most common names first. + for attr_name in ("app", "application"): + app = getattr(module, attr_name, None) + + if isinstance(app, Flask): + return app + + # Otherwise find the only object that is a Flask instance. + matches = [v for v in module.__dict__.values() if isinstance(v, Flask)] + + if len(matches) == 1: + return matches[0] + elif len(matches) > 1: + raise NoAppException( + "Detected multiple Flask applications in module" + f" '{module.__name__}'. Use '{module.__name__}:name'" + " to specify the correct one." + ) + + # Search for app factory functions. + for attr_name in ("create_app", "make_app"): + app_factory = getattr(module, attr_name, None) + + if inspect.isfunction(app_factory): + try: + app = app_factory() + + if isinstance(app, Flask): + return app + except TypeError as e: + if not _called_with_wrong_args(app_factory): + raise + + raise NoAppException( + f"Detected factory '{attr_name}' in module '{module.__name__}'," + " but could not call it without arguments. Use" + f" '{module.__name__}:{attr_name}(args)'" + " to specify arguments." + ) from e + + raise NoAppException( + "Failed to find Flask application or factory in module" + f" '{module.__name__}'. Use '{module.__name__}:name'" + " to specify one." + ) + + +def _called_with_wrong_args(f: t.Callable[..., Flask]) -> bool: + """Check whether calling a function raised a ``TypeError`` because + the call failed or because something in the factory raised the + error. + + :param f: The function that was called. + :return: ``True`` if the call failed. + """ + tb = sys.exc_info()[2] + + try: + while tb is not None: + if tb.tb_frame.f_code is f.__code__: + # In the function, it was called successfully. + return False + + tb = tb.tb_next + + # Didn't reach the function. + return True + finally: + # Delete tb to break a circular reference. + # https://docs.python.org/2/library/sys.html#sys.exc_info + del tb + + +def find_app_by_string(module: ModuleType, app_name: str) -> Flask: + """Check if the given string is a variable name or a function. Call + a function to get the app instance, or return the variable directly. + """ + from . import Flask + + # Parse app_name as a single expression to determine if it's a valid + # attribute name or function call. + try: + expr = ast.parse(app_name.strip(), mode="eval").body + except SyntaxError: + raise NoAppException( + f"Failed to parse {app_name!r} as an attribute name or function call." + ) from None + + if isinstance(expr, ast.Name): + name = expr.id + args = [] + kwargs = {} + elif isinstance(expr, ast.Call): + # Ensure the function name is an attribute name only. + if not isinstance(expr.func, ast.Name): + raise NoAppException( + f"Function reference must be a simple name: {app_name!r}." + ) + + name = expr.func.id + + # Parse the positional and keyword arguments as literals. + try: + args = [ast.literal_eval(arg) for arg in expr.args] + kwargs = { + kw.arg: ast.literal_eval(kw.value) + for kw in expr.keywords + if kw.arg is not None + } + except ValueError: + # literal_eval gives cryptic error messages, show a generic + # message with the full expression instead. + raise NoAppException( + f"Failed to parse arguments as literal values: {app_name!r}." + ) from None + else: + raise NoAppException( + f"Failed to parse {app_name!r} as an attribute name or function call." + ) + + try: + attr = getattr(module, name) + except AttributeError as e: + raise NoAppException( + f"Failed to find attribute {name!r} in {module.__name__!r}." + ) from e + + # If the attribute is a function, call it with any args and kwargs + # to get the real application. + if inspect.isfunction(attr): + try: + app = attr(*args, **kwargs) + except TypeError as e: + if not _called_with_wrong_args(attr): + raise + + raise NoAppException( + f"The factory {app_name!r} in module" + f" {module.__name__!r} could not be called with the" + " specified arguments." + ) from e + else: + app = attr + + if isinstance(app, Flask): + return app + + raise NoAppException( + "A valid Flask application was not obtained from" + f" '{module.__name__}:{app_name}'." + ) + + +def prepare_import(path: str) -> str: + """Given a filename this will try to calculate the python path, add it + to the search path and return the actual module name that is expected. + """ + path = os.path.realpath(path) + + fname, ext = os.path.splitext(path) + if ext == ".py": + path = fname + + if os.path.basename(path) == "__init__": + path = os.path.dirname(path) + + module_name = [] + + # move up until outside package structure (no __init__.py) + while True: + path, name = os.path.split(path) + module_name.append(name) + + if not os.path.exists(os.path.join(path, "__init__.py")): + break + + if sys.path[0] != path: + sys.path.insert(0, path) + + return ".".join(module_name[::-1]) + + +@t.overload +def locate_app( + module_name: str, app_name: str | None, raise_if_not_found: t.Literal[True] = True +) -> Flask: ... + + +@t.overload +def locate_app( + module_name: str, app_name: str | None, raise_if_not_found: t.Literal[False] = ... +) -> Flask | None: ... + + +def locate_app( + module_name: str, app_name: str | None, raise_if_not_found: bool = True +) -> Flask | None: + try: + __import__(module_name) + except ImportError: + # Reraise the ImportError if it occurred within the imported module. + # Determine this by checking whether the trace has a depth > 1. + if sys.exc_info()[2].tb_next: # type: ignore[union-attr] + raise NoAppException( + f"While importing {module_name!r}, an ImportError was" + f" raised:\n\n{traceback.format_exc()}" + ) from None + elif raise_if_not_found: + raise NoAppException(f"Could not import {module_name!r}.") from None + else: + return None + + module = sys.modules[module_name] + + if app_name is None: + return find_best_app(module) + else: + return find_app_by_string(module, app_name) + + +def get_version(ctx: click.Context, param: click.Parameter, value: t.Any) -> None: + if not value or ctx.resilient_parsing: + return + + flask_version = importlib.metadata.version("flask") + werkzeug_version = importlib.metadata.version("werkzeug") + + click.echo( + f"Python {platform.python_version()}\n" + f"Flask {flask_version}\n" + f"Werkzeug {werkzeug_version}", + color=ctx.color, + ) + ctx.exit() + + +version_option = click.Option( + ["--version"], + help="Show the Flask version.", + expose_value=False, + callback=get_version, + is_flag=True, + is_eager=True, +) + + +class ScriptInfo: + """Helper object to deal with Flask applications. This is usually not + necessary to interface with as it's used internally in the dispatching + to click. In future versions of Flask this object will most likely play + a bigger role. Typically it's created automatically by the + :class:`FlaskGroup` but you can also manually create it and pass it + onwards as click object. + + .. versionchanged:: 3.1 + Added the ``load_dotenv_defaults`` parameter and attribute. + """ + + def __init__( + self, + app_import_path: str | None = None, + create_app: t.Callable[..., Flask] | None = None, + set_debug_flag: bool = True, + load_dotenv_defaults: bool = True, + ) -> None: + #: Optionally the import path for the Flask application. + self.app_import_path = app_import_path + #: Optionally a function that is passed the script info to create + #: the instance of the application. + self.create_app = create_app + #: A dictionary with arbitrary data that can be associated with + #: this script info. + self.data: dict[t.Any, t.Any] = {} + self.set_debug_flag = set_debug_flag + + self.load_dotenv_defaults = get_load_dotenv(load_dotenv_defaults) + """Whether default ``.flaskenv`` and ``.env`` files should be loaded. + + ``ScriptInfo`` doesn't load anything, this is for reference when doing + the load elsewhere during processing. + + .. versionadded:: 3.1 + """ + + self._loaded_app: Flask | None = None + + def load_app(self) -> Flask: + """Loads the Flask app (if not yet loaded) and returns it. Calling + this multiple times will just result in the already loaded app to + be returned. + """ + if self._loaded_app is not None: + return self._loaded_app + app: Flask | None = None + if self.create_app is not None: + app = self.create_app() + else: + if self.app_import_path: + path, name = ( + re.split(r":(?![\\/])", self.app_import_path, maxsplit=1) + [None] + )[:2] + import_name = prepare_import(path) + app = locate_app(import_name, name) + else: + for path in ("wsgi.py", "app.py"): + import_name = prepare_import(path) + app = locate_app(import_name, None, raise_if_not_found=False) + + if app is not None: + break + + if app is None: + raise NoAppException( + "Could not locate a Flask application. Use the" + " 'flask --app' option, 'FLASK_APP' environment" + " variable, or a 'wsgi.py' or 'app.py' file in the" + " current directory." + ) + + if self.set_debug_flag: + # Update the app's debug flag through the descriptor so that + # other values repopulate as well. + app.debug = get_debug_flag() + + self._loaded_app = app + return app + + +pass_script_info = click.make_pass_decorator(ScriptInfo, ensure=True) + +F = t.TypeVar("F", bound=t.Callable[..., t.Any]) + + +def with_appcontext(f: F) -> F: + """Wraps a callback so that it's guaranteed to be executed with the + script's application context. + + Custom commands (and their options) registered under ``app.cli`` or + ``blueprint.cli`` will always have an app context available, this + decorator is not required in that case. + + .. versionchanged:: 2.2 + The app context is active for subcommands as well as the + decorated callback. The app context is always available to + ``app.cli`` command and parameter callbacks. + """ + + @click.pass_context + def decorator(ctx: click.Context, /, *args: t.Any, **kwargs: t.Any) -> t.Any: + if not current_app: + app = ctx.ensure_object(ScriptInfo).load_app() + ctx.with_resource(app.app_context()) + + return ctx.invoke(f, *args, **kwargs) + + return update_wrapper(decorator, f) # type: ignore[return-value] + + +class AppGroup(click.Group): + """This works similar to a regular click :class:`~click.Group` but it + changes the behavior of the :meth:`command` decorator so that it + automatically wraps the functions in :func:`with_appcontext`. + + Not to be confused with :class:`FlaskGroup`. + """ + + def command( # type: ignore[override] + self, *args: t.Any, **kwargs: t.Any + ) -> t.Callable[[t.Callable[..., t.Any]], click.Command]: + """This works exactly like the method of the same name on a regular + :class:`click.Group` but it wraps callbacks in :func:`with_appcontext` + unless it's disabled by passing ``with_appcontext=False``. + """ + wrap_for_ctx = kwargs.pop("with_appcontext", True) + + def decorator(f: t.Callable[..., t.Any]) -> click.Command: + if wrap_for_ctx: + f = with_appcontext(f) + return super(AppGroup, self).command(*args, **kwargs)(f) # type: ignore[no-any-return] + + return decorator + + def group( # type: ignore[override] + self, *args: t.Any, **kwargs: t.Any + ) -> t.Callable[[t.Callable[..., t.Any]], click.Group]: + """This works exactly like the method of the same name on a regular + :class:`click.Group` but it defaults the group class to + :class:`AppGroup`. + """ + kwargs.setdefault("cls", AppGroup) + return super().group(*args, **kwargs) # type: ignore[no-any-return] + + +def _set_app(ctx: click.Context, param: click.Option, value: str | None) -> str | None: + if value is None: + return None + + info = ctx.ensure_object(ScriptInfo) + info.app_import_path = value + return value + + +# This option is eager so the app will be available if --help is given. +# --help is also eager, so --app must be before it in the param list. +# no_args_is_help bypasses eager processing, so this option must be +# processed manually in that case to ensure FLASK_APP gets picked up. +_app_option = click.Option( + ["-A", "--app"], + metavar="IMPORT", + help=( + "The Flask application or factory function to load, in the form 'module:name'." + " Module can be a dotted import or file path. Name is not required if it is" + " 'app', 'application', 'create_app', or 'make_app', and can be 'name(args)' to" + " pass arguments." + ), + is_eager=True, + expose_value=False, + callback=_set_app, +) + + +def _set_debug(ctx: click.Context, param: click.Option, value: bool) -> bool | None: + # If the flag isn't provided, it will default to False. Don't use + # that, let debug be set by env in that case. + source = ctx.get_parameter_source(param.name) # type: ignore[arg-type] + + if source is not None and source in ( + ParameterSource.DEFAULT, + ParameterSource.DEFAULT_MAP, + ): + return None + + # Set with env var instead of ScriptInfo.load so that it can be + # accessed early during a factory function. + os.environ["FLASK_DEBUG"] = "1" if value else "0" + return value + + +_debug_option = click.Option( + ["--debug/--no-debug"], + help="Set debug mode.", + expose_value=False, + callback=_set_debug, +) + + +def _env_file_callback( + ctx: click.Context, param: click.Option, value: str | None +) -> str | None: + try: + import dotenv # noqa: F401 + except ImportError: + # Only show an error if a value was passed, otherwise we still want to + # call load_dotenv and show a message without exiting. + if value is not None: + raise click.BadParameter( + "python-dotenv must be installed to load an env file.", + ctx=ctx, + param=param, + ) from None + + # Load if a value was passed, or we want to load default files, or both. + if value is not None or ctx.obj.load_dotenv_defaults: + load_dotenv(value, load_defaults=ctx.obj.load_dotenv_defaults) + + return value + + +# This option is eager so env vars are loaded as early as possible to be +# used by other options. +_env_file_option = click.Option( + ["-e", "--env-file"], + type=click.Path(exists=True, dir_okay=False), + help=( + "Load environment variables from this file, taking precedence over" + " those set by '.env' and '.flaskenv'. Variables set directly in the" + " environment take highest precedence. python-dotenv must be installed." + ), + is_eager=True, + expose_value=False, + callback=_env_file_callback, +) + + +class FlaskGroup(AppGroup): + """Special subclass of the :class:`AppGroup` group that supports + loading more commands from the configured Flask app. Normally a + developer does not have to interface with this class but there are + some very advanced use cases for which it makes sense to create an + instance of this. see :ref:`custom-scripts`. + + :param add_default_commands: if this is True then the default run and + shell commands will be added. + :param add_version_option: adds the ``--version`` option. + :param create_app: an optional callback that is passed the script info and + returns the loaded app. + :param load_dotenv: Load the nearest :file:`.env` and :file:`.flaskenv` + files to set environment variables. Will also change the working + directory to the directory containing the first file found. + :param set_debug_flag: Set the app's debug flag. + + .. versionchanged:: 3.1 + ``-e path`` takes precedence over default ``.env`` and ``.flaskenv`` files. + + .. versionchanged:: 2.2 + Added the ``-A/--app``, ``--debug/--no-debug``, ``-e/--env-file`` options. + + .. versionchanged:: 2.2 + An app context is pushed when running ``app.cli`` commands, so + ``@with_appcontext`` is no longer required for those commands. + + .. versionchanged:: 1.0 + If installed, python-dotenv will be used to load environment variables + from :file:`.env` and :file:`.flaskenv` files. + """ + + def __init__( + self, + add_default_commands: bool = True, + create_app: t.Callable[..., Flask] | None = None, + add_version_option: bool = True, + load_dotenv: bool = True, + set_debug_flag: bool = True, + **extra: t.Any, + ) -> None: + params: list[click.Parameter] = list(extra.pop("params", None) or ()) + # Processing is done with option callbacks instead of a group + # callback. This allows users to make a custom group callback + # without losing the behavior. --env-file must come first so + # that it is eagerly evaluated before --app. + params.extend((_env_file_option, _app_option, _debug_option)) + + if add_version_option: + params.append(version_option) + + if "context_settings" not in extra: + extra["context_settings"] = {} + + extra["context_settings"].setdefault("auto_envvar_prefix", "FLASK") + + super().__init__(params=params, **extra) + + self.create_app = create_app + self.load_dotenv = load_dotenv + self.set_debug_flag = set_debug_flag + + if add_default_commands: + self.add_command(run_command) + self.add_command(shell_command) + self.add_command(routes_command) + + self._loaded_plugin_commands = False + + def _load_plugin_commands(self) -> None: + if self._loaded_plugin_commands: + return + + if sys.version_info >= (3, 10): + from importlib import metadata + else: + # Use a backport on Python < 3.10. We technically have + # importlib.metadata on 3.8+, but the API changed in 3.10, + # so use the backport for consistency. + import importlib_metadata as metadata # pyright: ignore + + for ep in metadata.entry_points(group="flask.commands"): + self.add_command(ep.load(), ep.name) + + self._loaded_plugin_commands = True + + def get_command(self, ctx: click.Context, name: str) -> click.Command | None: + self._load_plugin_commands() + # Look up built-in and plugin commands, which should be + # available even if the app fails to load. + rv = super().get_command(ctx, name) + + if rv is not None: + return rv + + info = ctx.ensure_object(ScriptInfo) + + # Look up commands provided by the app, showing an error and + # continuing if the app couldn't be loaded. + try: + app = info.load_app() + except NoAppException as e: + click.secho(f"Error: {e.format_message()}\n", err=True, fg="red") + return None + + # Push an app context for the loaded app unless it is already + # active somehow. This makes the context available to parameter + # and command callbacks without needing @with_appcontext. + if not current_app or current_app._get_current_object() is not app: # type: ignore[attr-defined] + ctx.with_resource(app.app_context()) + + return app.cli.get_command(ctx, name) + + def list_commands(self, ctx: click.Context) -> list[str]: + self._load_plugin_commands() + # Start with the built-in and plugin commands. + rv = set(super().list_commands(ctx)) + info = ctx.ensure_object(ScriptInfo) + + # Add commands provided by the app, showing an error and + # continuing if the app couldn't be loaded. + try: + rv.update(info.load_app().cli.list_commands(ctx)) + except NoAppException as e: + # When an app couldn't be loaded, show the error message + # without the traceback. + click.secho(f"Error: {e.format_message()}\n", err=True, fg="red") + except Exception: + # When any other errors occurred during loading, show the + # full traceback. + click.secho(f"{traceback.format_exc()}\n", err=True, fg="red") + + return sorted(rv) + + def make_context( + self, + info_name: str | None, + args: list[str], + parent: click.Context | None = None, + **extra: t.Any, + ) -> click.Context: + # Set a flag to tell app.run to become a no-op. If app.run was + # not in a __name__ == __main__ guard, it would start the server + # when importing, blocking whatever command is being called. + os.environ["FLASK_RUN_FROM_CLI"] = "true" + + if "obj" not in extra and "obj" not in self.context_settings: + extra["obj"] = ScriptInfo( + create_app=self.create_app, + set_debug_flag=self.set_debug_flag, + load_dotenv_defaults=self.load_dotenv, + ) + + return super().make_context(info_name, args, parent=parent, **extra) + + def parse_args(self, ctx: click.Context, args: list[str]) -> list[str]: + if (not args and self.no_args_is_help) or ( + len(args) == 1 and args[0] in self.get_help_option_names(ctx) + ): + # Attempt to load --env-file and --app early in case they + # were given as env vars. Otherwise no_args_is_help will not + # see commands from app.cli. + _env_file_option.handle_parse_result(ctx, {}, []) + _app_option.handle_parse_result(ctx, {}, []) + + return super().parse_args(ctx, args) + + +def _path_is_ancestor(path: str, other: str) -> bool: + """Take ``other`` and remove the length of ``path`` from it. Then join it + to ``path``. If it is the original value, ``path`` is an ancestor of + ``other``.""" + return os.path.join(path, other[len(path) :].lstrip(os.sep)) == other + + +def load_dotenv( + path: str | os.PathLike[str] | None = None, load_defaults: bool = True +) -> bool: + """Load "dotenv" files to set environment variables. A given path takes + precedence over ``.env``, which takes precedence over ``.flaskenv``. After + loading and combining these files, values are only set if the key is not + already set in ``os.environ``. + + This is a no-op if `python-dotenv`_ is not installed. + + .. _python-dotenv: https://github.com/theskumar/python-dotenv#readme + + :param path: Load the file at this location. + :param load_defaults: Search for and load the default ``.flaskenv`` and + ``.env`` files. + :return: ``True`` if at least one env var was loaded. + + .. versionchanged:: 3.1 + Added the ``load_defaults`` parameter. A given path takes precedence + over default files. + + .. versionchanged:: 2.0 + The current directory is not changed to the location of the + loaded file. + + .. versionchanged:: 2.0 + When loading the env files, set the default encoding to UTF-8. + + .. versionchanged:: 1.1.0 + Returns ``False`` when python-dotenv is not installed, or when + the given path isn't a file. + + .. versionadded:: 1.0 + """ + try: + import dotenv + except ImportError: + if path or os.path.isfile(".env") or os.path.isfile(".flaskenv"): + click.secho( + " * Tip: There are .env files present. Install python-dotenv" + " to use them.", + fg="yellow", + err=True, + ) + + return False + + data: dict[str, str | None] = {} + + if load_defaults: + for default_name in (".flaskenv", ".env"): + if not (default_path := dotenv.find_dotenv(default_name, usecwd=True)): + continue + + data |= dotenv.dotenv_values(default_path, encoding="utf-8") + + if path is not None and os.path.isfile(path): + data |= dotenv.dotenv_values(path, encoding="utf-8") + + for key, value in data.items(): + if key in os.environ or value is None: + continue + + os.environ[key] = value + + return bool(data) # True if at least one env var was loaded. + + +def show_server_banner(debug: bool, app_import_path: str | None) -> None: + """Show extra startup messages the first time the server is run, + ignoring the reloader. + """ + if is_running_from_reloader(): + return + + if app_import_path is not None: + click.echo(f" * Serving Flask app '{app_import_path}'") + + if debug is not None: + click.echo(f" * Debug mode: {'on' if debug else 'off'}") + + +class CertParamType(click.ParamType): + """Click option type for the ``--cert`` option. Allows either an + existing file, the string ``'adhoc'``, or an import for a + :class:`~ssl.SSLContext` object. + """ + + name = "path" + + def __init__(self) -> None: + self.path_type = click.Path(exists=True, dir_okay=False, resolve_path=True) + + def convert( + self, value: t.Any, param: click.Parameter | None, ctx: click.Context | None + ) -> t.Any: + try: + import ssl + except ImportError: + raise click.BadParameter( + 'Using "--cert" requires Python to be compiled with SSL support.', + ctx, + param, + ) from None + + try: + return self.path_type(value, param, ctx) + except click.BadParameter: + value = click.STRING(value, param, ctx).lower() + + if value == "adhoc": + try: + import cryptography # noqa: F401 + except ImportError: + raise click.BadParameter( + "Using ad-hoc certificates requires the cryptography library.", + ctx, + param, + ) from None + + return value + + obj = import_string(value, silent=True) + + if isinstance(obj, ssl.SSLContext): + return obj + + raise + + +def _validate_key(ctx: click.Context, param: click.Parameter, value: t.Any) -> t.Any: + """The ``--key`` option must be specified when ``--cert`` is a file. + Modifies the ``cert`` param to be a ``(cert, key)`` pair if needed. + """ + cert = ctx.params.get("cert") + is_adhoc = cert == "adhoc" + + try: + import ssl + except ImportError: + is_context = False + else: + is_context = isinstance(cert, ssl.SSLContext) + + if value is not None: + if is_adhoc: + raise click.BadParameter( + 'When "--cert" is "adhoc", "--key" is not used.', ctx, param + ) + + if is_context: + raise click.BadParameter( + 'When "--cert" is an SSLContext object, "--key" is not used.', + ctx, + param, + ) + + if not cert: + raise click.BadParameter('"--cert" must also be specified.', ctx, param) + + ctx.params["cert"] = cert, value + + else: + if cert and not (is_adhoc or is_context): + raise click.BadParameter('Required when using "--cert".', ctx, param) + + return value + + +class SeparatedPathType(click.Path): + """Click option type that accepts a list of values separated by the + OS's path separator (``:``, ``;`` on Windows). Each value is + validated as a :class:`click.Path` type. + """ + + def convert( + self, value: t.Any, param: click.Parameter | None, ctx: click.Context | None + ) -> t.Any: + items = self.split_envvar_value(value) + # can't call no-arg super() inside list comprehension until Python 3.12 + super_convert = super().convert + return [super_convert(item, param, ctx) for item in items] + + +@click.command("run", short_help="Run a development server.") +@click.option("--host", "-h", default="127.0.0.1", help="The interface to bind to.") +@click.option("--port", "-p", default=5000, help="The port to bind to.") +@click.option( + "--cert", + type=CertParamType(), + help="Specify a certificate file to use HTTPS.", + is_eager=True, +) +@click.option( + "--key", + type=click.Path(exists=True, dir_okay=False, resolve_path=True), + callback=_validate_key, + expose_value=False, + help="The key file to use when specifying a certificate.", +) +@click.option( + "--reload/--no-reload", + default=None, + help="Enable or disable the reloader. By default the reloader " + "is active if debug is enabled.", +) +@click.option( + "--debugger/--no-debugger", + default=None, + help="Enable or disable the debugger. By default the debugger " + "is active if debug is enabled.", +) +@click.option( + "--with-threads/--without-threads", + default=True, + help="Enable or disable multithreading.", +) +@click.option( + "--extra-files", + default=None, + type=SeparatedPathType(), + help=( + "Extra files that trigger a reload on change. Multiple paths" + f" are separated by {os.path.pathsep!r}." + ), +) +@click.option( + "--exclude-patterns", + default=None, + type=SeparatedPathType(), + help=( + "Files matching these fnmatch patterns will not trigger a reload" + " on change. Multiple patterns are separated by" + f" {os.path.pathsep!r}." + ), +) +@pass_script_info +def run_command( + info: ScriptInfo, + host: str, + port: int, + reload: bool, + debugger: bool, + with_threads: bool, + cert: ssl.SSLContext | tuple[str, str | None] | t.Literal["adhoc"] | None, + extra_files: list[str] | None, + exclude_patterns: list[str] | None, +) -> None: + """Run a local development server. + + This server is for development purposes only. It does not provide + the stability, security, or performance of production WSGI servers. + + The reloader and debugger are enabled by default with the '--debug' + option. + """ + try: + app: WSGIApplication = info.load_app() # pyright: ignore + except Exception as e: + if is_running_from_reloader(): + # When reloading, print out the error immediately, but raise + # it later so the debugger or server can handle it. + traceback.print_exc() + err = e + + def app( + environ: WSGIEnvironment, start_response: StartResponse + ) -> cabc.Iterable[bytes]: + raise err from None + + else: + # When not reloading, raise the error immediately so the + # command fails. + raise e from None + + debug = get_debug_flag() + + if reload is None: + reload = debug + + if debugger is None: + debugger = debug + + show_server_banner(debug, info.app_import_path) + + run_simple( + host, + port, + app, + use_reloader=reload, + use_debugger=debugger, + threaded=with_threads, + ssl_context=cert, + extra_files=extra_files, + exclude_patterns=exclude_patterns, + ) + + +run_command.params.insert(0, _debug_option) + + +@click.command("shell", short_help="Run a shell in the app context.") +@with_appcontext +def shell_command() -> None: + """Run an interactive Python shell in the context of a given + Flask application. The application will populate the default + namespace of this shell according to its configuration. + + This is useful for executing small snippets of management code + without having to manually configure the application. + """ + import code + + banner = ( + f"Python {sys.version} on {sys.platform}\n" + f"App: {current_app.import_name}\n" + f"Instance: {current_app.instance_path}" + ) + ctx: dict[str, t.Any] = {} + + # Support the regular Python interpreter startup script if someone + # is using it. + startup = os.environ.get("PYTHONSTARTUP") + if startup and os.path.isfile(startup): + with open(startup) as f: + eval(compile(f.read(), startup, "exec"), ctx) + + ctx.update(current_app.make_shell_context()) + + # Site, customize, or startup script can set a hook to call when + # entering interactive mode. The default one sets up readline with + # tab and history completion. + interactive_hook = getattr(sys, "__interactivehook__", None) + + if interactive_hook is not None: + try: + import readline + from rlcompleter import Completer + except ImportError: + pass + else: + # rlcompleter uses __main__.__dict__ by default, which is + # flask.__main__. Use the shell context instead. + readline.set_completer(Completer(ctx).complete) + + interactive_hook() + + code.interact(banner=banner, local=ctx) + + +@click.command("routes", short_help="Show the routes for the app.") +@click.option( + "--sort", + "-s", + type=click.Choice(("endpoint", "methods", "domain", "rule", "match")), + default="endpoint", + help=( + "Method to sort routes by. 'match' is the order that Flask will match routes" + " when dispatching a request." + ), +) +@click.option("--all-methods", is_flag=True, help="Show HEAD and OPTIONS methods.") +@with_appcontext +def routes_command(sort: str, all_methods: bool) -> None: + """Show all registered routes with endpoints and methods.""" + rules = list(current_app.url_map.iter_rules()) + + if not rules: + click.echo("No routes were registered.") + return + + ignored_methods = set() if all_methods else {"HEAD", "OPTIONS"} + host_matching = current_app.url_map.host_matching + has_domain = any(rule.host if host_matching else rule.subdomain for rule in rules) + rows = [] + + for rule in rules: + row = [ + rule.endpoint, + ", ".join(sorted((rule.methods or set()) - ignored_methods)), + ] + + if has_domain: + row.append((rule.host if host_matching else rule.subdomain) or "") + + row.append(rule.rule) + rows.append(row) + + headers = ["Endpoint", "Methods"] + sorts = ["endpoint", "methods"] + + if has_domain: + headers.append("Host" if host_matching else "Subdomain") + sorts.append("domain") + + headers.append("Rule") + sorts.append("rule") + + try: + rows.sort(key=itemgetter(sorts.index(sort))) + except ValueError: + pass + + rows.insert(0, headers) + widths = [max(len(row[i]) for row in rows) for i in range(len(headers))] + rows.insert(1, ["-" * w for w in widths]) + template = " ".join(f"{{{i}:<{w}}}" for i, w in enumerate(widths)) + + for row in rows: + click.echo(template.format(*row)) + + +cli = FlaskGroup( + name="flask", + help="""\ +A general utility script for Flask applications. + +An application to load must be given with the '--app' option, +'FLASK_APP' environment variable, or with a 'wsgi.py' or 'app.py' file +in the current directory. +""", +) + + +def main() -> None: + cli.main() + + +if __name__ == "__main__": + main() diff --git a/backend/venv/Lib/site-packages/flask/config.py b/backend/venv/Lib/site-packages/flask/config.py new file mode 100644 index 0000000..34ef1a5 --- /dev/null +++ b/backend/venv/Lib/site-packages/flask/config.py @@ -0,0 +1,367 @@ +from __future__ import annotations + +import errno +import json +import os +import types +import typing as t + +from werkzeug.utils import import_string + +if t.TYPE_CHECKING: + import typing_extensions as te + + from .sansio.app import App + + +T = t.TypeVar("T") + + +class ConfigAttribute(t.Generic[T]): + """Makes an attribute forward to the config""" + + def __init__( + self, name: str, get_converter: t.Callable[[t.Any], T] | None = None + ) -> None: + self.__name__ = name + self.get_converter = get_converter + + @t.overload + def __get__(self, obj: None, owner: None) -> te.Self: ... + + @t.overload + def __get__(self, obj: App, owner: type[App]) -> T: ... + + def __get__(self, obj: App | None, owner: type[App] | None = None) -> T | te.Self: + if obj is None: + return self + + rv = obj.config[self.__name__] + + if self.get_converter is not None: + rv = self.get_converter(rv) + + return rv # type: ignore[no-any-return] + + def __set__(self, obj: App, value: t.Any) -> None: + obj.config[self.__name__] = value + + +class Config(dict): # type: ignore[type-arg] + """Works exactly like a dict but provides ways to fill it from files + or special dictionaries. There are two common patterns to populate the + config. + + Either you can fill the config from a config file:: + + app.config.from_pyfile('yourconfig.cfg') + + Or alternatively you can define the configuration options in the + module that calls :meth:`from_object` or provide an import path to + a module that should be loaded. It is also possible to tell it to + use the same module and with that provide the configuration values + just before the call:: + + DEBUG = True + SECRET_KEY = 'development key' + app.config.from_object(__name__) + + In both cases (loading from any Python file or loading from modules), + only uppercase keys are added to the config. This makes it possible to use + lowercase values in the config file for temporary values that are not added + to the config or to define the config keys in the same file that implements + the application. + + Probably the most interesting way to load configurations is from an + environment variable pointing to a file:: + + app.config.from_envvar('YOURAPPLICATION_SETTINGS') + + In this case before launching the application you have to set this + environment variable to the file you want to use. On Linux and OS X + use the export statement:: + + export YOURAPPLICATION_SETTINGS='/path/to/config/file' + + On windows use `set` instead. + + :param root_path: path to which files are read relative from. When the + config object is created by the application, this is + the application's :attr:`~flask.Flask.root_path`. + :param defaults: an optional dictionary of default values + """ + + def __init__( + self, + root_path: str | os.PathLike[str], + defaults: dict[str, t.Any] | None = None, + ) -> None: + super().__init__(defaults or {}) + self.root_path = root_path + + def from_envvar(self, variable_name: str, silent: bool = False) -> bool: + """Loads a configuration from an environment variable pointing to + a configuration file. This is basically just a shortcut with nicer + error messages for this line of code:: + + app.config.from_pyfile(os.environ['YOURAPPLICATION_SETTINGS']) + + :param variable_name: name of the environment variable + :param silent: set to ``True`` if you want silent failure for missing + files. + :return: ``True`` if the file was loaded successfully. + """ + rv = os.environ.get(variable_name) + if not rv: + if silent: + return False + raise RuntimeError( + f"The environment variable {variable_name!r} is not set" + " and as such configuration could not be loaded. Set" + " this variable and make it point to a configuration" + " file" + ) + return self.from_pyfile(rv, silent=silent) + + def from_prefixed_env( + self, prefix: str = "FLASK", *, loads: t.Callable[[str], t.Any] = json.loads + ) -> bool: + """Load any environment variables that start with ``FLASK_``, + dropping the prefix from the env key for the config key. Values + are passed through a loading function to attempt to convert them + to more specific types than strings. + + Keys are loaded in :func:`sorted` order. + + The default loading function attempts to parse values as any + valid JSON type, including dicts and lists. + + Specific items in nested dicts can be set by separating the + keys with double underscores (``__``). If an intermediate key + doesn't exist, it will be initialized to an empty dict. + + :param prefix: Load env vars that start with this prefix, + separated with an underscore (``_``). + :param loads: Pass each string value to this function and use + the returned value as the config value. If any error is + raised it is ignored and the value remains a string. The + default is :func:`json.loads`. + + .. versionadded:: 2.1 + """ + prefix = f"{prefix}_" + + for key in sorted(os.environ): + if not key.startswith(prefix): + continue + + value = os.environ[key] + key = key.removeprefix(prefix) + + try: + value = loads(value) + except Exception: + # Keep the value as a string if loading failed. + pass + + if "__" not in key: + # A non-nested key, set directly. + self[key] = value + continue + + # Traverse nested dictionaries with keys separated by "__". + current = self + *parts, tail = key.split("__") + + for part in parts: + # If an intermediate dict does not exist, create it. + if part not in current: + current[part] = {} + + current = current[part] + + current[tail] = value + + return True + + def from_pyfile( + self, filename: str | os.PathLike[str], silent: bool = False + ) -> bool: + """Updates the values in the config from a Python file. This function + behaves as if the file was imported as module with the + :meth:`from_object` function. + + :param filename: the filename of the config. This can either be an + absolute filename or a filename relative to the + root path. + :param silent: set to ``True`` if you want silent failure for missing + files. + :return: ``True`` if the file was loaded successfully. + + .. versionadded:: 0.7 + `silent` parameter. + """ + filename = os.path.join(self.root_path, filename) + d = types.ModuleType("config") + d.__file__ = filename + try: + with open(filename, mode="rb") as config_file: + exec(compile(config_file.read(), filename, "exec"), d.__dict__) + except OSError as e: + if silent and e.errno in (errno.ENOENT, errno.EISDIR, errno.ENOTDIR): + return False + e.strerror = f"Unable to load configuration file ({e.strerror})" + raise + self.from_object(d) + return True + + def from_object(self, obj: object | str) -> None: + """Updates the values from the given object. An object can be of one + of the following two types: + + - a string: in this case the object with that name will be imported + - an actual object reference: that object is used directly + + Objects are usually either modules or classes. :meth:`from_object` + loads only the uppercase attributes of the module/class. A ``dict`` + object will not work with :meth:`from_object` because the keys of a + ``dict`` are not attributes of the ``dict`` class. + + Example of module-based configuration:: + + app.config.from_object('yourapplication.default_config') + from yourapplication import default_config + app.config.from_object(default_config) + + Nothing is done to the object before loading. If the object is a + class and has ``@property`` attributes, it needs to be + instantiated before being passed to this method. + + You should not use this function to load the actual configuration but + rather configuration defaults. The actual config should be loaded + with :meth:`from_pyfile` and ideally from a location not within the + package because the package might be installed system wide. + + See :ref:`config-dev-prod` for an example of class-based configuration + using :meth:`from_object`. + + :param obj: an import name or object + """ + if isinstance(obj, str): + obj = import_string(obj) + for key in dir(obj): + if key.isupper(): + self[key] = getattr(obj, key) + + def from_file( + self, + filename: str | os.PathLike[str], + load: t.Callable[[t.IO[t.Any]], t.Mapping[str, t.Any]], + silent: bool = False, + text: bool = True, + ) -> bool: + """Update the values in the config from a file that is loaded + using the ``load`` parameter. The loaded data is passed to the + :meth:`from_mapping` method. + + .. code-block:: python + + import json + app.config.from_file("config.json", load=json.load) + + import tomllib + app.config.from_file("config.toml", load=tomllib.load, text=False) + + :param filename: The path to the data file. This can be an + absolute path or relative to the config root path. + :param load: A callable that takes a file handle and returns a + mapping of loaded data from the file. + :type load: ``Callable[[Reader], Mapping]`` where ``Reader`` + implements a ``read`` method. + :param silent: Ignore the file if it doesn't exist. + :param text: Open the file in text or binary mode. + :return: ``True`` if the file was loaded successfully. + + .. versionchanged:: 2.3 + The ``text`` parameter was added. + + .. versionadded:: 2.0 + """ + filename = os.path.join(self.root_path, filename) + + try: + with open(filename, "r" if text else "rb") as f: + obj = load(f) + except OSError as e: + if silent and e.errno in (errno.ENOENT, errno.EISDIR): + return False + + e.strerror = f"Unable to load configuration file ({e.strerror})" + raise + + return self.from_mapping(obj) + + def from_mapping( + self, mapping: t.Mapping[str, t.Any] | None = None, **kwargs: t.Any + ) -> bool: + """Updates the config like :meth:`update` ignoring items with + non-upper keys. + + :return: Always returns ``True``. + + .. versionadded:: 0.11 + """ + mappings: dict[str, t.Any] = {} + if mapping is not None: + mappings.update(mapping) + mappings.update(kwargs) + for key, value in mappings.items(): + if key.isupper(): + self[key] = value + return True + + def get_namespace( + self, namespace: str, lowercase: bool = True, trim_namespace: bool = True + ) -> dict[str, t.Any]: + """Returns a dictionary containing a subset of configuration options + that match the specified namespace/prefix. Example usage:: + + app.config['IMAGE_STORE_TYPE'] = 'fs' + app.config['IMAGE_STORE_PATH'] = '/var/app/images' + app.config['IMAGE_STORE_BASE_URL'] = 'http://img.website.com' + image_store_config = app.config.get_namespace('IMAGE_STORE_') + + The resulting dictionary `image_store_config` would look like:: + + { + 'type': 'fs', + 'path': '/var/app/images', + 'base_url': 'http://img.website.com' + } + + This is often useful when configuration options map directly to + keyword arguments in functions or class constructors. + + :param namespace: a configuration namespace + :param lowercase: a flag indicating if the keys of the resulting + dictionary should be lowercase + :param trim_namespace: a flag indicating if the keys of the resulting + dictionary should not include the namespace + + .. versionadded:: 0.11 + """ + rv = {} + for k, v in self.items(): + if not k.startswith(namespace): + continue + if trim_namespace: + key = k[len(namespace) :] + else: + key = k + if lowercase: + key = key.lower() + rv[key] = v + return rv + + def __repr__(self) -> str: + return f"<{type(self).__name__} {dict.__repr__(self)}>" diff --git a/backend/venv/Lib/site-packages/flask/ctx.py b/backend/venv/Lib/site-packages/flask/ctx.py new file mode 100644 index 0000000..222e818 --- /dev/null +++ b/backend/venv/Lib/site-packages/flask/ctx.py @@ -0,0 +1,449 @@ +from __future__ import annotations + +import contextvars +import sys +import typing as t +from functools import update_wrapper +from types import TracebackType + +from werkzeug.exceptions import HTTPException + +from . import typing as ft +from .globals import _cv_app +from .globals import _cv_request +from .signals import appcontext_popped +from .signals import appcontext_pushed + +if t.TYPE_CHECKING: # pragma: no cover + from _typeshed.wsgi import WSGIEnvironment + + from .app import Flask + from .sessions import SessionMixin + from .wrappers import Request + + +# a singleton sentinel value for parameter defaults +_sentinel = object() + + +class _AppCtxGlobals: + """A plain object. Used as a namespace for storing data during an + application context. + + Creating an app context automatically creates this object, which is + made available as the :data:`g` proxy. + + .. describe:: 'key' in g + + Check whether an attribute is present. + + .. versionadded:: 0.10 + + .. describe:: iter(g) + + Return an iterator over the attribute names. + + .. versionadded:: 0.10 + """ + + # Define attr methods to let mypy know this is a namespace object + # that has arbitrary attributes. + + def __getattr__(self, name: str) -> t.Any: + try: + return self.__dict__[name] + except KeyError: + raise AttributeError(name) from None + + def __setattr__(self, name: str, value: t.Any) -> None: + self.__dict__[name] = value + + def __delattr__(self, name: str) -> None: + try: + del self.__dict__[name] + except KeyError: + raise AttributeError(name) from None + + def get(self, name: str, default: t.Any | None = None) -> t.Any: + """Get an attribute by name, or a default value. Like + :meth:`dict.get`. + + :param name: Name of attribute to get. + :param default: Value to return if the attribute is not present. + + .. versionadded:: 0.10 + """ + return self.__dict__.get(name, default) + + def pop(self, name: str, default: t.Any = _sentinel) -> t.Any: + """Get and remove an attribute by name. Like :meth:`dict.pop`. + + :param name: Name of attribute to pop. + :param default: Value to return if the attribute is not present, + instead of raising a ``KeyError``. + + .. versionadded:: 0.11 + """ + if default is _sentinel: + return self.__dict__.pop(name) + else: + return self.__dict__.pop(name, default) + + def setdefault(self, name: str, default: t.Any = None) -> t.Any: + """Get the value of an attribute if it is present, otherwise + set and return a default value. Like :meth:`dict.setdefault`. + + :param name: Name of attribute to get. + :param default: Value to set and return if the attribute is not + present. + + .. versionadded:: 0.11 + """ + return self.__dict__.setdefault(name, default) + + def __contains__(self, item: str) -> bool: + return item in self.__dict__ + + def __iter__(self) -> t.Iterator[str]: + return iter(self.__dict__) + + def __repr__(self) -> str: + ctx = _cv_app.get(None) + if ctx is not None: + return f"" + return object.__repr__(self) + + +def after_this_request( + f: ft.AfterRequestCallable[t.Any], +) -> ft.AfterRequestCallable[t.Any]: + """Executes a function after this request. This is useful to modify + response objects. The function is passed the response object and has + to return the same or a new one. + + Example:: + + @app.route('/') + def index(): + @after_this_request + def add_header(response): + response.headers['X-Foo'] = 'Parachute' + return response + return 'Hello World!' + + This is more useful if a function other than the view function wants to + modify a response. For instance think of a decorator that wants to add + some headers without converting the return value into a response object. + + .. versionadded:: 0.9 + """ + ctx = _cv_request.get(None) + + if ctx is None: + raise RuntimeError( + "'after_this_request' can only be used when a request" + " context is active, such as in a view function." + ) + + ctx._after_request_functions.append(f) + return f + + +F = t.TypeVar("F", bound=t.Callable[..., t.Any]) + + +def copy_current_request_context(f: F) -> F: + """A helper function that decorates a function to retain the current + request context. This is useful when working with greenlets. The moment + the function is decorated a copy of the request context is created and + then pushed when the function is called. The current session is also + included in the copied request context. + + Example:: + + import gevent + from flask import copy_current_request_context + + @app.route('/') + def index(): + @copy_current_request_context + def do_some_work(): + # do some work here, it can access flask.request or + # flask.session like you would otherwise in the view function. + ... + gevent.spawn(do_some_work) + return 'Regular response' + + .. versionadded:: 0.10 + """ + ctx = _cv_request.get(None) + + if ctx is None: + raise RuntimeError( + "'copy_current_request_context' can only be used when a" + " request context is active, such as in a view function." + ) + + ctx = ctx.copy() + + def wrapper(*args: t.Any, **kwargs: t.Any) -> t.Any: + with ctx: + return ctx.app.ensure_sync(f)(*args, **kwargs) + + return update_wrapper(wrapper, f) # type: ignore[return-value] + + +def has_request_context() -> bool: + """If you have code that wants to test if a request context is there or + not this function can be used. For instance, you may want to take advantage + of request information if the request object is available, but fail + silently if it is unavailable. + + :: + + class User(db.Model): + + def __init__(self, username, remote_addr=None): + self.username = username + if remote_addr is None and has_request_context(): + remote_addr = request.remote_addr + self.remote_addr = remote_addr + + Alternatively you can also just test any of the context bound objects + (such as :class:`request` or :class:`g`) for truthness:: + + class User(db.Model): + + def __init__(self, username, remote_addr=None): + self.username = username + if remote_addr is None and request: + remote_addr = request.remote_addr + self.remote_addr = remote_addr + + .. versionadded:: 0.7 + """ + return _cv_request.get(None) is not None + + +def has_app_context() -> bool: + """Works like :func:`has_request_context` but for the application + context. You can also just do a boolean check on the + :data:`current_app` object instead. + + .. versionadded:: 0.9 + """ + return _cv_app.get(None) is not None + + +class AppContext: + """The app context contains application-specific information. An app + context is created and pushed at the beginning of each request if + one is not already active. An app context is also pushed when + running CLI commands. + """ + + def __init__(self, app: Flask) -> None: + self.app = app + self.url_adapter = app.create_url_adapter(None) + self.g: _AppCtxGlobals = app.app_ctx_globals_class() + self._cv_tokens: list[contextvars.Token[AppContext]] = [] + + def push(self) -> None: + """Binds the app context to the current context.""" + self._cv_tokens.append(_cv_app.set(self)) + appcontext_pushed.send(self.app, _async_wrapper=self.app.ensure_sync) + + def pop(self, exc: BaseException | None = _sentinel) -> None: # type: ignore + """Pops the app context.""" + try: + if len(self._cv_tokens) == 1: + if exc is _sentinel: + exc = sys.exc_info()[1] + self.app.do_teardown_appcontext(exc) + finally: + ctx = _cv_app.get() + _cv_app.reset(self._cv_tokens.pop()) + + if ctx is not self: + raise AssertionError( + f"Popped wrong app context. ({ctx!r} instead of {self!r})" + ) + + appcontext_popped.send(self.app, _async_wrapper=self.app.ensure_sync) + + def __enter__(self) -> AppContext: + self.push() + return self + + def __exit__( + self, + exc_type: type | None, + exc_value: BaseException | None, + tb: TracebackType | None, + ) -> None: + self.pop(exc_value) + + +class RequestContext: + """The request context contains per-request information. The Flask + app creates and pushes it at the beginning of the request, then pops + it at the end of the request. It will create the URL adapter and + request object for the WSGI environment provided. + + Do not attempt to use this class directly, instead use + :meth:`~flask.Flask.test_request_context` and + :meth:`~flask.Flask.request_context` to create this object. + + When the request context is popped, it will evaluate all the + functions registered on the application for teardown execution + (:meth:`~flask.Flask.teardown_request`). + + The request context is automatically popped at the end of the + request. When using the interactive debugger, the context will be + restored so ``request`` is still accessible. Similarly, the test + client can preserve the context after the request ends. However, + teardown functions may already have closed some resources such as + database connections. + """ + + def __init__( + self, + app: Flask, + environ: WSGIEnvironment, + request: Request | None = None, + session: SessionMixin | None = None, + ) -> None: + self.app = app + if request is None: + request = app.request_class(environ) + request.json_module = app.json + self.request: Request = request + self.url_adapter = None + try: + self.url_adapter = app.create_url_adapter(self.request) + except HTTPException as e: + self.request.routing_exception = e + self.flashes: list[tuple[str, str]] | None = None + self.session: SessionMixin | None = session + # Functions that should be executed after the request on the response + # object. These will be called before the regular "after_request" + # functions. + self._after_request_functions: list[ft.AfterRequestCallable[t.Any]] = [] + + self._cv_tokens: list[ + tuple[contextvars.Token[RequestContext], AppContext | None] + ] = [] + + def copy(self) -> RequestContext: + """Creates a copy of this request context with the same request object. + This can be used to move a request context to a different greenlet. + Because the actual request object is the same this cannot be used to + move a request context to a different thread unless access to the + request object is locked. + + .. versionadded:: 0.10 + + .. versionchanged:: 1.1 + The current session object is used instead of reloading the original + data. This prevents `flask.session` pointing to an out-of-date object. + """ + return self.__class__( + self.app, + environ=self.request.environ, + request=self.request, + session=self.session, + ) + + def match_request(self) -> None: + """Can be overridden by a subclass to hook into the matching + of the request. + """ + try: + result = self.url_adapter.match(return_rule=True) # type: ignore + self.request.url_rule, self.request.view_args = result # type: ignore + except HTTPException as e: + self.request.routing_exception = e + + def push(self) -> None: + # Before we push the request context we have to ensure that there + # is an application context. + app_ctx = _cv_app.get(None) + + if app_ctx is None or app_ctx.app is not self.app: + app_ctx = self.app.app_context() + app_ctx.push() + else: + app_ctx = None + + self._cv_tokens.append((_cv_request.set(self), app_ctx)) + + # Open the session at the moment that the request context is available. + # This allows a custom open_session method to use the request context. + # Only open a new session if this is the first time the request was + # pushed, otherwise stream_with_context loses the session. + if self.session is None: + session_interface = self.app.session_interface + self.session = session_interface.open_session(self.app, self.request) + + if self.session is None: + self.session = session_interface.make_null_session(self.app) + + # Match the request URL after loading the session, so that the + # session is available in custom URL converters. + if self.url_adapter is not None: + self.match_request() + + def pop(self, exc: BaseException | None = _sentinel) -> None: # type: ignore + """Pops the request context and unbinds it by doing that. This will + also trigger the execution of functions registered by the + :meth:`~flask.Flask.teardown_request` decorator. + + .. versionchanged:: 0.9 + Added the `exc` argument. + """ + clear_request = len(self._cv_tokens) == 1 + + try: + if clear_request: + if exc is _sentinel: + exc = sys.exc_info()[1] + self.app.do_teardown_request(exc) + + request_close = getattr(self.request, "close", None) + if request_close is not None: + request_close() + finally: + ctx = _cv_request.get() + token, app_ctx = self._cv_tokens.pop() + _cv_request.reset(token) + + # get rid of circular dependencies at the end of the request + # so that we don't require the GC to be active. + if clear_request: + ctx.request.environ["werkzeug.request"] = None + + if app_ctx is not None: + app_ctx.pop(exc) + + if ctx is not self: + raise AssertionError( + f"Popped wrong request context. ({ctx!r} instead of {self!r})" + ) + + def __enter__(self) -> RequestContext: + self.push() + return self + + def __exit__( + self, + exc_type: type | None, + exc_value: BaseException | None, + tb: TracebackType | None, + ) -> None: + self.pop(exc_value) + + def __repr__(self) -> str: + return ( + f"<{type(self).__name__} {self.request.url!r}" + f" [{self.request.method}] of {self.app.name}>" + ) diff --git a/backend/venv/Lib/site-packages/flask/debughelpers.py b/backend/venv/Lib/site-packages/flask/debughelpers.py new file mode 100644 index 0000000..2c8c4c4 --- /dev/null +++ b/backend/venv/Lib/site-packages/flask/debughelpers.py @@ -0,0 +1,178 @@ +from __future__ import annotations + +import typing as t + +from jinja2.loaders import BaseLoader +from werkzeug.routing import RequestRedirect + +from .blueprints import Blueprint +from .globals import request_ctx +from .sansio.app import App + +if t.TYPE_CHECKING: + from .sansio.scaffold import Scaffold + from .wrappers import Request + + +class UnexpectedUnicodeError(AssertionError, UnicodeError): + """Raised in places where we want some better error reporting for + unexpected unicode or binary data. + """ + + +class DebugFilesKeyError(KeyError, AssertionError): + """Raised from request.files during debugging. The idea is that it can + provide a better error message than just a generic KeyError/BadRequest. + """ + + def __init__(self, request: Request, key: str) -> None: + form_matches = request.form.getlist(key) + buf = [ + f"You tried to access the file {key!r} in the request.files" + " dictionary but it does not exist. The mimetype for the" + f" request is {request.mimetype!r} instead of" + " 'multipart/form-data' which means that no file contents" + " were transmitted. To fix this error you should provide" + ' enctype="multipart/form-data" in your form.' + ] + if form_matches: + names = ", ".join(repr(x) for x in form_matches) + buf.append( + "\n\nThe browser instead transmitted some file names. " + f"This was submitted: {names}" + ) + self.msg = "".join(buf) + + def __str__(self) -> str: + return self.msg + + +class FormDataRoutingRedirect(AssertionError): + """This exception is raised in debug mode if a routing redirect + would cause the browser to drop the method or body. This happens + when method is not GET, HEAD or OPTIONS and the status code is not + 307 or 308. + """ + + def __init__(self, request: Request) -> None: + exc = request.routing_exception + assert isinstance(exc, RequestRedirect) + buf = [ + f"A request was sent to '{request.url}', but routing issued" + f" a redirect to the canonical URL '{exc.new_url}'." + ] + + if f"{request.base_url}/" == exc.new_url.partition("?")[0]: + buf.append( + " The URL was defined with a trailing slash. Flask" + " will redirect to the URL with a trailing slash if it" + " was accessed without one." + ) + + buf.append( + " Send requests to the canonical URL, or use 307 or 308 for" + " routing redirects. Otherwise, browsers will drop form" + " data.\n\n" + "This exception is only raised in debug mode." + ) + super().__init__("".join(buf)) + + +def attach_enctype_error_multidict(request: Request) -> None: + """Patch ``request.files.__getitem__`` to raise a descriptive error + about ``enctype=multipart/form-data``. + + :param request: The request to patch. + :meta private: + """ + oldcls = request.files.__class__ + + class newcls(oldcls): # type: ignore[valid-type, misc] + def __getitem__(self, key: str) -> t.Any: + try: + return super().__getitem__(key) + except KeyError as e: + if key not in request.form: + raise + + raise DebugFilesKeyError(request, key).with_traceback( + e.__traceback__ + ) from None + + newcls.__name__ = oldcls.__name__ + newcls.__module__ = oldcls.__module__ + request.files.__class__ = newcls + + +def _dump_loader_info(loader: BaseLoader) -> t.Iterator[str]: + yield f"class: {type(loader).__module__}.{type(loader).__name__}" + for key, value in sorted(loader.__dict__.items()): + if key.startswith("_"): + continue + if isinstance(value, (tuple, list)): + if not all(isinstance(x, str) for x in value): + continue + yield f"{key}:" + for item in value: + yield f" - {item}" + continue + elif not isinstance(value, (str, int, float, bool)): + continue + yield f"{key}: {value!r}" + + +def explain_template_loading_attempts( + app: App, + template: str, + attempts: list[ + tuple[ + BaseLoader, + Scaffold, + tuple[str, str | None, t.Callable[[], bool] | None] | None, + ] + ], +) -> None: + """This should help developers understand what failed""" + info = [f"Locating template {template!r}:"] + total_found = 0 + blueprint = None + if request_ctx and request_ctx.request.blueprint is not None: + blueprint = request_ctx.request.blueprint + + for idx, (loader, srcobj, triple) in enumerate(attempts): + if isinstance(srcobj, App): + src_info = f"application {srcobj.import_name!r}" + elif isinstance(srcobj, Blueprint): + src_info = f"blueprint {srcobj.name!r} ({srcobj.import_name})" + else: + src_info = repr(srcobj) + + info.append(f"{idx + 1:5}: trying loader of {src_info}") + + for line in _dump_loader_info(loader): + info.append(f" {line}") + + if triple is None: + detail = "no match" + else: + detail = f"found ({triple[1] or ''!r})" + total_found += 1 + info.append(f" -> {detail}") + + seems_fishy = False + if total_found == 0: + info.append("Error: the template could not be found.") + seems_fishy = True + elif total_found > 1: + info.append("Warning: multiple loaders returned a match for the template.") + seems_fishy = True + + if blueprint is not None and seems_fishy: + info.append( + " The template was looked up from an endpoint that belongs" + f" to the blueprint {blueprint!r}." + ) + info.append(" Maybe you did not place a template in the right folder?") + info.append(" See https://flask.palletsprojects.com/blueprints/#templates") + + app.logger.info("\n".join(info)) diff --git a/backend/venv/Lib/site-packages/flask/globals.py b/backend/venv/Lib/site-packages/flask/globals.py new file mode 100644 index 0000000..e2c410c --- /dev/null +++ b/backend/venv/Lib/site-packages/flask/globals.py @@ -0,0 +1,51 @@ +from __future__ import annotations + +import typing as t +from contextvars import ContextVar + +from werkzeug.local import LocalProxy + +if t.TYPE_CHECKING: # pragma: no cover + from .app import Flask + from .ctx import _AppCtxGlobals + from .ctx import AppContext + from .ctx import RequestContext + from .sessions import SessionMixin + from .wrappers import Request + + +_no_app_msg = """\ +Working outside of application context. + +This typically means that you attempted to use functionality that needed +the current application. To solve this, set up an application context +with app.app_context(). See the documentation for more information.\ +""" +_cv_app: ContextVar[AppContext] = ContextVar("flask.app_ctx") +app_ctx: AppContext = LocalProxy( # type: ignore[assignment] + _cv_app, unbound_message=_no_app_msg +) +current_app: Flask = LocalProxy( # type: ignore[assignment] + _cv_app, "app", unbound_message=_no_app_msg +) +g: _AppCtxGlobals = LocalProxy( # type: ignore[assignment] + _cv_app, "g", unbound_message=_no_app_msg +) + +_no_req_msg = """\ +Working outside of request context. + +This typically means that you attempted to use functionality that needed +an active HTTP request. Consult the documentation on testing for +information about how to avoid this problem.\ +""" +_cv_request: ContextVar[RequestContext] = ContextVar("flask.request_ctx") +request_ctx: RequestContext = LocalProxy( # type: ignore[assignment] + _cv_request, unbound_message=_no_req_msg +) +request: Request = LocalProxy( # type: ignore[assignment] + _cv_request, "request", unbound_message=_no_req_msg +) +session: SessionMixin = LocalProxy( # type: ignore[assignment] + _cv_request, "session", unbound_message=_no_req_msg +) diff --git a/backend/venv/Lib/site-packages/flask/helpers.py b/backend/venv/Lib/site-packages/flask/helpers.py new file mode 100644 index 0000000..5d412c9 --- /dev/null +++ b/backend/venv/Lib/site-packages/flask/helpers.py @@ -0,0 +1,641 @@ +from __future__ import annotations + +import importlib.util +import os +import sys +import typing as t +from datetime import datetime +from functools import cache +from functools import update_wrapper + +import werkzeug.utils +from werkzeug.exceptions import abort as _wz_abort +from werkzeug.utils import redirect as _wz_redirect +from werkzeug.wrappers import Response as BaseResponse + +from .globals import _cv_app +from .globals import _cv_request +from .globals import current_app +from .globals import request +from .globals import request_ctx +from .globals import session +from .signals import message_flashed + +if t.TYPE_CHECKING: # pragma: no cover + from .wrappers import Response + + +def get_debug_flag() -> bool: + """Get whether debug mode should be enabled for the app, indicated by the + :envvar:`FLASK_DEBUG` environment variable. The default is ``False``. + """ + val = os.environ.get("FLASK_DEBUG") + return bool(val and val.lower() not in {"0", "false", "no"}) + + +def get_load_dotenv(default: bool = True) -> bool: + """Get whether the user has disabled loading default dotenv files by + setting :envvar:`FLASK_SKIP_DOTENV`. The default is ``True``, load + the files. + + :param default: What to return if the env var isn't set. + """ + val = os.environ.get("FLASK_SKIP_DOTENV") + + if not val: + return default + + return val.lower() in ("0", "false", "no") + + +@t.overload +def stream_with_context( + generator_or_function: t.Iterator[t.AnyStr], +) -> t.Iterator[t.AnyStr]: ... + + +@t.overload +def stream_with_context( + generator_or_function: t.Callable[..., t.Iterator[t.AnyStr]], +) -> t.Callable[[t.Iterator[t.AnyStr]], t.Iterator[t.AnyStr]]: ... + + +def stream_with_context( + generator_or_function: t.Iterator[t.AnyStr] | t.Callable[..., t.Iterator[t.AnyStr]], +) -> t.Iterator[t.AnyStr] | t.Callable[[t.Iterator[t.AnyStr]], t.Iterator[t.AnyStr]]: + """Wrap a response generator function so that it runs inside the current + request context. This keeps :data:`request`, :data:`session`, and :data:`g` + available, even though at the point the generator runs the request context + will typically have ended. + + Use it as a decorator on a generator function: + + .. code-block:: python + + from flask import stream_with_context, request, Response + + @app.get("/stream") + def streamed_response(): + @stream_with_context + def generate(): + yield "Hello " + yield request.args["name"] + yield "!" + + return Response(generate()) + + Or use it as a wrapper around a created generator: + + .. code-block:: python + + from flask import stream_with_context, request, Response + + @app.get("/stream") + def streamed_response(): + def generate(): + yield "Hello " + yield request.args["name"] + yield "!" + + return Response(stream_with_context(generate())) + + .. versionadded:: 0.9 + """ + try: + gen = iter(generator_or_function) # type: ignore[arg-type] + except TypeError: + + def decorator(*args: t.Any, **kwargs: t.Any) -> t.Any: + gen = generator_or_function(*args, **kwargs) # type: ignore[operator] + return stream_with_context(gen) + + return update_wrapper(decorator, generator_or_function) # type: ignore[arg-type] + + def generator() -> t.Iterator[t.AnyStr]: + if (req_ctx := _cv_request.get(None)) is None: + raise RuntimeError( + "'stream_with_context' can only be used when a request" + " context is active, such as in a view function." + ) + + app_ctx = _cv_app.get() + # Setup code below will run the generator to this point, so that the + # current contexts are recorded. The contexts must be pushed after, + # otherwise their ContextVar will record the wrong event loop during + # async view functions. + yield None # type: ignore[misc] + + # Push the app context first, so that the request context does not + # automatically create and push a different app context. + with app_ctx, req_ctx: + try: + yield from gen + finally: + # Clean up in case the user wrapped a WSGI iterator. + if hasattr(gen, "close"): + gen.close() + + # Execute the generator to the sentinel value. This ensures the context is + # preserved in the generator's state. Further iteration will push the + # context and yield from the original iterator. + wrapped_g = generator() + next(wrapped_g) + return wrapped_g + + +def make_response(*args: t.Any) -> Response: + """Sometimes it is necessary to set additional headers in a view. Because + views do not have to return response objects but can return a value that + is converted into a response object by Flask itself, it becomes tricky to + add headers to it. This function can be called instead of using a return + and you will get a response object which you can use to attach headers. + + If view looked like this and you want to add a new header:: + + def index(): + return render_template('index.html', foo=42) + + You can now do something like this:: + + def index(): + response = make_response(render_template('index.html', foo=42)) + response.headers['X-Parachutes'] = 'parachutes are cool' + return response + + This function accepts the very same arguments you can return from a + view function. This for example creates a response with a 404 error + code:: + + response = make_response(render_template('not_found.html'), 404) + + The other use case of this function is to force the return value of a + view function into a response which is helpful with view + decorators:: + + response = make_response(view_function()) + response.headers['X-Parachutes'] = 'parachutes are cool' + + Internally this function does the following things: + + - if no arguments are passed, it creates a new response argument + - if one argument is passed, :meth:`flask.Flask.make_response` + is invoked with it. + - if more than one argument is passed, the arguments are passed + to the :meth:`flask.Flask.make_response` function as tuple. + + .. versionadded:: 0.6 + """ + if not args: + return current_app.response_class() + if len(args) == 1: + args = args[0] + return current_app.make_response(args) + + +def url_for( + endpoint: str, + *, + _anchor: str | None = None, + _method: str | None = None, + _scheme: str | None = None, + _external: bool | None = None, + **values: t.Any, +) -> str: + """Generate a URL to the given endpoint with the given values. + + This requires an active request or application context, and calls + :meth:`current_app.url_for() `. See that method + for full documentation. + + :param endpoint: The endpoint name associated with the URL to + generate. If this starts with a ``.``, the current blueprint + name (if any) will be used. + :param _anchor: If given, append this as ``#anchor`` to the URL. + :param _method: If given, generate the URL associated with this + method for the endpoint. + :param _scheme: If given, the URL will have this scheme if it is + external. + :param _external: If given, prefer the URL to be internal (False) or + require it to be external (True). External URLs include the + scheme and domain. When not in an active request, URLs are + external by default. + :param values: Values to use for the variable parts of the URL rule. + Unknown keys are appended as query string arguments, like + ``?a=b&c=d``. + + .. versionchanged:: 2.2 + Calls ``current_app.url_for``, allowing an app to override the + behavior. + + .. versionchanged:: 0.10 + The ``_scheme`` parameter was added. + + .. versionchanged:: 0.9 + The ``_anchor`` and ``_method`` parameters were added. + + .. versionchanged:: 0.9 + Calls ``app.handle_url_build_error`` on build errors. + """ + return current_app.url_for( + endpoint, + _anchor=_anchor, + _method=_method, + _scheme=_scheme, + _external=_external, + **values, + ) + + +def redirect( + location: str, code: int = 302, Response: type[BaseResponse] | None = None +) -> BaseResponse: + """Create a redirect response object. + + If :data:`~flask.current_app` is available, it will use its + :meth:`~flask.Flask.redirect` method, otherwise it will use + :func:`werkzeug.utils.redirect`. + + :param location: The URL to redirect to. + :param code: The status code for the redirect. + :param Response: The response class to use. Not used when + ``current_app`` is active, which uses ``app.response_class``. + + .. versionadded:: 2.2 + Calls ``current_app.redirect`` if available instead of always + using Werkzeug's default ``redirect``. + """ + if current_app: + return current_app.redirect(location, code=code) + + return _wz_redirect(location, code=code, Response=Response) + + +def abort(code: int | BaseResponse, *args: t.Any, **kwargs: t.Any) -> t.NoReturn: + """Raise an :exc:`~werkzeug.exceptions.HTTPException` for the given + status code. + + If :data:`~flask.current_app` is available, it will call its + :attr:`~flask.Flask.aborter` object, otherwise it will use + :func:`werkzeug.exceptions.abort`. + + :param code: The status code for the exception, which must be + registered in ``app.aborter``. + :param args: Passed to the exception. + :param kwargs: Passed to the exception. + + .. versionadded:: 2.2 + Calls ``current_app.aborter`` if available instead of always + using Werkzeug's default ``abort``. + """ + if current_app: + current_app.aborter(code, *args, **kwargs) + + _wz_abort(code, *args, **kwargs) + + +def get_template_attribute(template_name: str, attribute: str) -> t.Any: + """Loads a macro (or variable) a template exports. This can be used to + invoke a macro from within Python code. If you for example have a + template named :file:`_cider.html` with the following contents: + + .. sourcecode:: html+jinja + + {% macro hello(name) %}Hello {{ name }}!{% endmacro %} + + You can access this from Python code like this:: + + hello = get_template_attribute('_cider.html', 'hello') + return hello('World') + + .. versionadded:: 0.2 + + :param template_name: the name of the template + :param attribute: the name of the variable of macro to access + """ + return getattr(current_app.jinja_env.get_template(template_name).module, attribute) + + +def flash(message: str, category: str = "message") -> None: + """Flashes a message to the next request. In order to remove the + flashed message from the session and to display it to the user, + the template has to call :func:`get_flashed_messages`. + + .. versionchanged:: 0.3 + `category` parameter added. + + :param message: the message to be flashed. + :param category: the category for the message. The following values + are recommended: ``'message'`` for any kind of message, + ``'error'`` for errors, ``'info'`` for information + messages and ``'warning'`` for warnings. However any + kind of string can be used as category. + """ + # Original implementation: + # + # session.setdefault('_flashes', []).append((category, message)) + # + # This assumed that changes made to mutable structures in the session are + # always in sync with the session object, which is not true for session + # implementations that use external storage for keeping their keys/values. + flashes = session.get("_flashes", []) + flashes.append((category, message)) + session["_flashes"] = flashes + app = current_app._get_current_object() # type: ignore + message_flashed.send( + app, + _async_wrapper=app.ensure_sync, + message=message, + category=category, + ) + + +def get_flashed_messages( + with_categories: bool = False, category_filter: t.Iterable[str] = () +) -> list[str] | list[tuple[str, str]]: + """Pulls all flashed messages from the session and returns them. + Further calls in the same request to the function will return + the same messages. By default just the messages are returned, + but when `with_categories` is set to ``True``, the return value will + be a list of tuples in the form ``(category, message)`` instead. + + Filter the flashed messages to one or more categories by providing those + categories in `category_filter`. This allows rendering categories in + separate html blocks. The `with_categories` and `category_filter` + arguments are distinct: + + * `with_categories` controls whether categories are returned with message + text (``True`` gives a tuple, where ``False`` gives just the message text). + * `category_filter` filters the messages down to only those matching the + provided categories. + + See :doc:`/patterns/flashing` for examples. + + .. versionchanged:: 0.3 + `with_categories` parameter added. + + .. versionchanged:: 0.9 + `category_filter` parameter added. + + :param with_categories: set to ``True`` to also receive categories. + :param category_filter: filter of categories to limit return values. Only + categories in the list will be returned. + """ + flashes = request_ctx.flashes + if flashes is None: + flashes = session.pop("_flashes") if "_flashes" in session else [] + request_ctx.flashes = flashes + if category_filter: + flashes = list(filter(lambda f: f[0] in category_filter, flashes)) + if not with_categories: + return [x[1] for x in flashes] + return flashes + + +def _prepare_send_file_kwargs(**kwargs: t.Any) -> dict[str, t.Any]: + if kwargs.get("max_age") is None: + kwargs["max_age"] = current_app.get_send_file_max_age + + kwargs.update( + environ=request.environ, + use_x_sendfile=current_app.config["USE_X_SENDFILE"], + response_class=current_app.response_class, + _root_path=current_app.root_path, + ) + return kwargs + + +def send_file( + path_or_file: os.PathLike[t.AnyStr] | str | t.IO[bytes], + mimetype: str | None = None, + as_attachment: bool = False, + download_name: str | None = None, + conditional: bool = True, + etag: bool | str = True, + last_modified: datetime | int | float | None = None, + max_age: None | (int | t.Callable[[str | None], int | None]) = None, +) -> Response: + """Send the contents of a file to the client. + + The first argument can be a file path or a file-like object. Paths + are preferred in most cases because Werkzeug can manage the file and + get extra information from the path. Passing a file-like object + requires that the file is opened in binary mode, and is mostly + useful when building a file in memory with :class:`io.BytesIO`. + + Never pass file paths provided by a user. The path is assumed to be + trusted, so a user could craft a path to access a file you didn't + intend. Use :func:`send_from_directory` to safely serve + user-requested paths from within a directory. + + If the WSGI server sets a ``file_wrapper`` in ``environ``, it is + used, otherwise Werkzeug's built-in wrapper is used. Alternatively, + if the HTTP server supports ``X-Sendfile``, configuring Flask with + ``USE_X_SENDFILE = True`` will tell the server to send the given + path, which is much more efficient than reading it in Python. + + :param path_or_file: The path to the file to send, relative to the + current working directory if a relative path is given. + Alternatively, a file-like object opened in binary mode. Make + sure the file pointer is seeked to the start of the data. + :param mimetype: The MIME type to send for the file. If not + provided, it will try to detect it from the file name. + :param as_attachment: Indicate to a browser that it should offer to + save the file instead of displaying it. + :param download_name: The default name browsers will use when saving + the file. Defaults to the passed file name. + :param conditional: Enable conditional and range responses based on + request headers. Requires passing a file path and ``environ``. + :param etag: Calculate an ETag for the file, which requires passing + a file path. Can also be a string to use instead. + :param last_modified: The last modified time to send for the file, + in seconds. If not provided, it will try to detect it from the + file path. + :param max_age: How long the client should cache the file, in + seconds. If set, ``Cache-Control`` will be ``public``, otherwise + it will be ``no-cache`` to prefer conditional caching. + + .. versionchanged:: 2.0 + ``download_name`` replaces the ``attachment_filename`` + parameter. If ``as_attachment=False``, it is passed with + ``Content-Disposition: inline`` instead. + + .. versionchanged:: 2.0 + ``max_age`` replaces the ``cache_timeout`` parameter. + ``conditional`` is enabled and ``max_age`` is not set by + default. + + .. versionchanged:: 2.0 + ``etag`` replaces the ``add_etags`` parameter. It can be a + string to use instead of generating one. + + .. versionchanged:: 2.0 + Passing a file-like object that inherits from + :class:`~io.TextIOBase` will raise a :exc:`ValueError` rather + than sending an empty file. + + .. versionadded:: 2.0 + Moved the implementation to Werkzeug. This is now a wrapper to + pass some Flask-specific arguments. + + .. versionchanged:: 1.1 + ``filename`` may be a :class:`~os.PathLike` object. + + .. versionchanged:: 1.1 + Passing a :class:`~io.BytesIO` object supports range requests. + + .. versionchanged:: 1.0.3 + Filenames are encoded with ASCII instead of Latin-1 for broader + compatibility with WSGI servers. + + .. versionchanged:: 1.0 + UTF-8 filenames as specified in :rfc:`2231` are supported. + + .. versionchanged:: 0.12 + The filename is no longer automatically inferred from file + objects. If you want to use automatic MIME and etag support, + pass a filename via ``filename_or_fp`` or + ``attachment_filename``. + + .. versionchanged:: 0.12 + ``attachment_filename`` is preferred over ``filename`` for MIME + detection. + + .. versionchanged:: 0.9 + ``cache_timeout`` defaults to + :meth:`Flask.get_send_file_max_age`. + + .. versionchanged:: 0.7 + MIME guessing and etag support for file-like objects was + removed because it was unreliable. Pass a filename if you are + able to, otherwise attach an etag yourself. + + .. versionchanged:: 0.5 + The ``add_etags``, ``cache_timeout`` and ``conditional`` + parameters were added. The default behavior is to add etags. + + .. versionadded:: 0.2 + """ + return werkzeug.utils.send_file( # type: ignore[return-value] + **_prepare_send_file_kwargs( + path_or_file=path_or_file, + environ=request.environ, + mimetype=mimetype, + as_attachment=as_attachment, + download_name=download_name, + conditional=conditional, + etag=etag, + last_modified=last_modified, + max_age=max_age, + ) + ) + + +def send_from_directory( + directory: os.PathLike[str] | str, + path: os.PathLike[str] | str, + **kwargs: t.Any, +) -> Response: + """Send a file from within a directory using :func:`send_file`. + + .. code-block:: python + + @app.route("/uploads/") + def download_file(name): + return send_from_directory( + app.config['UPLOAD_FOLDER'], name, as_attachment=True + ) + + This is a secure way to serve files from a folder, such as static + files or uploads. Uses :func:`~werkzeug.security.safe_join` to + ensure the path coming from the client is not maliciously crafted to + point outside the specified directory. + + If the final path does not point to an existing regular file, + raises a 404 :exc:`~werkzeug.exceptions.NotFound` error. + + :param directory: The directory that ``path`` must be located under, + relative to the current application's root path. This *must not* + be a value provided by the client, otherwise it becomes insecure. + :param path: The path to the file to send, relative to + ``directory``. + :param kwargs: Arguments to pass to :func:`send_file`. + + .. versionchanged:: 2.0 + ``path`` replaces the ``filename`` parameter. + + .. versionadded:: 2.0 + Moved the implementation to Werkzeug. This is now a wrapper to + pass some Flask-specific arguments. + + .. versionadded:: 0.5 + """ + return werkzeug.utils.send_from_directory( # type: ignore[return-value] + directory, path, **_prepare_send_file_kwargs(**kwargs) + ) + + +def get_root_path(import_name: str) -> str: + """Find the root path of a package, or the path that contains a + module. If it cannot be found, returns the current working + directory. + + Not to be confused with the value returned by :func:`find_package`. + + :meta private: + """ + # Module already imported and has a file attribute. Use that first. + mod = sys.modules.get(import_name) + + if mod is not None and hasattr(mod, "__file__") and mod.__file__ is not None: + return os.path.dirname(os.path.abspath(mod.__file__)) + + # Next attempt: check the loader. + try: + spec = importlib.util.find_spec(import_name) + + if spec is None: + raise ValueError + except (ImportError, ValueError): + loader = None + else: + loader = spec.loader + + # Loader does not exist or we're referring to an unloaded main + # module or a main module without path (interactive sessions), go + # with the current working directory. + if loader is None: + return os.getcwd() + + if hasattr(loader, "get_filename"): + filepath = loader.get_filename(import_name) # pyright: ignore + else: + # Fall back to imports. + __import__(import_name) + mod = sys.modules[import_name] + filepath = getattr(mod, "__file__", None) + + # If we don't have a file path it might be because it is a + # namespace package. In this case pick the root path from the + # first module that is contained in the package. + if filepath is None: + raise RuntimeError( + "No root path can be found for the provided module" + f" {import_name!r}. This can happen because the module" + " came from an import hook that does not provide file" + " name information or because it's a namespace package." + " In this case the root path needs to be explicitly" + " provided." + ) + + # filepath is import_name.py for a module, or __init__.py for a package. + return os.path.dirname(os.path.abspath(filepath)) # type: ignore[no-any-return] + + +@cache +def _split_blueprint_path(name: str) -> list[str]: + out: list[str] = [name] + + if "." in name: + out.extend(_split_blueprint_path(name.rpartition(".")[0])) + + return out diff --git a/backend/venv/Lib/site-packages/flask/json/__init__.py b/backend/venv/Lib/site-packages/flask/json/__init__.py new file mode 100644 index 0000000..c0941d0 --- /dev/null +++ b/backend/venv/Lib/site-packages/flask/json/__init__.py @@ -0,0 +1,170 @@ +from __future__ import annotations + +import json as _json +import typing as t + +from ..globals import current_app +from .provider import _default + +if t.TYPE_CHECKING: # pragma: no cover + from ..wrappers import Response + + +def dumps(obj: t.Any, **kwargs: t.Any) -> str: + """Serialize data as JSON. + + If :data:`~flask.current_app` is available, it will use its + :meth:`app.json.dumps() ` + method, otherwise it will use :func:`json.dumps`. + + :param obj: The data to serialize. + :param kwargs: Arguments passed to the ``dumps`` implementation. + + .. versionchanged:: 2.3 + The ``app`` parameter was removed. + + .. versionchanged:: 2.2 + Calls ``current_app.json.dumps``, allowing an app to override + the behavior. + + .. versionchanged:: 2.0.2 + :class:`decimal.Decimal` is supported by converting to a string. + + .. versionchanged:: 2.0 + ``encoding`` will be removed in Flask 2.1. + + .. versionchanged:: 1.0.3 + ``app`` can be passed directly, rather than requiring an app + context for configuration. + """ + if current_app: + return current_app.json.dumps(obj, **kwargs) + + kwargs.setdefault("default", _default) + return _json.dumps(obj, **kwargs) + + +def dump(obj: t.Any, fp: t.IO[str], **kwargs: t.Any) -> None: + """Serialize data as JSON and write to a file. + + If :data:`~flask.current_app` is available, it will use its + :meth:`app.json.dump() ` + method, otherwise it will use :func:`json.dump`. + + :param obj: The data to serialize. + :param fp: A file opened for writing text. Should use the UTF-8 + encoding to be valid JSON. + :param kwargs: Arguments passed to the ``dump`` implementation. + + .. versionchanged:: 2.3 + The ``app`` parameter was removed. + + .. versionchanged:: 2.2 + Calls ``current_app.json.dump``, allowing an app to override + the behavior. + + .. versionchanged:: 2.0 + Writing to a binary file, and the ``encoding`` argument, will be + removed in Flask 2.1. + """ + if current_app: + current_app.json.dump(obj, fp, **kwargs) + else: + kwargs.setdefault("default", _default) + _json.dump(obj, fp, **kwargs) + + +def loads(s: str | bytes, **kwargs: t.Any) -> t.Any: + """Deserialize data as JSON. + + If :data:`~flask.current_app` is available, it will use its + :meth:`app.json.loads() ` + method, otherwise it will use :func:`json.loads`. + + :param s: Text or UTF-8 bytes. + :param kwargs: Arguments passed to the ``loads`` implementation. + + .. versionchanged:: 2.3 + The ``app`` parameter was removed. + + .. versionchanged:: 2.2 + Calls ``current_app.json.loads``, allowing an app to override + the behavior. + + .. versionchanged:: 2.0 + ``encoding`` will be removed in Flask 2.1. The data must be a + string or UTF-8 bytes. + + .. versionchanged:: 1.0.3 + ``app`` can be passed directly, rather than requiring an app + context for configuration. + """ + if current_app: + return current_app.json.loads(s, **kwargs) + + return _json.loads(s, **kwargs) + + +def load(fp: t.IO[t.AnyStr], **kwargs: t.Any) -> t.Any: + """Deserialize data as JSON read from a file. + + If :data:`~flask.current_app` is available, it will use its + :meth:`app.json.load() ` + method, otherwise it will use :func:`json.load`. + + :param fp: A file opened for reading text or UTF-8 bytes. + :param kwargs: Arguments passed to the ``load`` implementation. + + .. versionchanged:: 2.3 + The ``app`` parameter was removed. + + .. versionchanged:: 2.2 + Calls ``current_app.json.load``, allowing an app to override + the behavior. + + .. versionchanged:: 2.2 + The ``app`` parameter will be removed in Flask 2.3. + + .. versionchanged:: 2.0 + ``encoding`` will be removed in Flask 2.1. The file must be text + mode, or binary mode with UTF-8 bytes. + """ + if current_app: + return current_app.json.load(fp, **kwargs) + + return _json.load(fp, **kwargs) + + +def jsonify(*args: t.Any, **kwargs: t.Any) -> Response: + """Serialize the given arguments as JSON, and return a + :class:`~flask.Response` object with the ``application/json`` + mimetype. A dict or list returned from a view will be converted to a + JSON response automatically without needing to call this. + + This requires an active request or application context, and calls + :meth:`app.json.response() `. + + In debug mode, the output is formatted with indentation to make it + easier to read. This may also be controlled by the provider. + + Either positional or keyword arguments can be given, not both. + If no arguments are given, ``None`` is serialized. + + :param args: A single value to serialize, or multiple values to + treat as a list to serialize. + :param kwargs: Treat as a dict to serialize. + + .. versionchanged:: 2.2 + Calls ``current_app.json.response``, allowing an app to override + the behavior. + + .. versionchanged:: 2.0.2 + :class:`decimal.Decimal` is supported by converting to a string. + + .. versionchanged:: 0.11 + Added support for serializing top-level arrays. This was a + security risk in ancient browsers. See :ref:`security-json`. + + .. versionadded:: 0.2 + """ + return current_app.json.response(*args, **kwargs) # type: ignore[return-value] diff --git a/backend/venv/Lib/site-packages/flask/json/__pycache__/__init__.cpython-312.pyc b/backend/venv/Lib/site-packages/flask/json/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2bf0bc25576e31a928e2d4a6056db470218f7a97 GIT binary patch literal 6702 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 literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/flask/json/__pycache__/provider.cpython-312.pyc b/backend/venv/Lib/site-packages/flask/json/__pycache__/provider.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..97c001a3bc710941ce040ea5a326a86580990dd8 GIT binary patch literal 9269 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 jbz2f%TfGhPgES9bG` to an instance of the class. + + :param app: An application instance. This will be stored as a + :class:`weakref.proxy` on the :attr:`_app` attribute. + + .. versionadded:: 2.2 + """ + + def __init__(self, app: App) -> None: + self._app: App = weakref.proxy(app) + + def dumps(self, obj: t.Any, **kwargs: t.Any) -> str: + """Serialize data as JSON. + + :param obj: The data to serialize. + :param kwargs: May be passed to the underlying JSON library. + """ + raise NotImplementedError + + def dump(self, obj: t.Any, fp: t.IO[str], **kwargs: t.Any) -> None: + """Serialize data as JSON and write to a file. + + :param obj: The data to serialize. + :param fp: A file opened for writing text. Should use the UTF-8 + encoding to be valid JSON. + :param kwargs: May be passed to the underlying JSON library. + """ + fp.write(self.dumps(obj, **kwargs)) + + def loads(self, s: str | bytes, **kwargs: t.Any) -> t.Any: + """Deserialize data as JSON. + + :param s: Text or UTF-8 bytes. + :param kwargs: May be passed to the underlying JSON library. + """ + raise NotImplementedError + + def load(self, fp: t.IO[t.AnyStr], **kwargs: t.Any) -> t.Any: + """Deserialize data as JSON read from a file. + + :param fp: A file opened for reading text or UTF-8 bytes. + :param kwargs: May be passed to the underlying JSON library. + """ + return self.loads(fp.read(), **kwargs) + + def _prepare_response_obj( + self, args: tuple[t.Any, ...], kwargs: dict[str, t.Any] + ) -> t.Any: + if args and kwargs: + raise TypeError("app.json.response() takes either args or kwargs, not both") + + if not args and not kwargs: + return None + + if len(args) == 1: + return args[0] + + return args or kwargs + + def response(self, *args: t.Any, **kwargs: t.Any) -> Response: + """Serialize the given arguments as JSON, and return a + :class:`~flask.Response` object with the ``application/json`` + mimetype. + + The :func:`~flask.json.jsonify` function calls this method for + the current application. + + Either positional or keyword arguments can be given, not both. + If no arguments are given, ``None`` is serialized. + + :param args: A single value to serialize, or multiple values to + treat as a list to serialize. + :param kwargs: Treat as a dict to serialize. + """ + obj = self._prepare_response_obj(args, kwargs) + return self._app.response_class(self.dumps(obj), mimetype="application/json") + + +def _default(o: t.Any) -> t.Any: + if isinstance(o, date): + return http_date(o) + + if isinstance(o, (decimal.Decimal, uuid.UUID)): + return str(o) + + if dataclasses and dataclasses.is_dataclass(o): + return dataclasses.asdict(o) # type: ignore[arg-type] + + if hasattr(o, "__html__"): + return str(o.__html__()) + + raise TypeError(f"Object of type {type(o).__name__} is not JSON serializable") + + +class DefaultJSONProvider(JSONProvider): + """Provide JSON operations using Python's built-in :mod:`json` + library. Serializes the following additional data types: + + - :class:`datetime.datetime` and :class:`datetime.date` are + serialized to :rfc:`822` strings. This is the same as the HTTP + date format. + - :class:`uuid.UUID` is serialized to a string. + - :class:`dataclasses.dataclass` is passed to + :func:`dataclasses.asdict`. + - :class:`~markupsafe.Markup` (or any object with a ``__html__`` + method) will call the ``__html__`` method to get a string. + """ + + default: t.Callable[[t.Any], t.Any] = staticmethod(_default) # type: ignore[assignment] + """Apply this function to any object that :meth:`json.dumps` does + not know how to serialize. It should return a valid JSON type or + raise a ``TypeError``. + """ + + ensure_ascii = True + """Replace non-ASCII characters with escape sequences. This may be + more compatible with some clients, but can be disabled for better + performance and size. + """ + + sort_keys = True + """Sort the keys in any serialized dicts. This may be useful for + some caching situations, but can be disabled for better performance. + When enabled, keys must all be strings, they are not converted + before sorting. + """ + + compact: bool | None = None + """If ``True``, or ``None`` out of debug mode, the :meth:`response` + output will not add indentation, newlines, or spaces. If ``False``, + or ``None`` in debug mode, it will use a non-compact representation. + """ + + mimetype = "application/json" + """The mimetype set in :meth:`response`.""" + + def dumps(self, obj: t.Any, **kwargs: t.Any) -> str: + """Serialize data as JSON to a string. + + Keyword arguments are passed to :func:`json.dumps`. Sets some + parameter defaults from the :attr:`default`, + :attr:`ensure_ascii`, and :attr:`sort_keys` attributes. + + :param obj: The data to serialize. + :param kwargs: Passed to :func:`json.dumps`. + """ + kwargs.setdefault("default", self.default) + kwargs.setdefault("ensure_ascii", self.ensure_ascii) + kwargs.setdefault("sort_keys", self.sort_keys) + return json.dumps(obj, **kwargs) + + def loads(self, s: str | bytes, **kwargs: t.Any) -> t.Any: + """Deserialize data as JSON from a string or bytes. + + :param s: Text or UTF-8 bytes. + :param kwargs: Passed to :func:`json.loads`. + """ + return json.loads(s, **kwargs) + + def response(self, *args: t.Any, **kwargs: t.Any) -> Response: + """Serialize the given arguments as JSON, and return a + :class:`~flask.Response` object with it. The response mimetype + will be "application/json" and can be changed with + :attr:`mimetype`. + + If :attr:`compact` is ``False`` or debug mode is enabled, the + output will be formatted to be easier to read. + + Either positional or keyword arguments can be given, not both. + If no arguments are given, ``None`` is serialized. + + :param args: A single value to serialize, or multiple values to + treat as a list to serialize. + :param kwargs: Treat as a dict to serialize. + """ + obj = self._prepare_response_obj(args, kwargs) + dump_args: dict[str, t.Any] = {} + + if (self.compact is None and self._app.debug) or self.compact is False: + dump_args.setdefault("indent", 2) + else: + dump_args.setdefault("separators", (",", ":")) + + return self._app.response_class( + f"{self.dumps(obj, **dump_args)}\n", mimetype=self.mimetype + ) diff --git a/backend/venv/Lib/site-packages/flask/json/tag.py b/backend/venv/Lib/site-packages/flask/json/tag.py new file mode 100644 index 0000000..8dc3629 --- /dev/null +++ b/backend/venv/Lib/site-packages/flask/json/tag.py @@ -0,0 +1,327 @@ +""" +Tagged JSON +~~~~~~~~~~~ + +A compact representation for lossless serialization of non-standard JSON +types. :class:`~flask.sessions.SecureCookieSessionInterface` uses this +to serialize the session data, but it may be useful in other places. It +can be extended to support other types. + +.. autoclass:: TaggedJSONSerializer + :members: + +.. autoclass:: JSONTag + :members: + +Let's see an example that adds support for +:class:`~collections.OrderedDict`. Dicts don't have an order in JSON, so +to handle this we will dump the items as a list of ``[key, value]`` +pairs. Subclass :class:`JSONTag` and give it the new key ``' od'`` to +identify the type. The session serializer processes dicts first, so +insert the new tag at the front of the order since ``OrderedDict`` must +be processed before ``dict``. + +.. code-block:: python + + from flask.json.tag import JSONTag + + class TagOrderedDict(JSONTag): + __slots__ = ('serializer',) + key = ' od' + + def check(self, value): + return isinstance(value, OrderedDict) + + def to_json(self, value): + return [[k, self.serializer.tag(v)] for k, v in iteritems(value)] + + def to_python(self, value): + return OrderedDict(value) + + app.session_interface.serializer.register(TagOrderedDict, index=0) +""" + +from __future__ import annotations + +import typing as t +from base64 import b64decode +from base64 import b64encode +from datetime import datetime +from uuid import UUID + +from markupsafe import Markup +from werkzeug.http import http_date +from werkzeug.http import parse_date + +from ..json import dumps +from ..json import loads + + +class JSONTag: + """Base class for defining type tags for :class:`TaggedJSONSerializer`.""" + + __slots__ = ("serializer",) + + #: The tag to mark the serialized object with. If empty, this tag is + #: only used as an intermediate step during tagging. + key: str = "" + + def __init__(self, serializer: TaggedJSONSerializer) -> None: + """Create a tagger for the given serializer.""" + self.serializer = serializer + + def check(self, value: t.Any) -> bool: + """Check if the given value should be tagged by this tag.""" + raise NotImplementedError + + def to_json(self, value: t.Any) -> t.Any: + """Convert the Python object to an object that is a valid JSON type. + The tag will be added later.""" + raise NotImplementedError + + def to_python(self, value: t.Any) -> t.Any: + """Convert the JSON representation back to the correct type. The tag + will already be removed.""" + raise NotImplementedError + + def tag(self, value: t.Any) -> dict[str, t.Any]: + """Convert the value to a valid JSON type and add the tag structure + around it.""" + return {self.key: self.to_json(value)} + + +class TagDict(JSONTag): + """Tag for 1-item dicts whose only key matches a registered tag. + + Internally, the dict key is suffixed with `__`, and the suffix is removed + when deserializing. + """ + + __slots__ = () + key = " di" + + def check(self, value: t.Any) -> bool: + return ( + isinstance(value, dict) + and len(value) == 1 + and next(iter(value)) in self.serializer.tags + ) + + def to_json(self, value: t.Any) -> t.Any: + key = next(iter(value)) + return {f"{key}__": self.serializer.tag(value[key])} + + def to_python(self, value: t.Any) -> t.Any: + key = next(iter(value)) + return {key[:-2]: value[key]} + + +class PassDict(JSONTag): + __slots__ = () + + def check(self, value: t.Any) -> bool: + return isinstance(value, dict) + + def to_json(self, value: t.Any) -> t.Any: + # JSON objects may only have string keys, so don't bother tagging the + # key here. + return {k: self.serializer.tag(v) for k, v in value.items()} + + tag = to_json + + +class TagTuple(JSONTag): + __slots__ = () + key = " t" + + def check(self, value: t.Any) -> bool: + return isinstance(value, tuple) + + def to_json(self, value: t.Any) -> t.Any: + return [self.serializer.tag(item) for item in value] + + def to_python(self, value: t.Any) -> t.Any: + return tuple(value) + + +class PassList(JSONTag): + __slots__ = () + + def check(self, value: t.Any) -> bool: + return isinstance(value, list) + + def to_json(self, value: t.Any) -> t.Any: + return [self.serializer.tag(item) for item in value] + + tag = to_json + + +class TagBytes(JSONTag): + __slots__ = () + key = " b" + + def check(self, value: t.Any) -> bool: + return isinstance(value, bytes) + + def to_json(self, value: t.Any) -> t.Any: + return b64encode(value).decode("ascii") + + def to_python(self, value: t.Any) -> t.Any: + return b64decode(value) + + +class TagMarkup(JSONTag): + """Serialize anything matching the :class:`~markupsafe.Markup` API by + having a ``__html__`` method to the result of that method. Always + deserializes to an instance of :class:`~markupsafe.Markup`.""" + + __slots__ = () + key = " m" + + def check(self, value: t.Any) -> bool: + return callable(getattr(value, "__html__", None)) + + def to_json(self, value: t.Any) -> t.Any: + return str(value.__html__()) + + def to_python(self, value: t.Any) -> t.Any: + return Markup(value) + + +class TagUUID(JSONTag): + __slots__ = () + key = " u" + + def check(self, value: t.Any) -> bool: + return isinstance(value, UUID) + + def to_json(self, value: t.Any) -> t.Any: + return value.hex + + def to_python(self, value: t.Any) -> t.Any: + return UUID(value) + + +class TagDateTime(JSONTag): + __slots__ = () + key = " d" + + def check(self, value: t.Any) -> bool: + return isinstance(value, datetime) + + def to_json(self, value: t.Any) -> t.Any: + return http_date(value) + + def to_python(self, value: t.Any) -> t.Any: + return parse_date(value) + + +class TaggedJSONSerializer: + """Serializer that uses a tag system to compactly represent objects that + are not JSON types. Passed as the intermediate serializer to + :class:`itsdangerous.Serializer`. + + The following extra types are supported: + + * :class:`dict` + * :class:`tuple` + * :class:`bytes` + * :class:`~markupsafe.Markup` + * :class:`~uuid.UUID` + * :class:`~datetime.datetime` + """ + + __slots__ = ("tags", "order") + + #: Tag classes to bind when creating the serializer. Other tags can be + #: added later using :meth:`~register`. + default_tags = [ + TagDict, + PassDict, + TagTuple, + PassList, + TagBytes, + TagMarkup, + TagUUID, + TagDateTime, + ] + + def __init__(self) -> None: + self.tags: dict[str, JSONTag] = {} + self.order: list[JSONTag] = [] + + for cls in self.default_tags: + self.register(cls) + + def register( + self, + tag_class: type[JSONTag], + force: bool = False, + index: int | None = None, + ) -> None: + """Register a new tag with this serializer. + + :param tag_class: tag class to register. Will be instantiated with this + serializer instance. + :param force: overwrite an existing tag. If false (default), a + :exc:`KeyError` is raised. + :param index: index to insert the new tag in the tag order. Useful when + the new tag is a special case of an existing tag. If ``None`` + (default), the tag is appended to the end of the order. + + :raise KeyError: if the tag key is already registered and ``force`` is + not true. + """ + tag = tag_class(self) + key = tag.key + + if key: + if not force and key in self.tags: + raise KeyError(f"Tag '{key}' is already registered.") + + self.tags[key] = tag + + if index is None: + self.order.append(tag) + else: + self.order.insert(index, tag) + + def tag(self, value: t.Any) -> t.Any: + """Convert a value to a tagged representation if necessary.""" + for tag in self.order: + if tag.check(value): + return tag.tag(value) + + return value + + def untag(self, value: dict[str, t.Any]) -> t.Any: + """Convert a tagged representation back to the original type.""" + if len(value) != 1: + return value + + key = next(iter(value)) + + if key not in self.tags: + return value + + return self.tags[key].to_python(value[key]) + + def _untag_scan(self, value: t.Any) -> t.Any: + if isinstance(value, dict): + # untag each item recursively + value = {k: self._untag_scan(v) for k, v in value.items()} + # untag the dict itself + value = self.untag(value) + elif isinstance(value, list): + # untag each item recursively + value = [self._untag_scan(item) for item in value] + + return value + + def dumps(self, value: t.Any) -> str: + """Tag the value and dump it to a compact JSON string.""" + return dumps(self.tag(value), separators=(",", ":")) + + def loads(self, value: str) -> t.Any: + """Load data from a JSON string and deserialized any tagged objects.""" + return self._untag_scan(loads(value)) diff --git a/backend/venv/Lib/site-packages/flask/logging.py b/backend/venv/Lib/site-packages/flask/logging.py new file mode 100644 index 0000000..0cb8f43 --- /dev/null +++ b/backend/venv/Lib/site-packages/flask/logging.py @@ -0,0 +1,79 @@ +from __future__ import annotations + +import logging +import sys +import typing as t + +from werkzeug.local import LocalProxy + +from .globals import request + +if t.TYPE_CHECKING: # pragma: no cover + from .sansio.app import App + + +@LocalProxy +def wsgi_errors_stream() -> t.TextIO: + """Find the most appropriate error stream for the application. If a request + is active, log to ``wsgi.errors``, otherwise use ``sys.stderr``. + + If you configure your own :class:`logging.StreamHandler`, you may want to + use this for the stream. If you are using file or dict configuration and + can't import this directly, you can refer to it as + ``ext://flask.logging.wsgi_errors_stream``. + """ + if request: + return request.environ["wsgi.errors"] # type: ignore[no-any-return] + + return sys.stderr + + +def has_level_handler(logger: logging.Logger) -> bool: + """Check if there is a handler in the logging chain that will handle the + given logger's :meth:`effective level <~logging.Logger.getEffectiveLevel>`. + """ + level = logger.getEffectiveLevel() + current = logger + + while current: + if any(handler.level <= level for handler in current.handlers): + return True + + if not current.propagate: + break + + current = current.parent # type: ignore + + return False + + +#: Log messages to :func:`~flask.logging.wsgi_errors_stream` with the format +#: ``[%(asctime)s] %(levelname)s in %(module)s: %(message)s``. +default_handler = logging.StreamHandler(wsgi_errors_stream) # type: ignore +default_handler.setFormatter( + logging.Formatter("[%(asctime)s] %(levelname)s in %(module)s: %(message)s") +) + + +def create_logger(app: App) -> logging.Logger: + """Get the Flask app's logger and configure it if needed. + + The logger name will be the same as + :attr:`app.import_name `. + + When :attr:`~flask.Flask.debug` is enabled, set the logger level to + :data:`logging.DEBUG` if it is not set. + + If there is no handler for the logger's effective level, add a + :class:`~logging.StreamHandler` for + :func:`~flask.logging.wsgi_errors_stream` with a basic format. + """ + logger = logging.getLogger(app.name) + + if app.debug and not logger.level: + logger.setLevel(logging.DEBUG) + + if not has_level_handler(logger): + logger.addHandler(default_handler) + + return logger diff --git a/backend/venv/Lib/site-packages/flask/py.typed b/backend/venv/Lib/site-packages/flask/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/backend/venv/Lib/site-packages/flask/sansio/README.md b/backend/venv/Lib/site-packages/flask/sansio/README.md new file mode 100644 index 0000000..623ac19 --- /dev/null +++ b/backend/venv/Lib/site-packages/flask/sansio/README.md @@ -0,0 +1,6 @@ +# Sansio + +This folder contains code that can be used by alternative Flask +implementations, for example Quart. The code therefore cannot do any +IO, nor be part of a likely IO path. Finally this code cannot use the +Flask globals. diff --git a/backend/venv/Lib/site-packages/flask/sansio/__pycache__/app.cpython-312.pyc b/backend/venv/Lib/site-packages/flask/sansio/__pycache__/app.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b00d03c6825817526645dab3d3f4e8168876853f GIT binary patch literal 33695 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 G^?w2R8bZ(j literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/flask/sansio/__pycache__/blueprints.cpython-312.pyc b/backend/venv/Lib/site-packages/flask/sansio/__pycache__/blueprints.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..366066101c229353844be68a3994b9d9cb14ceca GIT binary patch literal 31193 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 literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/flask/sansio/app.py b/backend/venv/Lib/site-packages/flask/sansio/app.py new file mode 100644 index 0000000..a2592fe --- /dev/null +++ b/backend/venv/Lib/site-packages/flask/sansio/app.py @@ -0,0 +1,964 @@ +from __future__ import annotations + +import logging +import os +import sys +import typing as t +from datetime import timedelta +from itertools import chain + +from werkzeug.exceptions import Aborter +from werkzeug.exceptions import BadRequest +from werkzeug.exceptions import BadRequestKeyError +from werkzeug.routing import BuildError +from werkzeug.routing import Map +from werkzeug.routing import Rule +from werkzeug.sansio.response import Response +from werkzeug.utils import cached_property +from werkzeug.utils import redirect as _wz_redirect + +from .. import typing as ft +from ..config import Config +from ..config import ConfigAttribute +from ..ctx import _AppCtxGlobals +from ..helpers import _split_blueprint_path +from ..helpers import get_debug_flag +from ..json.provider import DefaultJSONProvider +from ..json.provider import JSONProvider +from ..logging import create_logger +from ..templating import DispatchingJinjaLoader +from ..templating import Environment +from .scaffold import _endpoint_from_view_func +from .scaffold import find_package +from .scaffold import Scaffold +from .scaffold import setupmethod + +if t.TYPE_CHECKING: # pragma: no cover + from werkzeug.wrappers import Response as BaseResponse + + from ..testing import FlaskClient + from ..testing import FlaskCliRunner + from .blueprints import Blueprint + +T_shell_context_processor = t.TypeVar( + "T_shell_context_processor", bound=ft.ShellContextProcessorCallable +) +T_teardown = t.TypeVar("T_teardown", bound=ft.TeardownCallable) +T_template_filter = t.TypeVar("T_template_filter", bound=ft.TemplateFilterCallable) +T_template_global = t.TypeVar("T_template_global", bound=ft.TemplateGlobalCallable) +T_template_test = t.TypeVar("T_template_test", bound=ft.TemplateTestCallable) + + +def _make_timedelta(value: timedelta | int | None) -> timedelta | None: + if value is None or isinstance(value, timedelta): + return value + + return timedelta(seconds=value) + + +class App(Scaffold): + """The flask object implements a WSGI application and acts as the central + object. It is passed the name of the module or package of the + application. Once it is created it will act as a central registry for + the view functions, the URL rules, template configuration and much more. + + The name of the package is used to resolve resources from inside the + package or the folder the module is contained in depending on if the + package parameter resolves to an actual python package (a folder with + an :file:`__init__.py` file inside) or a standard module (just a ``.py`` file). + + For more information about resource loading, see :func:`open_resource`. + + Usually you create a :class:`Flask` instance in your main module or + in the :file:`__init__.py` file of your package like this:: + + from flask import Flask + app = Flask(__name__) + + .. admonition:: About the First Parameter + + The idea of the first parameter is to give Flask an idea of what + belongs to your application. This name is used to find resources + on the filesystem, can be used by extensions to improve debugging + information and a lot more. + + So it's important what you provide there. If you are using a single + module, `__name__` is always the correct value. If you however are + using a package, it's usually recommended to hardcode the name of + your package there. + + For example if your application is defined in :file:`yourapplication/app.py` + you should create it with one of the two versions below:: + + app = Flask('yourapplication') + app = Flask(__name__.split('.')[0]) + + Why is that? The application will work even with `__name__`, thanks + to how resources are looked up. However it will make debugging more + painful. Certain extensions can make assumptions based on the + import name of your application. For example the Flask-SQLAlchemy + extension will look for the code in your application that triggered + an SQL query in debug mode. If the import name is not properly set + up, that debugging information is lost. (For example it would only + pick up SQL queries in `yourapplication.app` and not + `yourapplication.views.frontend`) + + .. versionadded:: 0.7 + The `static_url_path`, `static_folder`, and `template_folder` + parameters were added. + + .. versionadded:: 0.8 + The `instance_path` and `instance_relative_config` parameters were + added. + + .. versionadded:: 0.11 + The `root_path` parameter was added. + + .. versionadded:: 1.0 + The ``host_matching`` and ``static_host`` parameters were added. + + .. versionadded:: 1.0 + The ``subdomain_matching`` parameter was added. Subdomain + matching needs to be enabled manually now. Setting + :data:`SERVER_NAME` does not implicitly enable it. + + :param import_name: the name of the application package + :param static_url_path: can be used to specify a different path for the + static files on the web. Defaults to the name + of the `static_folder` folder. + :param static_folder: The folder with static files that is served at + ``static_url_path``. Relative to the application ``root_path`` + or an absolute path. Defaults to ``'static'``. + :param static_host: the host to use when adding the static route. + Defaults to None. Required when using ``host_matching=True`` + with a ``static_folder`` configured. + :param host_matching: set ``url_map.host_matching`` attribute. + Defaults to False. + :param subdomain_matching: consider the subdomain relative to + :data:`SERVER_NAME` when matching routes. Defaults to False. + :param template_folder: the folder that contains the templates that should + be used by the application. Defaults to + ``'templates'`` folder in the root path of the + application. + :param instance_path: An alternative instance path for the application. + By default the folder ``'instance'`` next to the + package or module is assumed to be the instance + path. + :param instance_relative_config: if set to ``True`` relative filenames + for loading the config are assumed to + be relative to the instance path instead + of the application root. + :param root_path: The path to the root of the application files. + This should only be set manually when it can't be detected + automatically, such as for namespace packages. + """ + + #: The class of the object assigned to :attr:`aborter`, created by + #: :meth:`create_aborter`. That object is called by + #: :func:`flask.abort` to raise HTTP errors, and can be + #: called directly as well. + #: + #: Defaults to :class:`werkzeug.exceptions.Aborter`. + #: + #: .. versionadded:: 2.2 + aborter_class = Aborter + + #: The class that is used for the Jinja environment. + #: + #: .. versionadded:: 0.11 + jinja_environment = Environment + + #: The class that is used for the :data:`~flask.g` instance. + #: + #: Example use cases for a custom class: + #: + #: 1. Store arbitrary attributes on flask.g. + #: 2. Add a property for lazy per-request database connectors. + #: 3. Return None instead of AttributeError on unexpected attributes. + #: 4. Raise exception if an unexpected attr is set, a "controlled" flask.g. + #: + #: In Flask 0.9 this property was called `request_globals_class` but it + #: was changed in 0.10 to :attr:`app_ctx_globals_class` because the + #: flask.g object is now application context scoped. + #: + #: .. versionadded:: 0.10 + app_ctx_globals_class = _AppCtxGlobals + + #: The class that is used for the ``config`` attribute of this app. + #: Defaults to :class:`~flask.Config`. + #: + #: Example use cases for a custom class: + #: + #: 1. Default values for certain config options. + #: 2. Access to config values through attributes in addition to keys. + #: + #: .. versionadded:: 0.11 + config_class = Config + + #: The testing flag. Set this to ``True`` to enable the test mode of + #: Flask extensions (and in the future probably also Flask itself). + #: For example this might activate test helpers that have an + #: additional runtime cost which should not be enabled by default. + #: + #: If this is enabled and PROPAGATE_EXCEPTIONS is not changed from the + #: default it's implicitly enabled. + #: + #: This attribute can also be configured from the config with the + #: ``TESTING`` configuration key. Defaults to ``False``. + testing = ConfigAttribute[bool]("TESTING") + + #: If a secret key is set, cryptographic components can use this to + #: sign cookies and other things. Set this to a complex random value + #: when you want to use the secure cookie for instance. + #: + #: This attribute can also be configured from the config with the + #: :data:`SECRET_KEY` configuration key. Defaults to ``None``. + secret_key = ConfigAttribute[t.Union[str, bytes, None]]("SECRET_KEY") + + #: A :class:`~datetime.timedelta` which is used to set the expiration + #: date of a permanent session. The default is 31 days which makes a + #: permanent session survive for roughly one month. + #: + #: This attribute can also be configured from the config with the + #: ``PERMANENT_SESSION_LIFETIME`` configuration key. Defaults to + #: ``timedelta(days=31)`` + permanent_session_lifetime = ConfigAttribute[timedelta]( + "PERMANENT_SESSION_LIFETIME", + get_converter=_make_timedelta, # type: ignore[arg-type] + ) + + json_provider_class: type[JSONProvider] = DefaultJSONProvider + """A subclass of :class:`~flask.json.provider.JSONProvider`. An + instance is created and assigned to :attr:`app.json` when creating + the app. + + The default, :class:`~flask.json.provider.DefaultJSONProvider`, uses + Python's built-in :mod:`json` library. A different provider can use + a different JSON library. + + .. versionadded:: 2.2 + """ + + #: Options that are passed to the Jinja environment in + #: :meth:`create_jinja_environment`. Changing these options after + #: the environment is created (accessing :attr:`jinja_env`) will + #: have no effect. + #: + #: .. versionchanged:: 1.1.0 + #: This is a ``dict`` instead of an ``ImmutableDict`` to allow + #: easier configuration. + #: + jinja_options: dict[str, t.Any] = {} + + #: The rule object to use for URL rules created. This is used by + #: :meth:`add_url_rule`. Defaults to :class:`werkzeug.routing.Rule`. + #: + #: .. versionadded:: 0.7 + url_rule_class = Rule + + #: The map object to use for storing the URL rules and routing + #: configuration parameters. Defaults to :class:`werkzeug.routing.Map`. + #: + #: .. versionadded:: 1.1.0 + url_map_class = Map + + #: The :meth:`test_client` method creates an instance of this test + #: client class. Defaults to :class:`~flask.testing.FlaskClient`. + #: + #: .. versionadded:: 0.7 + test_client_class: type[FlaskClient] | None = None + + #: The :class:`~click.testing.CliRunner` subclass, by default + #: :class:`~flask.testing.FlaskCliRunner` that is used by + #: :meth:`test_cli_runner`. Its ``__init__`` method should take a + #: Flask app object as the first argument. + #: + #: .. versionadded:: 1.0 + test_cli_runner_class: type[FlaskCliRunner] | None = None + + default_config: dict[str, t.Any] + response_class: type[Response] + + def __init__( + self, + import_name: str, + static_url_path: str | None = None, + static_folder: str | os.PathLike[str] | None = "static", + static_host: str | None = None, + host_matching: bool = False, + subdomain_matching: bool = False, + template_folder: str | os.PathLike[str] | None = "templates", + instance_path: str | None = None, + instance_relative_config: bool = False, + root_path: str | None = None, + ) -> None: + super().__init__( + import_name=import_name, + static_folder=static_folder, + static_url_path=static_url_path, + template_folder=template_folder, + root_path=root_path, + ) + + if instance_path is None: + instance_path = self.auto_find_instance_path() + elif not os.path.isabs(instance_path): + raise ValueError( + "If an instance path is provided it must be absolute." + " A relative path was given instead." + ) + + #: Holds the path to the instance folder. + #: + #: .. versionadded:: 0.8 + self.instance_path = instance_path + + #: The configuration dictionary as :class:`Config`. This behaves + #: exactly like a regular dictionary but supports additional methods + #: to load a config from files. + self.config = self.make_config(instance_relative_config) + + #: An instance of :attr:`aborter_class` created by + #: :meth:`make_aborter`. This is called by :func:`flask.abort` + #: to raise HTTP errors, and can be called directly as well. + #: + #: .. versionadded:: 2.2 + #: Moved from ``flask.abort``, which calls this object. + self.aborter = self.make_aborter() + + self.json: JSONProvider = self.json_provider_class(self) + """Provides access to JSON methods. Functions in ``flask.json`` + will call methods on this provider when the application context + is active. Used for handling JSON requests and responses. + + An instance of :attr:`json_provider_class`. Can be customized by + changing that attribute on a subclass, or by assigning to this + attribute afterwards. + + The default, :class:`~flask.json.provider.DefaultJSONProvider`, + uses Python's built-in :mod:`json` library. A different provider + can use a different JSON library. + + .. versionadded:: 2.2 + """ + + #: A list of functions that are called by + #: :meth:`handle_url_build_error` when :meth:`.url_for` raises a + #: :exc:`~werkzeug.routing.BuildError`. Each function is called + #: with ``error``, ``endpoint`` and ``values``. If a function + #: returns ``None`` or raises a ``BuildError``, it is skipped. + #: Otherwise, its return value is returned by ``url_for``. + #: + #: .. versionadded:: 0.9 + self.url_build_error_handlers: list[ + t.Callable[[Exception, str, dict[str, t.Any]], str] + ] = [] + + #: A list of functions that are called when the application context + #: is destroyed. Since the application context is also torn down + #: if the request ends this is the place to store code that disconnects + #: from databases. + #: + #: .. versionadded:: 0.9 + self.teardown_appcontext_funcs: list[ft.TeardownCallable] = [] + + #: A list of shell context processor functions that should be run + #: when a shell context is created. + #: + #: .. versionadded:: 0.11 + self.shell_context_processors: list[ft.ShellContextProcessorCallable] = [] + + #: Maps registered blueprint names to blueprint objects. The + #: dict retains the order the blueprints were registered in. + #: Blueprints can be registered multiple times, this dict does + #: not track how often they were attached. + #: + #: .. versionadded:: 0.7 + self.blueprints: dict[str, Blueprint] = {} + + #: a place where extensions can store application specific state. For + #: example this is where an extension could store database engines and + #: similar things. + #: + #: The key must match the name of the extension module. For example in + #: case of a "Flask-Foo" extension in `flask_foo`, the key would be + #: ``'foo'``. + #: + #: .. versionadded:: 0.7 + self.extensions: dict[str, t.Any] = {} + + #: The :class:`~werkzeug.routing.Map` for this instance. You can use + #: this to change the routing converters after the class was created + #: but before any routes are connected. Example:: + #: + #: from werkzeug.routing import BaseConverter + #: + #: class ListConverter(BaseConverter): + #: def to_python(self, value): + #: return value.split(',') + #: def to_url(self, values): + #: return ','.join(super(ListConverter, self).to_url(value) + #: for value in values) + #: + #: app = Flask(__name__) + #: app.url_map.converters['list'] = ListConverter + self.url_map = self.url_map_class(host_matching=host_matching) + + self.subdomain_matching = subdomain_matching + + # tracks internally if the application already handled at least one + # request. + self._got_first_request = False + + def _check_setup_finished(self, f_name: str) -> None: + if self._got_first_request: + raise AssertionError( + f"The setup method '{f_name}' can no longer be called" + " on the application. It has already handled its first" + " request, any changes will not be applied" + " consistently.\n" + "Make sure all imports, decorators, functions, etc." + " needed to set up the application are done before" + " running it." + ) + + @cached_property + def name(self) -> str: + """The name of the application. This is usually the import name + with the difference that it's guessed from the run file if the + import name is main. This name is used as a display name when + Flask needs the name of the application. It can be set and overridden + to change the value. + + .. versionadded:: 0.8 + """ + if self.import_name == "__main__": + fn: str | None = getattr(sys.modules["__main__"], "__file__", None) + if fn is None: + return "__main__" + return os.path.splitext(os.path.basename(fn))[0] + return self.import_name + + @cached_property + def logger(self) -> logging.Logger: + """A standard Python :class:`~logging.Logger` for the app, with + the same name as :attr:`name`. + + In debug mode, the logger's :attr:`~logging.Logger.level` will + be set to :data:`~logging.DEBUG`. + + If there are no handlers configured, a default handler will be + added. See :doc:`/logging` for more information. + + .. versionchanged:: 1.1.0 + The logger takes the same name as :attr:`name` rather than + hard-coding ``"flask.app"``. + + .. versionchanged:: 1.0.0 + Behavior was simplified. The logger is always named + ``"flask.app"``. The level is only set during configuration, + it doesn't check ``app.debug`` each time. Only one format is + used, not different ones depending on ``app.debug``. No + handlers are removed, and a handler is only added if no + handlers are already configured. + + .. versionadded:: 0.3 + """ + return create_logger(self) + + @cached_property + def jinja_env(self) -> Environment: + """The Jinja environment used to load templates. + + The environment is created the first time this property is + accessed. Changing :attr:`jinja_options` after that will have no + effect. + """ + return self.create_jinja_environment() + + def create_jinja_environment(self) -> Environment: + raise NotImplementedError() + + def make_config(self, instance_relative: bool = False) -> Config: + """Used to create the config attribute by the Flask constructor. + The `instance_relative` parameter is passed in from the constructor + of Flask (there named `instance_relative_config`) and indicates if + the config should be relative to the instance path or the root path + of the application. + + .. versionadded:: 0.8 + """ + root_path = self.root_path + if instance_relative: + root_path = self.instance_path + defaults = dict(self.default_config) + defaults["DEBUG"] = get_debug_flag() + return self.config_class(root_path, defaults) + + def make_aborter(self) -> Aborter: + """Create the object to assign to :attr:`aborter`. That object + is called by :func:`flask.abort` to raise HTTP errors, and can + be called directly as well. + + By default, this creates an instance of :attr:`aborter_class`, + which defaults to :class:`werkzeug.exceptions.Aborter`. + + .. versionadded:: 2.2 + """ + return self.aborter_class() + + def auto_find_instance_path(self) -> str: + """Tries to locate the instance path if it was not provided to the + constructor of the application class. It will basically calculate + the path to a folder named ``instance`` next to your main file or + the package. + + .. versionadded:: 0.8 + """ + prefix, package_path = find_package(self.import_name) + if prefix is None: + return os.path.join(package_path, "instance") + return os.path.join(prefix, "var", f"{self.name}-instance") + + def create_global_jinja_loader(self) -> DispatchingJinjaLoader: + """Creates the loader for the Jinja environment. Can be used to + override just the loader and keeping the rest unchanged. It's + discouraged to override this function. Instead one should override + the :meth:`jinja_loader` function instead. + + The global loader dispatches between the loaders of the application + and the individual blueprints. + + .. versionadded:: 0.7 + """ + return DispatchingJinjaLoader(self) + + def select_jinja_autoescape(self, filename: str) -> bool: + """Returns ``True`` if autoescaping should be active for the given + template name. If no template name is given, returns `True`. + + .. versionchanged:: 2.2 + Autoescaping is now enabled by default for ``.svg`` files. + + .. versionadded:: 0.5 + """ + if filename is None: + return True + return filename.endswith((".html", ".htm", ".xml", ".xhtml", ".svg")) + + @property + def debug(self) -> bool: + """Whether debug mode is enabled. When using ``flask run`` to start the + development server, an interactive debugger will be shown for unhandled + exceptions, and the server will be reloaded when code changes. This maps to the + :data:`DEBUG` config key. It may not behave as expected if set late. + + **Do not enable debug mode when deploying in production.** + + Default: ``False`` + """ + return self.config["DEBUG"] # type: ignore[no-any-return] + + @debug.setter + def debug(self, value: bool) -> None: + self.config["DEBUG"] = value + + if self.config["TEMPLATES_AUTO_RELOAD"] is None: + self.jinja_env.auto_reload = value + + @setupmethod + def register_blueprint(self, blueprint: Blueprint, **options: t.Any) -> None: + """Register a :class:`~flask.Blueprint` on the application. Keyword + arguments passed to this method will override the defaults set on the + blueprint. + + Calls the blueprint's :meth:`~flask.Blueprint.register` method after + recording the blueprint in the application's :attr:`blueprints`. + + :param blueprint: The blueprint to register. + :param url_prefix: Blueprint routes will be prefixed with this. + :param subdomain: Blueprint routes will match on this subdomain. + :param url_defaults: Blueprint routes will use these default values for + view arguments. + :param options: Additional keyword arguments are passed to + :class:`~flask.blueprints.BlueprintSetupState`. They can be + accessed in :meth:`~flask.Blueprint.record` callbacks. + + .. versionchanged:: 2.0.1 + The ``name`` option can be used to change the (pre-dotted) + name the blueprint is registered with. This allows the same + blueprint to be registered multiple times with unique names + for ``url_for``. + + .. versionadded:: 0.7 + """ + blueprint.register(self, options) + + def iter_blueprints(self) -> t.ValuesView[Blueprint]: + """Iterates over all blueprints by the order they were registered. + + .. versionadded:: 0.11 + """ + return self.blueprints.values() + + @setupmethod + def add_url_rule( + self, + rule: str, + endpoint: str | None = None, + view_func: ft.RouteCallable | None = None, + provide_automatic_options: bool | None = None, + **options: t.Any, + ) -> None: + if endpoint is None: + endpoint = _endpoint_from_view_func(view_func) # type: ignore + options["endpoint"] = endpoint + methods = options.pop("methods", None) + + # if the methods are not given and the view_func object knows its + # methods we can use that instead. If neither exists, we go with + # a tuple of only ``GET`` as default. + if methods is None: + methods = getattr(view_func, "methods", None) or ("GET",) + if isinstance(methods, str): + raise TypeError( + "Allowed methods must be a list of strings, for" + ' example: @app.route(..., methods=["POST"])' + ) + methods = {item.upper() for item in methods} + + # Methods that should always be added + required_methods: set[str] = set(getattr(view_func, "required_methods", ())) + + # starting with Flask 0.8 the view_func object can disable and + # force-enable the automatic options handling. + if provide_automatic_options is None: + provide_automatic_options = getattr( + view_func, "provide_automatic_options", None + ) + + if provide_automatic_options is None: + if "OPTIONS" not in methods and self.config["PROVIDE_AUTOMATIC_OPTIONS"]: + provide_automatic_options = True + required_methods.add("OPTIONS") + else: + provide_automatic_options = False + + # Add the required methods now. + methods |= required_methods + + rule_obj = self.url_rule_class(rule, methods=methods, **options) + rule_obj.provide_automatic_options = provide_automatic_options # type: ignore[attr-defined] + + self.url_map.add(rule_obj) + if view_func is not None: + old_func = self.view_functions.get(endpoint) + if old_func is not None and old_func != view_func: + raise AssertionError( + "View function mapping is overwriting an existing" + f" endpoint function: {endpoint}" + ) + self.view_functions[endpoint] = view_func + + @setupmethod + def template_filter( + self, name: str | None = None + ) -> t.Callable[[T_template_filter], T_template_filter]: + """A decorator that is used to register custom template filter. + You can specify a name for the filter, otherwise the function + name will be used. Example:: + + @app.template_filter() + def reverse(s): + return s[::-1] + + :param name: the optional name of the filter, otherwise the + function name will be used. + """ + + def decorator(f: T_template_filter) -> T_template_filter: + self.add_template_filter(f, name=name) + return f + + return decorator + + @setupmethod + def add_template_filter( + self, f: ft.TemplateFilterCallable, name: str | None = None + ) -> None: + """Register a custom template filter. Works exactly like the + :meth:`template_filter` decorator. + + :param name: the optional name of the filter, otherwise the + function name will be used. + """ + self.jinja_env.filters[name or f.__name__] = f + + @setupmethod + def template_test( + self, name: str | None = None + ) -> t.Callable[[T_template_test], T_template_test]: + """A decorator that is used to register custom template test. + You can specify a name for the test, otherwise the function + name will be used. Example:: + + @app.template_test() + def is_prime(n): + if n == 2: + return True + for i in range(2, int(math.ceil(math.sqrt(n))) + 1): + if n % i == 0: + return False + return True + + .. versionadded:: 0.10 + + :param name: the optional name of the test, otherwise the + function name will be used. + """ + + def decorator(f: T_template_test) -> T_template_test: + self.add_template_test(f, name=name) + return f + + return decorator + + @setupmethod + def add_template_test( + self, f: ft.TemplateTestCallable, name: str | None = None + ) -> None: + """Register a custom template test. Works exactly like the + :meth:`template_test` decorator. + + .. versionadded:: 0.10 + + :param name: the optional name of the test, otherwise the + function name will be used. + """ + self.jinja_env.tests[name or f.__name__] = f + + @setupmethod + def template_global( + self, name: str | None = None + ) -> t.Callable[[T_template_global], T_template_global]: + """A decorator that is used to register a custom template global function. + You can specify a name for the global function, otherwise the function + name will be used. Example:: + + @app.template_global() + def double(n): + return 2 * n + + .. versionadded:: 0.10 + + :param name: the optional name of the global function, otherwise the + function name will be used. + """ + + def decorator(f: T_template_global) -> T_template_global: + self.add_template_global(f, name=name) + return f + + return decorator + + @setupmethod + def add_template_global( + self, f: ft.TemplateGlobalCallable, name: str | None = None + ) -> None: + """Register a custom template global function. Works exactly like the + :meth:`template_global` decorator. + + .. versionadded:: 0.10 + + :param name: the optional name of the global function, otherwise the + function name will be used. + """ + self.jinja_env.globals[name or f.__name__] = f + + @setupmethod + def teardown_appcontext(self, f: T_teardown) -> T_teardown: + """Registers a function to be called when the application + context is popped. The application context is typically popped + after the request context for each request, at the end of CLI + commands, or after a manually pushed context ends. + + .. code-block:: python + + with app.app_context(): + ... + + When the ``with`` block exits (or ``ctx.pop()`` is called), the + teardown functions are called just before the app context is + made inactive. Since a request context typically also manages an + application context it would also be called when you pop a + request context. + + When a teardown function was called because of an unhandled + exception it will be passed an error object. If an + :meth:`errorhandler` is registered, it will handle the exception + and the teardown will not receive it. + + Teardown functions must avoid raising exceptions. If they + execute code that might fail they must surround that code with a + ``try``/``except`` block and log any errors. + + The return values of teardown functions are ignored. + + .. versionadded:: 0.9 + """ + self.teardown_appcontext_funcs.append(f) + return f + + @setupmethod + def shell_context_processor( + self, f: T_shell_context_processor + ) -> T_shell_context_processor: + """Registers a shell context processor function. + + .. versionadded:: 0.11 + """ + self.shell_context_processors.append(f) + return f + + def _find_error_handler( + self, e: Exception, blueprints: list[str] + ) -> ft.ErrorHandlerCallable | None: + """Return a registered error handler for an exception in this order: + blueprint handler for a specific code, app handler for a specific code, + blueprint handler for an exception class, app handler for an exception + class, or ``None`` if a suitable handler is not found. + """ + exc_class, code = self._get_exc_class_and_code(type(e)) + names = (*blueprints, None) + + for c in (code, None) if code is not None else (None,): + for name in names: + handler_map = self.error_handler_spec[name][c] + + if not handler_map: + continue + + for cls in exc_class.__mro__: + handler = handler_map.get(cls) + + if handler is not None: + return handler + return None + + def trap_http_exception(self, e: Exception) -> bool: + """Checks if an HTTP exception should be trapped or not. By default + this will return ``False`` for all exceptions except for a bad request + key error if ``TRAP_BAD_REQUEST_ERRORS`` is set to ``True``. It + also returns ``True`` if ``TRAP_HTTP_EXCEPTIONS`` is set to ``True``. + + This is called for all HTTP exceptions raised by a view function. + If it returns ``True`` for any exception the error handler for this + exception is not called and it shows up as regular exception in the + traceback. This is helpful for debugging implicitly raised HTTP + exceptions. + + .. versionchanged:: 1.0 + Bad request errors are not trapped by default in debug mode. + + .. versionadded:: 0.8 + """ + if self.config["TRAP_HTTP_EXCEPTIONS"]: + return True + + trap_bad_request = self.config["TRAP_BAD_REQUEST_ERRORS"] + + # if unset, trap key errors in debug mode + if ( + trap_bad_request is None + and self.debug + and isinstance(e, BadRequestKeyError) + ): + return True + + if trap_bad_request: + return isinstance(e, BadRequest) + + return False + + def should_ignore_error(self, error: BaseException | None) -> bool: + """This is called to figure out if an error should be ignored + or not as far as the teardown system is concerned. If this + function returns ``True`` then the teardown handlers will not be + passed the error. + + .. versionadded:: 0.10 + """ + return False + + def redirect(self, location: str, code: int = 302) -> BaseResponse: + """Create a redirect response object. + + This is called by :func:`flask.redirect`, and can be called + directly as well. + + :param location: The URL to redirect to. + :param code: The status code for the redirect. + + .. versionadded:: 2.2 + Moved from ``flask.redirect``, which calls this method. + """ + return _wz_redirect( + location, + code=code, + Response=self.response_class, # type: ignore[arg-type] + ) + + def inject_url_defaults(self, endpoint: str, values: dict[str, t.Any]) -> None: + """Injects the URL defaults for the given endpoint directly into + the values dictionary passed. This is used internally and + automatically called on URL building. + + .. versionadded:: 0.7 + """ + names: t.Iterable[str | None] = (None,) + + # url_for may be called outside a request context, parse the + # passed endpoint instead of using request.blueprints. + if "." in endpoint: + names = chain( + names, reversed(_split_blueprint_path(endpoint.rpartition(".")[0])) + ) + + for name in names: + if name in self.url_default_functions: + for func in self.url_default_functions[name]: + func(endpoint, values) + + def handle_url_build_error( + self, error: BuildError, endpoint: str, values: dict[str, t.Any] + ) -> str: + """Called by :meth:`.url_for` if a + :exc:`~werkzeug.routing.BuildError` was raised. If this returns + a value, it will be returned by ``url_for``, otherwise the error + will be re-raised. + + Each function in :attr:`url_build_error_handlers` is called with + ``error``, ``endpoint`` and ``values``. If a function returns + ``None`` or raises a ``BuildError``, it is skipped. Otherwise, + its return value is returned by ``url_for``. + + :param error: The active ``BuildError`` being handled. + :param endpoint: The endpoint being built. + :param values: The keyword arguments passed to ``url_for``. + """ + for handler in self.url_build_error_handlers: + try: + rv = handler(error, endpoint, values) + except BuildError as e: + # make error available outside except block + error = e + else: + if rv is not None: + return rv + + # Re-raise if called with an active exception, otherwise raise + # the passed in exception. + if error is sys.exc_info()[1]: + raise + + raise error diff --git a/backend/venv/Lib/site-packages/flask/sansio/blueprints.py b/backend/venv/Lib/site-packages/flask/sansio/blueprints.py new file mode 100644 index 0000000..4f912cc --- /dev/null +++ b/backend/venv/Lib/site-packages/flask/sansio/blueprints.py @@ -0,0 +1,632 @@ +from __future__ import annotations + +import os +import typing as t +from collections import defaultdict +from functools import update_wrapper + +from .. import typing as ft +from .scaffold import _endpoint_from_view_func +from .scaffold import _sentinel +from .scaffold import Scaffold +from .scaffold import setupmethod + +if t.TYPE_CHECKING: # pragma: no cover + from .app import App + +DeferredSetupFunction = t.Callable[["BlueprintSetupState"], None] +T_after_request = t.TypeVar("T_after_request", bound=ft.AfterRequestCallable[t.Any]) +T_before_request = t.TypeVar("T_before_request", bound=ft.BeforeRequestCallable) +T_error_handler = t.TypeVar("T_error_handler", bound=ft.ErrorHandlerCallable) +T_teardown = t.TypeVar("T_teardown", bound=ft.TeardownCallable) +T_template_context_processor = t.TypeVar( + "T_template_context_processor", bound=ft.TemplateContextProcessorCallable +) +T_template_filter = t.TypeVar("T_template_filter", bound=ft.TemplateFilterCallable) +T_template_global = t.TypeVar("T_template_global", bound=ft.TemplateGlobalCallable) +T_template_test = t.TypeVar("T_template_test", bound=ft.TemplateTestCallable) +T_url_defaults = t.TypeVar("T_url_defaults", bound=ft.URLDefaultCallable) +T_url_value_preprocessor = t.TypeVar( + "T_url_value_preprocessor", bound=ft.URLValuePreprocessorCallable +) + + +class BlueprintSetupState: + """Temporary holder object for registering a blueprint with the + application. An instance of this class is created by the + :meth:`~flask.Blueprint.make_setup_state` method and later passed + to all register callback functions. + """ + + def __init__( + self, + blueprint: Blueprint, + app: App, + options: t.Any, + first_registration: bool, + ) -> None: + #: a reference to the current application + self.app = app + + #: a reference to the blueprint that created this setup state. + self.blueprint = blueprint + + #: a dictionary with all options that were passed to the + #: :meth:`~flask.Flask.register_blueprint` method. + self.options = options + + #: as blueprints can be registered multiple times with the + #: application and not everything wants to be registered + #: multiple times on it, this attribute can be used to figure + #: out if the blueprint was registered in the past already. + self.first_registration = first_registration + + subdomain = self.options.get("subdomain") + if subdomain is None: + subdomain = self.blueprint.subdomain + + #: The subdomain that the blueprint should be active for, ``None`` + #: otherwise. + self.subdomain = subdomain + + url_prefix = self.options.get("url_prefix") + if url_prefix is None: + url_prefix = self.blueprint.url_prefix + #: The prefix that should be used for all URLs defined on the + #: blueprint. + self.url_prefix = url_prefix + + self.name = self.options.get("name", blueprint.name) + self.name_prefix = self.options.get("name_prefix", "") + + #: A dictionary with URL defaults that is added to each and every + #: URL that was defined with the blueprint. + self.url_defaults = dict(self.blueprint.url_values_defaults) + self.url_defaults.update(self.options.get("url_defaults", ())) + + def add_url_rule( + self, + rule: str, + endpoint: str | None = None, + view_func: ft.RouteCallable | None = None, + **options: t.Any, + ) -> None: + """A helper method to register a rule (and optionally a view function) + to the application. The endpoint is automatically prefixed with the + blueprint's name. + """ + if self.url_prefix is not None: + if rule: + rule = "/".join((self.url_prefix.rstrip("/"), rule.lstrip("/"))) + else: + rule = self.url_prefix + options.setdefault("subdomain", self.subdomain) + if endpoint is None: + endpoint = _endpoint_from_view_func(view_func) # type: ignore + defaults = self.url_defaults + if "defaults" in options: + defaults = dict(defaults, **options.pop("defaults")) + + self.app.add_url_rule( + rule, + f"{self.name_prefix}.{self.name}.{endpoint}".lstrip("."), + view_func, + defaults=defaults, + **options, + ) + + +class Blueprint(Scaffold): + """Represents a blueprint, a collection of routes and other + app-related functions that can be registered on a real application + later. + + A blueprint is an object that allows defining application functions + without requiring an application object ahead of time. It uses the + same decorators as :class:`~flask.Flask`, but defers the need for an + application by recording them for later registration. + + Decorating a function with a blueprint creates a deferred function + that is called with :class:`~flask.blueprints.BlueprintSetupState` + when the blueprint is registered on an application. + + See :doc:`/blueprints` for more information. + + :param name: The name of the blueprint. Will be prepended to each + endpoint name. + :param import_name: The name of the blueprint package, usually + ``__name__``. This helps locate the ``root_path`` for the + blueprint. + :param static_folder: A folder with static files that should be + served by the blueprint's static route. The path is relative to + the blueprint's root path. Blueprint static files are disabled + by default. + :param static_url_path: The url to serve static files from. + Defaults to ``static_folder``. If the blueprint does not have + a ``url_prefix``, the app's static route will take precedence, + and the blueprint's static files won't be accessible. + :param template_folder: A folder with templates that should be added + to the app's template search path. The path is relative to the + blueprint's root path. Blueprint templates are disabled by + default. Blueprint templates have a lower precedence than those + in the app's templates folder. + :param url_prefix: A path to prepend to all of the blueprint's URLs, + to make them distinct from the rest of the app's routes. + :param subdomain: A subdomain that blueprint routes will match on by + default. + :param url_defaults: A dict of default values that blueprint routes + will receive by default. + :param root_path: By default, the blueprint will automatically set + this based on ``import_name``. In certain situations this + automatic detection can fail, so the path can be specified + manually instead. + + .. versionchanged:: 1.1.0 + Blueprints have a ``cli`` group to register nested CLI commands. + The ``cli_group`` parameter controls the name of the group under + the ``flask`` command. + + .. versionadded:: 0.7 + """ + + _got_registered_once = False + + def __init__( + self, + name: str, + import_name: str, + static_folder: str | os.PathLike[str] | None = None, + static_url_path: str | None = None, + template_folder: str | os.PathLike[str] | None = None, + url_prefix: str | None = None, + subdomain: str | None = None, + url_defaults: dict[str, t.Any] | None = None, + root_path: str | None = None, + cli_group: str | None = _sentinel, # type: ignore[assignment] + ): + super().__init__( + import_name=import_name, + static_folder=static_folder, + static_url_path=static_url_path, + template_folder=template_folder, + root_path=root_path, + ) + + if not name: + raise ValueError("'name' may not be empty.") + + if "." in name: + raise ValueError("'name' may not contain a dot '.' character.") + + self.name = name + self.url_prefix = url_prefix + self.subdomain = subdomain + self.deferred_functions: list[DeferredSetupFunction] = [] + + if url_defaults is None: + url_defaults = {} + + self.url_values_defaults = url_defaults + self.cli_group = cli_group + self._blueprints: list[tuple[Blueprint, dict[str, t.Any]]] = [] + + def _check_setup_finished(self, f_name: str) -> None: + if self._got_registered_once: + raise AssertionError( + f"The setup method '{f_name}' can no longer be called on the blueprint" + f" '{self.name}'. It has already been registered at least once, any" + " changes will not be applied consistently.\n" + "Make sure all imports, decorators, functions, etc. needed to set up" + " the blueprint are done before registering it." + ) + + @setupmethod + def record(self, func: DeferredSetupFunction) -> None: + """Registers a function that is called when the blueprint is + registered on the application. This function is called with the + state as argument as returned by the :meth:`make_setup_state` + method. + """ + self.deferred_functions.append(func) + + @setupmethod + def record_once(self, func: DeferredSetupFunction) -> None: + """Works like :meth:`record` but wraps the function in another + function that will ensure the function is only called once. If the + blueprint is registered a second time on the application, the + function passed is not called. + """ + + def wrapper(state: BlueprintSetupState) -> None: + if state.first_registration: + func(state) + + self.record(update_wrapper(wrapper, func)) + + def make_setup_state( + self, app: App, options: dict[str, t.Any], first_registration: bool = False + ) -> BlueprintSetupState: + """Creates an instance of :meth:`~flask.blueprints.BlueprintSetupState` + object that is later passed to the register callback functions. + Subclasses can override this to return a subclass of the setup state. + """ + return BlueprintSetupState(self, app, options, first_registration) + + @setupmethod + def register_blueprint(self, blueprint: Blueprint, **options: t.Any) -> None: + """Register a :class:`~flask.Blueprint` on this blueprint. Keyword + arguments passed to this method will override the defaults set + on the blueprint. + + .. versionchanged:: 2.0.1 + The ``name`` option can be used to change the (pre-dotted) + name the blueprint is registered with. This allows the same + blueprint to be registered multiple times with unique names + for ``url_for``. + + .. versionadded:: 2.0 + """ + if blueprint is self: + raise ValueError("Cannot register a blueprint on itself") + self._blueprints.append((blueprint, options)) + + def register(self, app: App, options: dict[str, t.Any]) -> None: + """Called by :meth:`Flask.register_blueprint` to register all + views and callbacks registered on the blueprint with the + application. Creates a :class:`.BlueprintSetupState` and calls + each :meth:`record` callback with it. + + :param app: The application this blueprint is being registered + with. + :param options: Keyword arguments forwarded from + :meth:`~Flask.register_blueprint`. + + .. versionchanged:: 2.3 + Nested blueprints now correctly apply subdomains. + + .. versionchanged:: 2.1 + Registering the same blueprint with the same name multiple + times is an error. + + .. versionchanged:: 2.0.1 + Nested blueprints are registered with their dotted name. + This allows different blueprints with the same name to be + nested at different locations. + + .. versionchanged:: 2.0.1 + The ``name`` option can be used to change the (pre-dotted) + name the blueprint is registered with. This allows the same + blueprint to be registered multiple times with unique names + for ``url_for``. + """ + name_prefix = options.get("name_prefix", "") + self_name = options.get("name", self.name) + name = f"{name_prefix}.{self_name}".lstrip(".") + + if name in app.blueprints: + bp_desc = "this" if app.blueprints[name] is self else "a different" + existing_at = f" '{name}'" if self_name != name else "" + + raise ValueError( + f"The name '{self_name}' is already registered for" + f" {bp_desc} blueprint{existing_at}. Use 'name=' to" + f" provide a unique name." + ) + + first_bp_registration = not any(bp is self for bp in app.blueprints.values()) + first_name_registration = name not in app.blueprints + + app.blueprints[name] = self + self._got_registered_once = True + state = self.make_setup_state(app, options, first_bp_registration) + + if self.has_static_folder: + state.add_url_rule( + f"{self.static_url_path}/", + view_func=self.send_static_file, # type: ignore[attr-defined] + endpoint="static", + ) + + # Merge blueprint data into parent. + if first_bp_registration or first_name_registration: + self._merge_blueprint_funcs(app, name) + + for deferred in self.deferred_functions: + deferred(state) + + cli_resolved_group = options.get("cli_group", self.cli_group) + + if self.cli.commands: + if cli_resolved_group is None: + app.cli.commands.update(self.cli.commands) + elif cli_resolved_group is _sentinel: + self.cli.name = name + app.cli.add_command(self.cli) + else: + self.cli.name = cli_resolved_group + app.cli.add_command(self.cli) + + for blueprint, bp_options in self._blueprints: + bp_options = bp_options.copy() + bp_url_prefix = bp_options.get("url_prefix") + bp_subdomain = bp_options.get("subdomain") + + if bp_subdomain is None: + bp_subdomain = blueprint.subdomain + + if state.subdomain is not None and bp_subdomain is not None: + bp_options["subdomain"] = bp_subdomain + "." + state.subdomain + elif bp_subdomain is not None: + bp_options["subdomain"] = bp_subdomain + elif state.subdomain is not None: + bp_options["subdomain"] = state.subdomain + + if bp_url_prefix is None: + bp_url_prefix = blueprint.url_prefix + + if state.url_prefix is not None and bp_url_prefix is not None: + bp_options["url_prefix"] = ( + state.url_prefix.rstrip("/") + "/" + bp_url_prefix.lstrip("/") + ) + elif bp_url_prefix is not None: + bp_options["url_prefix"] = bp_url_prefix + elif state.url_prefix is not None: + bp_options["url_prefix"] = state.url_prefix + + bp_options["name_prefix"] = name + blueprint.register(app, bp_options) + + def _merge_blueprint_funcs(self, app: App, name: str) -> None: + def extend( + bp_dict: dict[ft.AppOrBlueprintKey, list[t.Any]], + parent_dict: dict[ft.AppOrBlueprintKey, list[t.Any]], + ) -> None: + for key, values in bp_dict.items(): + key = name if key is None else f"{name}.{key}" + parent_dict[key].extend(values) + + for key, value in self.error_handler_spec.items(): + key = name if key is None else f"{name}.{key}" + value = defaultdict( + dict, + { + code: {exc_class: func for exc_class, func in code_values.items()} + for code, code_values in value.items() + }, + ) + app.error_handler_spec[key] = value + + for endpoint, func in self.view_functions.items(): + app.view_functions[endpoint] = func + + extend(self.before_request_funcs, app.before_request_funcs) + extend(self.after_request_funcs, app.after_request_funcs) + extend( + self.teardown_request_funcs, + app.teardown_request_funcs, + ) + extend(self.url_default_functions, app.url_default_functions) + extend(self.url_value_preprocessors, app.url_value_preprocessors) + extend(self.template_context_processors, app.template_context_processors) + + @setupmethod + def add_url_rule( + self, + rule: str, + endpoint: str | None = None, + view_func: ft.RouteCallable | None = None, + provide_automatic_options: bool | None = None, + **options: t.Any, + ) -> None: + """Register a URL rule with the blueprint. See :meth:`.Flask.add_url_rule` for + full documentation. + + The URL rule is prefixed with the blueprint's URL prefix. The endpoint name, + used with :func:`url_for`, is prefixed with the blueprint's name. + """ + if endpoint and "." in endpoint: + raise ValueError("'endpoint' may not contain a dot '.' character.") + + if view_func and hasattr(view_func, "__name__") and "." in view_func.__name__: + raise ValueError("'view_func' name may not contain a dot '.' character.") + + self.record( + lambda s: s.add_url_rule( + rule, + endpoint, + view_func, + provide_automatic_options=provide_automatic_options, + **options, + ) + ) + + @setupmethod + def app_template_filter( + self, name: str | None = None + ) -> t.Callable[[T_template_filter], T_template_filter]: + """Register a template filter, available in any template rendered by the + application. Equivalent to :meth:`.Flask.template_filter`. + + :param name: the optional name of the filter, otherwise the + function name will be used. + """ + + def decorator(f: T_template_filter) -> T_template_filter: + self.add_app_template_filter(f, name=name) + return f + + return decorator + + @setupmethod + def add_app_template_filter( + self, f: ft.TemplateFilterCallable, name: str | None = None + ) -> None: + """Register a template filter, available in any template rendered by the + application. Works like the :meth:`app_template_filter` decorator. Equivalent to + :meth:`.Flask.add_template_filter`. + + :param name: the optional name of the filter, otherwise the + function name will be used. + """ + + def register_template(state: BlueprintSetupState) -> None: + state.app.jinja_env.filters[name or f.__name__] = f + + self.record_once(register_template) + + @setupmethod + def app_template_test( + self, name: str | None = None + ) -> t.Callable[[T_template_test], T_template_test]: + """Register a template test, available in any template rendered by the + application. Equivalent to :meth:`.Flask.template_test`. + + .. versionadded:: 0.10 + + :param name: the optional name of the test, otherwise the + function name will be used. + """ + + def decorator(f: T_template_test) -> T_template_test: + self.add_app_template_test(f, name=name) + return f + + return decorator + + @setupmethod + def add_app_template_test( + self, f: ft.TemplateTestCallable, name: str | None = None + ) -> None: + """Register a template test, available in any template rendered by the + application. Works like the :meth:`app_template_test` decorator. Equivalent to + :meth:`.Flask.add_template_test`. + + .. versionadded:: 0.10 + + :param name: the optional name of the test, otherwise the + function name will be used. + """ + + def register_template(state: BlueprintSetupState) -> None: + state.app.jinja_env.tests[name or f.__name__] = f + + self.record_once(register_template) + + @setupmethod + def app_template_global( + self, name: str | None = None + ) -> t.Callable[[T_template_global], T_template_global]: + """Register a template global, available in any template rendered by the + application. Equivalent to :meth:`.Flask.template_global`. + + .. versionadded:: 0.10 + + :param name: the optional name of the global, otherwise the + function name will be used. + """ + + def decorator(f: T_template_global) -> T_template_global: + self.add_app_template_global(f, name=name) + return f + + return decorator + + @setupmethod + def add_app_template_global( + self, f: ft.TemplateGlobalCallable, name: str | None = None + ) -> None: + """Register a template global, available in any template rendered by the + application. Works like the :meth:`app_template_global` decorator. Equivalent to + :meth:`.Flask.add_template_global`. + + .. versionadded:: 0.10 + + :param name: the optional name of the global, otherwise the + function name will be used. + """ + + def register_template(state: BlueprintSetupState) -> None: + state.app.jinja_env.globals[name or f.__name__] = f + + self.record_once(register_template) + + @setupmethod + def before_app_request(self, f: T_before_request) -> T_before_request: + """Like :meth:`before_request`, but before every request, not only those handled + by the blueprint. Equivalent to :meth:`.Flask.before_request`. + """ + self.record_once( + lambda s: s.app.before_request_funcs.setdefault(None, []).append(f) + ) + return f + + @setupmethod + def after_app_request(self, f: T_after_request) -> T_after_request: + """Like :meth:`after_request`, but after every request, not only those handled + by the blueprint. Equivalent to :meth:`.Flask.after_request`. + """ + self.record_once( + lambda s: s.app.after_request_funcs.setdefault(None, []).append(f) + ) + return f + + @setupmethod + def teardown_app_request(self, f: T_teardown) -> T_teardown: + """Like :meth:`teardown_request`, but after every request, not only those + handled by the blueprint. Equivalent to :meth:`.Flask.teardown_request`. + """ + self.record_once( + lambda s: s.app.teardown_request_funcs.setdefault(None, []).append(f) + ) + return f + + @setupmethod + def app_context_processor( + self, f: T_template_context_processor + ) -> T_template_context_processor: + """Like :meth:`context_processor`, but for templates rendered by every view, not + only by the blueprint. Equivalent to :meth:`.Flask.context_processor`. + """ + self.record_once( + lambda s: s.app.template_context_processors.setdefault(None, []).append(f) + ) + return f + + @setupmethod + def app_errorhandler( + self, code: type[Exception] | int + ) -> t.Callable[[T_error_handler], T_error_handler]: + """Like :meth:`errorhandler`, but for every request, not only those handled by + the blueprint. Equivalent to :meth:`.Flask.errorhandler`. + """ + + def decorator(f: T_error_handler) -> T_error_handler: + def from_blueprint(state: BlueprintSetupState) -> None: + state.app.errorhandler(code)(f) + + self.record_once(from_blueprint) + return f + + return decorator + + @setupmethod + def app_url_value_preprocessor( + self, f: T_url_value_preprocessor + ) -> T_url_value_preprocessor: + """Like :meth:`url_value_preprocessor`, but for every request, not only those + handled by the blueprint. Equivalent to :meth:`.Flask.url_value_preprocessor`. + """ + self.record_once( + lambda s: s.app.url_value_preprocessors.setdefault(None, []).append(f) + ) + return f + + @setupmethod + def app_url_defaults(self, f: T_url_defaults) -> T_url_defaults: + """Like :meth:`url_defaults`, but for every request, not only those handled by + the blueprint. Equivalent to :meth:`.Flask.url_defaults`. + """ + self.record_once( + lambda s: s.app.url_default_functions.setdefault(None, []).append(f) + ) + return f diff --git a/backend/venv/Lib/site-packages/flask/sansio/scaffold.py b/backend/venv/Lib/site-packages/flask/sansio/scaffold.py new file mode 100644 index 0000000..0e96f15 --- /dev/null +++ b/backend/venv/Lib/site-packages/flask/sansio/scaffold.py @@ -0,0 +1,792 @@ +from __future__ import annotations + +import importlib.util +import os +import pathlib +import sys +import typing as t +from collections import defaultdict +from functools import update_wrapper + +from jinja2 import BaseLoader +from jinja2 import FileSystemLoader +from werkzeug.exceptions import default_exceptions +from werkzeug.exceptions import HTTPException +from werkzeug.utils import cached_property + +from .. import typing as ft +from ..helpers import get_root_path +from ..templating import _default_template_ctx_processor + +if t.TYPE_CHECKING: # pragma: no cover + from click import Group + +# a singleton sentinel value for parameter defaults +_sentinel = object() + +F = t.TypeVar("F", bound=t.Callable[..., t.Any]) +T_after_request = t.TypeVar("T_after_request", bound=ft.AfterRequestCallable[t.Any]) +T_before_request = t.TypeVar("T_before_request", bound=ft.BeforeRequestCallable) +T_error_handler = t.TypeVar("T_error_handler", bound=ft.ErrorHandlerCallable) +T_teardown = t.TypeVar("T_teardown", bound=ft.TeardownCallable) +T_template_context_processor = t.TypeVar( + "T_template_context_processor", bound=ft.TemplateContextProcessorCallable +) +T_url_defaults = t.TypeVar("T_url_defaults", bound=ft.URLDefaultCallable) +T_url_value_preprocessor = t.TypeVar( + "T_url_value_preprocessor", bound=ft.URLValuePreprocessorCallable +) +T_route = t.TypeVar("T_route", bound=ft.RouteCallable) + + +def setupmethod(f: F) -> F: + f_name = f.__name__ + + def wrapper_func(self: Scaffold, *args: t.Any, **kwargs: t.Any) -> t.Any: + self._check_setup_finished(f_name) + return f(self, *args, **kwargs) + + return t.cast(F, update_wrapper(wrapper_func, f)) + + +class Scaffold: + """Common behavior shared between :class:`~flask.Flask` and + :class:`~flask.blueprints.Blueprint`. + + :param import_name: The import name of the module where this object + is defined. Usually :attr:`__name__` should be used. + :param static_folder: Path to a folder of static files to serve. + If this is set, a static route will be added. + :param static_url_path: URL prefix for the static route. + :param template_folder: Path to a folder containing template files. + for rendering. If this is set, a Jinja loader will be added. + :param root_path: The path that static, template, and resource files + are relative to. Typically not set, it is discovered based on + the ``import_name``. + + .. versionadded:: 2.0 + """ + + cli: Group + name: str + _static_folder: str | None = None + _static_url_path: str | None = None + + def __init__( + self, + import_name: str, + static_folder: str | os.PathLike[str] | None = None, + static_url_path: str | None = None, + template_folder: str | os.PathLike[str] | None = None, + root_path: str | None = None, + ): + #: The name of the package or module that this object belongs + #: to. Do not change this once it is set by the constructor. + self.import_name = import_name + + self.static_folder = static_folder + self.static_url_path = static_url_path + + #: The path to the templates folder, relative to + #: :attr:`root_path`, to add to the template loader. ``None`` if + #: templates should not be added. + self.template_folder = template_folder + + if root_path is None: + root_path = get_root_path(self.import_name) + + #: Absolute path to the package on the filesystem. Used to look + #: up resources contained in the package. + self.root_path = root_path + + #: A dictionary mapping endpoint names to view functions. + #: + #: To register a view function, use the :meth:`route` decorator. + #: + #: This data structure is internal. It should not be modified + #: directly and its format may change at any time. + self.view_functions: dict[str, ft.RouteCallable] = {} + + #: A data structure of registered error handlers, in the format + #: ``{scope: {code: {class: handler}}}``. The ``scope`` key is + #: the name of a blueprint the handlers are active for, or + #: ``None`` for all requests. The ``code`` key is the HTTP + #: status code for ``HTTPException``, or ``None`` for + #: other exceptions. The innermost dictionary maps exception + #: classes to handler functions. + #: + #: To register an error handler, use the :meth:`errorhandler` + #: decorator. + #: + #: This data structure is internal. It should not be modified + #: directly and its format may change at any time. + self.error_handler_spec: dict[ + ft.AppOrBlueprintKey, + dict[int | None, dict[type[Exception], ft.ErrorHandlerCallable]], + ] = defaultdict(lambda: defaultdict(dict)) + + #: A data structure of functions to call at the beginning of + #: each request, in the format ``{scope: [functions]}``. The + #: ``scope`` key is the name of a blueprint the functions are + #: active for, or ``None`` for all requests. + #: + #: To register a function, use the :meth:`before_request` + #: decorator. + #: + #: This data structure is internal. It should not be modified + #: directly and its format may change at any time. + self.before_request_funcs: dict[ + ft.AppOrBlueprintKey, list[ft.BeforeRequestCallable] + ] = defaultdict(list) + + #: A data structure of functions to call at the end of each + #: request, in the format ``{scope: [functions]}``. The + #: ``scope`` key is the name of a blueprint the functions are + #: active for, or ``None`` for all requests. + #: + #: To register a function, use the :meth:`after_request` + #: decorator. + #: + #: This data structure is internal. It should not be modified + #: directly and its format may change at any time. + self.after_request_funcs: dict[ + ft.AppOrBlueprintKey, list[ft.AfterRequestCallable[t.Any]] + ] = defaultdict(list) + + #: A data structure of functions to call at the end of each + #: request even if an exception is raised, in the format + #: ``{scope: [functions]}``. The ``scope`` key is the name of a + #: blueprint the functions are active for, or ``None`` for all + #: requests. + #: + #: To register a function, use the :meth:`teardown_request` + #: decorator. + #: + #: This data structure is internal. It should not be modified + #: directly and its format may change at any time. + self.teardown_request_funcs: dict[ + ft.AppOrBlueprintKey, list[ft.TeardownCallable] + ] = defaultdict(list) + + #: A data structure of functions to call to pass extra context + #: values when rendering templates, in the format + #: ``{scope: [functions]}``. The ``scope`` key is the name of a + #: blueprint the functions are active for, or ``None`` for all + #: requests. + #: + #: To register a function, use the :meth:`context_processor` + #: decorator. + #: + #: This data structure is internal. It should not be modified + #: directly and its format may change at any time. + self.template_context_processors: dict[ + ft.AppOrBlueprintKey, list[ft.TemplateContextProcessorCallable] + ] = defaultdict(list, {None: [_default_template_ctx_processor]}) + + #: A data structure of functions to call to modify the keyword + #: arguments passed to the view function, in the format + #: ``{scope: [functions]}``. The ``scope`` key is the name of a + #: blueprint the functions are active for, or ``None`` for all + #: requests. + #: + #: To register a function, use the + #: :meth:`url_value_preprocessor` decorator. + #: + #: This data structure is internal. It should not be modified + #: directly and its format may change at any time. + self.url_value_preprocessors: dict[ + ft.AppOrBlueprintKey, + list[ft.URLValuePreprocessorCallable], + ] = defaultdict(list) + + #: A data structure of functions to call to modify the keyword + #: arguments when generating URLs, in the format + #: ``{scope: [functions]}``. The ``scope`` key is the name of a + #: blueprint the functions are active for, or ``None`` for all + #: requests. + #: + #: To register a function, use the :meth:`url_defaults` + #: decorator. + #: + #: This data structure is internal. It should not be modified + #: directly and its format may change at any time. + self.url_default_functions: dict[ + ft.AppOrBlueprintKey, list[ft.URLDefaultCallable] + ] = defaultdict(list) + + def __repr__(self) -> str: + return f"<{type(self).__name__} {self.name!r}>" + + def _check_setup_finished(self, f_name: str) -> None: + raise NotImplementedError + + @property + def static_folder(self) -> str | None: + """The absolute path to the configured static folder. ``None`` + if no static folder is set. + """ + if self._static_folder is not None: + return os.path.join(self.root_path, self._static_folder) + else: + return None + + @static_folder.setter + def static_folder(self, value: str | os.PathLike[str] | None) -> None: + if value is not None: + value = os.fspath(value).rstrip(r"\/") + + self._static_folder = value + + @property + def has_static_folder(self) -> bool: + """``True`` if :attr:`static_folder` is set. + + .. versionadded:: 0.5 + """ + return self.static_folder is not None + + @property + def static_url_path(self) -> str | None: + """The URL prefix that the static route will be accessible from. + + If it was not configured during init, it is derived from + :attr:`static_folder`. + """ + if self._static_url_path is not None: + return self._static_url_path + + if self.static_folder is not None: + basename = os.path.basename(self.static_folder) + return f"/{basename}".rstrip("/") + + return None + + @static_url_path.setter + def static_url_path(self, value: str | None) -> None: + if value is not None: + value = value.rstrip("/") + + self._static_url_path = value + + @cached_property + def jinja_loader(self) -> BaseLoader | None: + """The Jinja loader for this object's templates. By default this + is a class :class:`jinja2.loaders.FileSystemLoader` to + :attr:`template_folder` if it is set. + + .. versionadded:: 0.5 + """ + if self.template_folder is not None: + return FileSystemLoader(os.path.join(self.root_path, self.template_folder)) + else: + return None + + def _method_route( + self, + method: str, + rule: str, + options: dict[str, t.Any], + ) -> t.Callable[[T_route], T_route]: + if "methods" in options: + raise TypeError("Use the 'route' decorator to use the 'methods' argument.") + + return self.route(rule, methods=[method], **options) + + @setupmethod + def get(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]: + """Shortcut for :meth:`route` with ``methods=["GET"]``. + + .. versionadded:: 2.0 + """ + return self._method_route("GET", rule, options) + + @setupmethod + def post(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]: + """Shortcut for :meth:`route` with ``methods=["POST"]``. + + .. versionadded:: 2.0 + """ + return self._method_route("POST", rule, options) + + @setupmethod + def put(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]: + """Shortcut for :meth:`route` with ``methods=["PUT"]``. + + .. versionadded:: 2.0 + """ + return self._method_route("PUT", rule, options) + + @setupmethod + def delete(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]: + """Shortcut for :meth:`route` with ``methods=["DELETE"]``. + + .. versionadded:: 2.0 + """ + return self._method_route("DELETE", rule, options) + + @setupmethod + def patch(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]: + """Shortcut for :meth:`route` with ``methods=["PATCH"]``. + + .. versionadded:: 2.0 + """ + return self._method_route("PATCH", rule, options) + + @setupmethod + def route(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]: + """Decorate a view function to register it with the given URL + rule and options. Calls :meth:`add_url_rule`, which has more + details about the implementation. + + .. code-block:: python + + @app.route("/") + def index(): + return "Hello, World!" + + See :ref:`url-route-registrations`. + + The endpoint name for the route defaults to the name of the view + function if the ``endpoint`` parameter isn't passed. + + The ``methods`` parameter defaults to ``["GET"]``. ``HEAD`` and + ``OPTIONS`` are added automatically. + + :param rule: The URL rule string. + :param options: Extra options passed to the + :class:`~werkzeug.routing.Rule` object. + """ + + def decorator(f: T_route) -> T_route: + endpoint = options.pop("endpoint", None) + self.add_url_rule(rule, endpoint, f, **options) + return f + + return decorator + + @setupmethod + def add_url_rule( + self, + rule: str, + endpoint: str | None = None, + view_func: ft.RouteCallable | None = None, + provide_automatic_options: bool | None = None, + **options: t.Any, + ) -> None: + """Register a rule for routing incoming requests and building + URLs. The :meth:`route` decorator is a shortcut to call this + with the ``view_func`` argument. These are equivalent: + + .. code-block:: python + + @app.route("/") + def index(): + ... + + .. code-block:: python + + def index(): + ... + + app.add_url_rule("/", view_func=index) + + See :ref:`url-route-registrations`. + + The endpoint name for the route defaults to the name of the view + function if the ``endpoint`` parameter isn't passed. An error + will be raised if a function has already been registered for the + endpoint. + + The ``methods`` parameter defaults to ``["GET"]``. ``HEAD`` is + always added automatically, and ``OPTIONS`` is added + automatically by default. + + ``view_func`` does not necessarily need to be passed, but if the + rule should participate in routing an endpoint name must be + associated with a view function at some point with the + :meth:`endpoint` decorator. + + .. code-block:: python + + app.add_url_rule("/", endpoint="index") + + @app.endpoint("index") + def index(): + ... + + If ``view_func`` has a ``required_methods`` attribute, those + methods are added to the passed and automatic methods. If it + has a ``provide_automatic_methods`` attribute, it is used as the + default if the parameter is not passed. + + :param rule: The URL rule string. + :param endpoint: The endpoint name to associate with the rule + and view function. Used when routing and building URLs. + Defaults to ``view_func.__name__``. + :param view_func: The view function to associate with the + endpoint name. + :param provide_automatic_options: Add the ``OPTIONS`` method and + respond to ``OPTIONS`` requests automatically. + :param options: Extra options passed to the + :class:`~werkzeug.routing.Rule` object. + """ + raise NotImplementedError + + @setupmethod + def endpoint(self, endpoint: str) -> t.Callable[[F], F]: + """Decorate a view function to register it for the given + endpoint. Used if a rule is added without a ``view_func`` with + :meth:`add_url_rule`. + + .. code-block:: python + + app.add_url_rule("/ex", endpoint="example") + + @app.endpoint("example") + def example(): + ... + + :param endpoint: The endpoint name to associate with the view + function. + """ + + def decorator(f: F) -> F: + self.view_functions[endpoint] = f + return f + + return decorator + + @setupmethod + def before_request(self, f: T_before_request) -> T_before_request: + """Register a function to run before each request. + + For example, this can be used to open a database connection, or + to load the logged in user from the session. + + .. code-block:: python + + @app.before_request + def load_user(): + if "user_id" in session: + g.user = db.session.get(session["user_id"]) + + The function will be called without any arguments. If it returns + a non-``None`` value, the value is handled as if it was the + return value from the view, and further request handling is + stopped. + + This is available on both app and blueprint objects. When used on an app, this + executes before every request. When used on a blueprint, this executes before + every request that the blueprint handles. To register with a blueprint and + execute before every request, use :meth:`.Blueprint.before_app_request`. + """ + self.before_request_funcs.setdefault(None, []).append(f) + return f + + @setupmethod + def after_request(self, f: T_after_request) -> T_after_request: + """Register a function to run after each request to this object. + + The function is called with the response object, and must return + a response object. This allows the functions to modify or + replace the response before it is sent. + + If a function raises an exception, any remaining + ``after_request`` functions will not be called. Therefore, this + should not be used for actions that must execute, such as to + close resources. Use :meth:`teardown_request` for that. + + This is available on both app and blueprint objects. When used on an app, this + executes after every request. When used on a blueprint, this executes after + every request that the blueprint handles. To register with a blueprint and + execute after every request, use :meth:`.Blueprint.after_app_request`. + """ + self.after_request_funcs.setdefault(None, []).append(f) + return f + + @setupmethod + def teardown_request(self, f: T_teardown) -> T_teardown: + """Register a function to be called when the request context is + popped. Typically this happens at the end of each request, but + contexts may be pushed manually as well during testing. + + .. code-block:: python + + with app.test_request_context(): + ... + + When the ``with`` block exits (or ``ctx.pop()`` is called), the + teardown functions are called just before the request context is + made inactive. + + When a teardown function was called because of an unhandled + exception it will be passed an error object. If an + :meth:`errorhandler` is registered, it will handle the exception + and the teardown will not receive it. + + Teardown functions must avoid raising exceptions. If they + execute code that might fail they must surround that code with a + ``try``/``except`` block and log any errors. + + The return values of teardown functions are ignored. + + This is available on both app and blueprint objects. When used on an app, this + executes after every request. When used on a blueprint, this executes after + every request that the blueprint handles. To register with a blueprint and + execute after every request, use :meth:`.Blueprint.teardown_app_request`. + """ + self.teardown_request_funcs.setdefault(None, []).append(f) + return f + + @setupmethod + def context_processor( + self, + f: T_template_context_processor, + ) -> T_template_context_processor: + """Registers a template context processor function. These functions run before + rendering a template. The keys of the returned dict are added as variables + available in the template. + + This is available on both app and blueprint objects. When used on an app, this + is called for every rendered template. When used on a blueprint, this is called + for templates rendered from the blueprint's views. To register with a blueprint + and affect every template, use :meth:`.Blueprint.app_context_processor`. + """ + self.template_context_processors[None].append(f) + return f + + @setupmethod + def url_value_preprocessor( + self, + f: T_url_value_preprocessor, + ) -> T_url_value_preprocessor: + """Register a URL value preprocessor function for all view + functions in the application. These functions will be called before the + :meth:`before_request` functions. + + The function can modify the values captured from the matched url before + they are passed to the view. For example, this can be used to pop a + common language code value and place it in ``g`` rather than pass it to + every view. + + The function is passed the endpoint name and values dict. The return + value is ignored. + + This is available on both app and blueprint objects. When used on an app, this + is called for every request. When used on a blueprint, this is called for + requests that the blueprint handles. To register with a blueprint and affect + every request, use :meth:`.Blueprint.app_url_value_preprocessor`. + """ + self.url_value_preprocessors[None].append(f) + return f + + @setupmethod + def url_defaults(self, f: T_url_defaults) -> T_url_defaults: + """Callback function for URL defaults for all view functions of the + application. It's called with the endpoint and values and should + update the values passed in place. + + This is available on both app and blueprint objects. When used on an app, this + is called for every request. When used on a blueprint, this is called for + requests that the blueprint handles. To register with a blueprint and affect + every request, use :meth:`.Blueprint.app_url_defaults`. + """ + self.url_default_functions[None].append(f) + return f + + @setupmethod + def errorhandler( + self, code_or_exception: type[Exception] | int + ) -> t.Callable[[T_error_handler], T_error_handler]: + """Register a function to handle errors by code or exception class. + + A decorator that is used to register a function given an + error code. Example:: + + @app.errorhandler(404) + def page_not_found(error): + return 'This page does not exist', 404 + + You can also register handlers for arbitrary exceptions:: + + @app.errorhandler(DatabaseError) + def special_exception_handler(error): + return 'Database connection failed', 500 + + This is available on both app and blueprint objects. When used on an app, this + can handle errors from every request. When used on a blueprint, this can handle + errors from requests that the blueprint handles. To register with a blueprint + and affect every request, use :meth:`.Blueprint.app_errorhandler`. + + .. versionadded:: 0.7 + Use :meth:`register_error_handler` instead of modifying + :attr:`error_handler_spec` directly, for application wide error + handlers. + + .. versionadded:: 0.7 + One can now additionally also register custom exception types + that do not necessarily have to be a subclass of the + :class:`~werkzeug.exceptions.HTTPException` class. + + :param code_or_exception: the code as integer for the handler, or + an arbitrary exception + """ + + def decorator(f: T_error_handler) -> T_error_handler: + self.register_error_handler(code_or_exception, f) + return f + + return decorator + + @setupmethod + def register_error_handler( + self, + code_or_exception: type[Exception] | int, + f: ft.ErrorHandlerCallable, + ) -> None: + """Alternative error attach function to the :meth:`errorhandler` + decorator that is more straightforward to use for non decorator + usage. + + .. versionadded:: 0.7 + """ + exc_class, code = self._get_exc_class_and_code(code_or_exception) + self.error_handler_spec[None][code][exc_class] = f + + @staticmethod + def _get_exc_class_and_code( + exc_class_or_code: type[Exception] | int, + ) -> tuple[type[Exception], int | None]: + """Get the exception class being handled. For HTTP status codes + or ``HTTPException`` subclasses, return both the exception and + status code. + + :param exc_class_or_code: Any exception class, or an HTTP status + code as an integer. + """ + exc_class: type[Exception] + + if isinstance(exc_class_or_code, int): + try: + exc_class = default_exceptions[exc_class_or_code] + except KeyError: + raise ValueError( + f"'{exc_class_or_code}' is not a recognized HTTP" + " error code. Use a subclass of HTTPException with" + " that code instead." + ) from None + else: + exc_class = exc_class_or_code + + if isinstance(exc_class, Exception): + raise TypeError( + f"{exc_class!r} is an instance, not a class. Handlers" + " can only be registered for Exception classes or HTTP" + " error codes." + ) + + if not issubclass(exc_class, Exception): + raise ValueError( + f"'{exc_class.__name__}' is not a subclass of Exception." + " Handlers can only be registered for Exception classes" + " or HTTP error codes." + ) + + if issubclass(exc_class, HTTPException): + return exc_class, exc_class.code + else: + return exc_class, None + + +def _endpoint_from_view_func(view_func: ft.RouteCallable) -> str: + """Internal helper that returns the default endpoint for a given + function. This always is the function name. + """ + assert view_func is not None, "expected view func if endpoint is not provided." + return view_func.__name__ + + +def _find_package_path(import_name: str) -> str: + """Find the path that contains the package or module.""" + root_mod_name, _, _ = import_name.partition(".") + + try: + root_spec = importlib.util.find_spec(root_mod_name) + + if root_spec is None: + raise ValueError("not found") + except (ImportError, ValueError): + # ImportError: the machinery told us it does not exist + # ValueError: + # - the module name was invalid + # - the module name is __main__ + # - we raised `ValueError` due to `root_spec` being `None` + return os.getcwd() + + if root_spec.submodule_search_locations: + if root_spec.origin is None or root_spec.origin == "namespace": + # namespace package + package_spec = importlib.util.find_spec(import_name) + + if package_spec is not None and package_spec.submodule_search_locations: + # Pick the path in the namespace that contains the submodule. + package_path = pathlib.Path( + os.path.commonpath(package_spec.submodule_search_locations) + ) + search_location = next( + location + for location in root_spec.submodule_search_locations + if package_path.is_relative_to(location) + ) + else: + # Pick the first path. + search_location = root_spec.submodule_search_locations[0] + + return os.path.dirname(search_location) + else: + # package with __init__.py + return os.path.dirname(os.path.dirname(root_spec.origin)) + else: + # module + return os.path.dirname(root_spec.origin) # type: ignore[type-var, return-value] + + +def find_package(import_name: str) -> tuple[str | None, str]: + """Find the prefix that a package is installed under, and the path + that it would be imported from. + + The prefix is the directory containing the standard directory + hierarchy (lib, bin, etc.). If the package is not installed to the + system (:attr:`sys.prefix`) or a virtualenv (``site-packages``), + ``None`` is returned. + + The path is the entry in :attr:`sys.path` that contains the package + for import. If the package is not installed, it's assumed that the + package was imported from the current working directory. + """ + package_path = _find_package_path(import_name) + py_prefix = os.path.abspath(sys.prefix) + + # installed to the system + if pathlib.PurePath(package_path).is_relative_to(py_prefix): + return py_prefix, package_path + + site_parent, site_folder = os.path.split(package_path) + + # installed to a virtualenv + if site_folder.lower() == "site-packages": + parent, folder = os.path.split(site_parent) + + # Windows (prefix/lib/site-packages) + if folder.lower() == "lib": + return parent, package_path + + # Unix (prefix/lib/pythonX.Y/site-packages) + if os.path.basename(parent).lower() == "lib": + return os.path.dirname(parent), package_path + + # something else (prefix/site-packages) + return site_parent, package_path + + # not installed + return None, package_path diff --git a/backend/venv/Lib/site-packages/flask/sessions.py b/backend/venv/Lib/site-packages/flask/sessions.py new file mode 100644 index 0000000..0a357d9 --- /dev/null +++ b/backend/venv/Lib/site-packages/flask/sessions.py @@ -0,0 +1,399 @@ +from __future__ import annotations + +import collections.abc as c +import hashlib +import typing as t +from collections.abc import MutableMapping +from datetime import datetime +from datetime import timezone + +from itsdangerous import BadSignature +from itsdangerous import URLSafeTimedSerializer +from werkzeug.datastructures import CallbackDict + +from .json.tag import TaggedJSONSerializer + +if t.TYPE_CHECKING: # pragma: no cover + import typing_extensions as te + + from .app import Flask + from .wrappers import Request + from .wrappers import Response + + +class SessionMixin(MutableMapping[str, t.Any]): + """Expands a basic dictionary with session attributes.""" + + @property + def permanent(self) -> bool: + """This reflects the ``'_permanent'`` key in the dict.""" + return self.get("_permanent", False) + + @permanent.setter + def permanent(self, value: bool) -> None: + self["_permanent"] = bool(value) + + #: Some implementations can detect whether a session is newly + #: created, but that is not guaranteed. Use with caution. The mixin + # default is hard-coded ``False``. + new = False + + #: Some implementations can detect changes to the session and set + #: this when that happens. The mixin default is hard coded to + #: ``True``. + modified = True + + #: Some implementations can detect when session data is read or + #: written and set this when that happens. The mixin default is hard + #: coded to ``True``. + accessed = True + + +class SecureCookieSession(CallbackDict[str, t.Any], SessionMixin): + """Base class for sessions based on signed cookies. + + This session backend will set the :attr:`modified` and + :attr:`accessed` attributes. It cannot reliably track whether a + session is new (vs. empty), so :attr:`new` remains hard coded to + ``False``. + """ + + #: When data is changed, this is set to ``True``. Only the session + #: dictionary itself is tracked; if the session contains mutable + #: data (for example a nested dict) then this must be set to + #: ``True`` manually when modifying that data. The session cookie + #: will only be written to the response if this is ``True``. + modified = False + + #: When data is read or written, this is set to ``True``. Used by + # :class:`.SecureCookieSessionInterface` to add a ``Vary: Cookie`` + #: header, which allows caching proxies to cache different pages for + #: different users. + accessed = False + + def __init__( + self, + initial: c.Mapping[str, t.Any] | c.Iterable[tuple[str, t.Any]] | None = None, + ) -> None: + def on_update(self: te.Self) -> None: + self.modified = True + self.accessed = True + + super().__init__(initial, on_update) + + def __getitem__(self, key: str) -> t.Any: + self.accessed = True + return super().__getitem__(key) + + def get(self, key: str, default: t.Any = None) -> t.Any: + self.accessed = True + return super().get(key, default) + + def setdefault(self, key: str, default: t.Any = None) -> t.Any: + self.accessed = True + return super().setdefault(key, default) + + +class NullSession(SecureCookieSession): + """Class used to generate nicer error messages if sessions are not + available. Will still allow read-only access to the empty session + but fail on setting. + """ + + def _fail(self, *args: t.Any, **kwargs: t.Any) -> t.NoReturn: + raise RuntimeError( + "The session is unavailable because no secret " + "key was set. Set the secret_key on the " + "application to something unique and secret." + ) + + __setitem__ = __delitem__ = clear = pop = popitem = update = setdefault = _fail # noqa: B950 + del _fail + + +class SessionInterface: + """The basic interface you have to implement in order to replace the + default session interface which uses werkzeug's securecookie + implementation. The only methods you have to implement are + :meth:`open_session` and :meth:`save_session`, the others have + useful defaults which you don't need to change. + + The session object returned by the :meth:`open_session` method has to + provide a dictionary like interface plus the properties and methods + from the :class:`SessionMixin`. We recommend just subclassing a dict + and adding that mixin:: + + class Session(dict, SessionMixin): + pass + + If :meth:`open_session` returns ``None`` Flask will call into + :meth:`make_null_session` to create a session that acts as replacement + if the session support cannot work because some requirement is not + fulfilled. The default :class:`NullSession` class that is created + will complain that the secret key was not set. + + To replace the session interface on an application all you have to do + is to assign :attr:`flask.Flask.session_interface`:: + + app = Flask(__name__) + app.session_interface = MySessionInterface() + + Multiple requests with the same session may be sent and handled + concurrently. When implementing a new session interface, consider + whether reads or writes to the backing store must be synchronized. + There is no guarantee on the order in which the session for each + request is opened or saved, it will occur in the order that requests + begin and end processing. + + .. versionadded:: 0.8 + """ + + #: :meth:`make_null_session` will look here for the class that should + #: be created when a null session is requested. Likewise the + #: :meth:`is_null_session` method will perform a typecheck against + #: this type. + null_session_class = NullSession + + #: A flag that indicates if the session interface is pickle based. + #: This can be used by Flask extensions to make a decision in regards + #: to how to deal with the session object. + #: + #: .. versionadded:: 0.10 + pickle_based = False + + def make_null_session(self, app: Flask) -> NullSession: + """Creates a null session which acts as a replacement object if the + real session support could not be loaded due to a configuration + error. This mainly aids the user experience because the job of the + null session is to still support lookup without complaining but + modifications are answered with a helpful error message of what + failed. + + This creates an instance of :attr:`null_session_class` by default. + """ + return self.null_session_class() + + def is_null_session(self, obj: object) -> bool: + """Checks if a given object is a null session. Null sessions are + not asked to be saved. + + This checks if the object is an instance of :attr:`null_session_class` + by default. + """ + return isinstance(obj, self.null_session_class) + + def get_cookie_name(self, app: Flask) -> str: + """The name of the session cookie. Uses``app.config["SESSION_COOKIE_NAME"]``.""" + return app.config["SESSION_COOKIE_NAME"] # type: ignore[no-any-return] + + def get_cookie_domain(self, app: Flask) -> str | None: + """The value of the ``Domain`` parameter on the session cookie. If not set, + browsers will only send the cookie to the exact domain it was set from. + Otherwise, they will send it to any subdomain of the given value as well. + + Uses the :data:`SESSION_COOKIE_DOMAIN` config. + + .. versionchanged:: 2.3 + Not set by default, does not fall back to ``SERVER_NAME``. + """ + return app.config["SESSION_COOKIE_DOMAIN"] # type: ignore[no-any-return] + + def get_cookie_path(self, app: Flask) -> str: + """Returns the path for which the cookie should be valid. The + default implementation uses the value from the ``SESSION_COOKIE_PATH`` + config var if it's set, and falls back to ``APPLICATION_ROOT`` or + uses ``/`` if it's ``None``. + """ + return app.config["SESSION_COOKIE_PATH"] or app.config["APPLICATION_ROOT"] # type: ignore[no-any-return] + + def get_cookie_httponly(self, app: Flask) -> bool: + """Returns True if the session cookie should be httponly. This + currently just returns the value of the ``SESSION_COOKIE_HTTPONLY`` + config var. + """ + return app.config["SESSION_COOKIE_HTTPONLY"] # type: ignore[no-any-return] + + def get_cookie_secure(self, app: Flask) -> bool: + """Returns True if the cookie should be secure. This currently + just returns the value of the ``SESSION_COOKIE_SECURE`` setting. + """ + return app.config["SESSION_COOKIE_SECURE"] # type: ignore[no-any-return] + + def get_cookie_samesite(self, app: Flask) -> str | None: + """Return ``'Strict'`` or ``'Lax'`` if the cookie should use the + ``SameSite`` attribute. This currently just returns the value of + the :data:`SESSION_COOKIE_SAMESITE` setting. + """ + return app.config["SESSION_COOKIE_SAMESITE"] # type: ignore[no-any-return] + + def get_cookie_partitioned(self, app: Flask) -> bool: + """Returns True if the cookie should be partitioned. By default, uses + the value of :data:`SESSION_COOKIE_PARTITIONED`. + + .. versionadded:: 3.1 + """ + return app.config["SESSION_COOKIE_PARTITIONED"] # type: ignore[no-any-return] + + def get_expiration_time(self, app: Flask, session: SessionMixin) -> datetime | None: + """A helper method that returns an expiration date for the session + or ``None`` if the session is linked to the browser session. The + default implementation returns now + the permanent session + lifetime configured on the application. + """ + if session.permanent: + return datetime.now(timezone.utc) + app.permanent_session_lifetime + return None + + def should_set_cookie(self, app: Flask, session: SessionMixin) -> bool: + """Used by session backends to determine if a ``Set-Cookie`` header + should be set for this session cookie for this response. If the session + has been modified, the cookie is set. If the session is permanent and + the ``SESSION_REFRESH_EACH_REQUEST`` config is true, the cookie is + always set. + + This check is usually skipped if the session was deleted. + + .. versionadded:: 0.11 + """ + + return session.modified or ( + session.permanent and app.config["SESSION_REFRESH_EACH_REQUEST"] + ) + + def open_session(self, app: Flask, request: Request) -> SessionMixin | None: + """This is called at the beginning of each request, after + pushing the request context, before matching the URL. + + This must return an object which implements a dictionary-like + interface as well as the :class:`SessionMixin` interface. + + This will return ``None`` to indicate that loading failed in + some way that is not immediately an error. The request + context will fall back to using :meth:`make_null_session` + in this case. + """ + raise NotImplementedError() + + def save_session( + self, app: Flask, session: SessionMixin, response: Response + ) -> None: + """This is called at the end of each request, after generating + a response, before removing the request context. It is skipped + if :meth:`is_null_session` returns ``True``. + """ + raise NotImplementedError() + + +session_json_serializer = TaggedJSONSerializer() + + +def _lazy_sha1(string: bytes = b"") -> t.Any: + """Don't access ``hashlib.sha1`` until runtime. FIPS builds may not include + SHA-1, in which case the import and use as a default would fail before the + developer can configure something else. + """ + return hashlib.sha1(string) + + +class SecureCookieSessionInterface(SessionInterface): + """The default session interface that stores sessions in signed cookies + through the :mod:`itsdangerous` module. + """ + + #: the salt that should be applied on top of the secret key for the + #: signing of cookie based sessions. + salt = "cookie-session" + #: the hash function to use for the signature. The default is sha1 + digest_method = staticmethod(_lazy_sha1) + #: the name of the itsdangerous supported key derivation. The default + #: is hmac. + key_derivation = "hmac" + #: A python serializer for the payload. The default is a compact + #: JSON derived serializer with support for some extra Python types + #: such as datetime objects or tuples. + serializer = session_json_serializer + session_class = SecureCookieSession + + def get_signing_serializer(self, app: Flask) -> URLSafeTimedSerializer | None: + if not app.secret_key: + return None + + keys: list[str | bytes] = [] + + if fallbacks := app.config["SECRET_KEY_FALLBACKS"]: + keys.extend(fallbacks) + + keys.append(app.secret_key) # itsdangerous expects current key at top + return URLSafeTimedSerializer( + keys, # type: ignore[arg-type] + salt=self.salt, + serializer=self.serializer, + signer_kwargs={ + "key_derivation": self.key_derivation, + "digest_method": self.digest_method, + }, + ) + + def open_session(self, app: Flask, request: Request) -> SecureCookieSession | None: + s = self.get_signing_serializer(app) + if s is None: + return None + val = request.cookies.get(self.get_cookie_name(app)) + if not val: + return self.session_class() + max_age = int(app.permanent_session_lifetime.total_seconds()) + try: + data = s.loads(val, max_age=max_age) + return self.session_class(data) + except BadSignature: + return self.session_class() + + def save_session( + self, app: Flask, session: SessionMixin, response: Response + ) -> None: + name = self.get_cookie_name(app) + domain = self.get_cookie_domain(app) + path = self.get_cookie_path(app) + secure = self.get_cookie_secure(app) + partitioned = self.get_cookie_partitioned(app) + samesite = self.get_cookie_samesite(app) + httponly = self.get_cookie_httponly(app) + + # Add a "Vary: Cookie" header if the session was accessed at all. + if session.accessed: + response.vary.add("Cookie") + + # If the session is modified to be empty, remove the cookie. + # If the session is empty, return without setting the cookie. + if not session: + if session.modified: + response.delete_cookie( + name, + domain=domain, + path=path, + secure=secure, + partitioned=partitioned, + samesite=samesite, + httponly=httponly, + ) + response.vary.add("Cookie") + + return + + if not self.should_set_cookie(app, session): + return + + expires = self.get_expiration_time(app, session) + val = self.get_signing_serializer(app).dumps(dict(session)) # type: ignore[union-attr] + response.set_cookie( + name, + val, + expires=expires, + httponly=httponly, + domain=domain, + path=path, + secure=secure, + partitioned=partitioned, + samesite=samesite, + ) + response.vary.add("Cookie") diff --git a/backend/venv/Lib/site-packages/flask/signals.py b/backend/venv/Lib/site-packages/flask/signals.py new file mode 100644 index 0000000..444fda9 --- /dev/null +++ b/backend/venv/Lib/site-packages/flask/signals.py @@ -0,0 +1,17 @@ +from __future__ import annotations + +from blinker import Namespace + +# This namespace is only for signals provided by Flask itself. +_signals = Namespace() + +template_rendered = _signals.signal("template-rendered") +before_render_template = _signals.signal("before-render-template") +request_started = _signals.signal("request-started") +request_finished = _signals.signal("request-finished") +request_tearing_down = _signals.signal("request-tearing-down") +got_request_exception = _signals.signal("got-request-exception") +appcontext_tearing_down = _signals.signal("appcontext-tearing-down") +appcontext_pushed = _signals.signal("appcontext-pushed") +appcontext_popped = _signals.signal("appcontext-popped") +message_flashed = _signals.signal("message-flashed") diff --git a/backend/venv/Lib/site-packages/flask/templating.py b/backend/venv/Lib/site-packages/flask/templating.py new file mode 100644 index 0000000..16d480f --- /dev/null +++ b/backend/venv/Lib/site-packages/flask/templating.py @@ -0,0 +1,219 @@ +from __future__ import annotations + +import typing as t + +from jinja2 import BaseLoader +from jinja2 import Environment as BaseEnvironment +from jinja2 import Template +from jinja2 import TemplateNotFound + +from .globals import _cv_app +from .globals import _cv_request +from .globals import current_app +from .globals import request +from .helpers import stream_with_context +from .signals import before_render_template +from .signals import template_rendered + +if t.TYPE_CHECKING: # pragma: no cover + from .app import Flask + from .sansio.app import App + from .sansio.scaffold import Scaffold + + +def _default_template_ctx_processor() -> dict[str, t.Any]: + """Default template context processor. Injects `request`, + `session` and `g`. + """ + appctx = _cv_app.get(None) + reqctx = _cv_request.get(None) + rv: dict[str, t.Any] = {} + if appctx is not None: + rv["g"] = appctx.g + if reqctx is not None: + rv["request"] = reqctx.request + rv["session"] = reqctx.session + return rv + + +class Environment(BaseEnvironment): + """Works like a regular Jinja environment but has some additional + knowledge of how Flask's blueprint works so that it can prepend the + name of the blueprint to referenced templates if necessary. + """ + + def __init__(self, app: App, **options: t.Any) -> None: + if "loader" not in options: + options["loader"] = app.create_global_jinja_loader() + BaseEnvironment.__init__(self, **options) + self.app = app + + +class DispatchingJinjaLoader(BaseLoader): + """A loader that looks for templates in the application and all + the blueprint folders. + """ + + def __init__(self, app: App) -> None: + self.app = app + + def get_source( + self, environment: BaseEnvironment, template: str + ) -> tuple[str, str | None, t.Callable[[], bool] | None]: + if self.app.config["EXPLAIN_TEMPLATE_LOADING"]: + return self._get_source_explained(environment, template) + return self._get_source_fast(environment, template) + + def _get_source_explained( + self, environment: BaseEnvironment, template: str + ) -> tuple[str, str | None, t.Callable[[], bool] | None]: + attempts = [] + rv: tuple[str, str | None, t.Callable[[], bool] | None] | None + trv: None | (tuple[str, str | None, t.Callable[[], bool] | None]) = None + + for srcobj, loader in self._iter_loaders(template): + try: + rv = loader.get_source(environment, template) + if trv is None: + trv = rv + except TemplateNotFound: + rv = None + attempts.append((loader, srcobj, rv)) + + from .debughelpers import explain_template_loading_attempts + + explain_template_loading_attempts(self.app, template, attempts) + + if trv is not None: + return trv + raise TemplateNotFound(template) + + def _get_source_fast( + self, environment: BaseEnvironment, template: str + ) -> tuple[str, str | None, t.Callable[[], bool] | None]: + for _srcobj, loader in self._iter_loaders(template): + try: + return loader.get_source(environment, template) + except TemplateNotFound: + continue + raise TemplateNotFound(template) + + def _iter_loaders(self, template: str) -> t.Iterator[tuple[Scaffold, BaseLoader]]: + loader = self.app.jinja_loader + if loader is not None: + yield self.app, loader + + for blueprint in self.app.iter_blueprints(): + loader = blueprint.jinja_loader + if loader is not None: + yield blueprint, loader + + def list_templates(self) -> list[str]: + result = set() + loader = self.app.jinja_loader + if loader is not None: + result.update(loader.list_templates()) + + for blueprint in self.app.iter_blueprints(): + loader = blueprint.jinja_loader + if loader is not None: + for template in loader.list_templates(): + result.add(template) + + return list(result) + + +def _render(app: Flask, template: Template, context: dict[str, t.Any]) -> str: + app.update_template_context(context) + before_render_template.send( + app, _async_wrapper=app.ensure_sync, template=template, context=context + ) + rv = template.render(context) + template_rendered.send( + app, _async_wrapper=app.ensure_sync, template=template, context=context + ) + return rv + + +def render_template( + template_name_or_list: str | Template | list[str | Template], + **context: t.Any, +) -> str: + """Render a template by name with the given context. + + :param template_name_or_list: The name of the template to render. If + a list is given, the first name to exist will be rendered. + :param context: The variables to make available in the template. + """ + app = current_app._get_current_object() # type: ignore[attr-defined] + template = app.jinja_env.get_or_select_template(template_name_or_list) + return _render(app, template, context) + + +def render_template_string(source: str, **context: t.Any) -> str: + """Render a template from the given source string with the given + context. + + :param source: The source code of the template to render. + :param context: The variables to make available in the template. + """ + app = current_app._get_current_object() # type: ignore[attr-defined] + template = app.jinja_env.from_string(source) + return _render(app, template, context) + + +def _stream( + app: Flask, template: Template, context: dict[str, t.Any] +) -> t.Iterator[str]: + app.update_template_context(context) + before_render_template.send( + app, _async_wrapper=app.ensure_sync, template=template, context=context + ) + + def generate() -> t.Iterator[str]: + yield from template.generate(context) + template_rendered.send( + app, _async_wrapper=app.ensure_sync, template=template, context=context + ) + + rv = generate() + + # If a request context is active, keep it while generating. + if request: + rv = stream_with_context(rv) + + return rv + + +def stream_template( + template_name_or_list: str | Template | list[str | Template], + **context: t.Any, +) -> t.Iterator[str]: + """Render a template by name with the given context as a stream. + This returns an iterator of strings, which can be used as a + streaming response from a view. + + :param template_name_or_list: The name of the template to render. If + a list is given, the first name to exist will be rendered. + :param context: The variables to make available in the template. + + .. versionadded:: 2.2 + """ + app = current_app._get_current_object() # type: ignore[attr-defined] + template = app.jinja_env.get_or_select_template(template_name_or_list) + return _stream(app, template, context) + + +def stream_template_string(source: str, **context: t.Any) -> t.Iterator[str]: + """Render a template from the given source string with the given + context as a stream. This returns an iterator of strings, which can + be used as a streaming response from a view. + + :param source: The source code of the template to render. + :param context: The variables to make available in the template. + + .. versionadded:: 2.2 + """ + app = current_app._get_current_object() # type: ignore[attr-defined] + template = app.jinja_env.from_string(source) + return _stream(app, template, context) diff --git a/backend/venv/Lib/site-packages/flask/testing.py b/backend/venv/Lib/site-packages/flask/testing.py new file mode 100644 index 0000000..55eb12f --- /dev/null +++ b/backend/venv/Lib/site-packages/flask/testing.py @@ -0,0 +1,298 @@ +from __future__ import annotations + +import importlib.metadata +import typing as t +from contextlib import contextmanager +from contextlib import ExitStack +from copy import copy +from types import TracebackType +from urllib.parse import urlsplit + +import werkzeug.test +from click.testing import CliRunner +from click.testing import Result +from werkzeug.test import Client +from werkzeug.wrappers import Request as BaseRequest + +from .cli import ScriptInfo +from .sessions import SessionMixin + +if t.TYPE_CHECKING: # pragma: no cover + from _typeshed.wsgi import WSGIEnvironment + from werkzeug.test import TestResponse + + from .app import Flask + + +class EnvironBuilder(werkzeug.test.EnvironBuilder): + """An :class:`~werkzeug.test.EnvironBuilder`, that takes defaults from the + application. + + :param app: The Flask application to configure the environment from. + :param path: URL path being requested. + :param base_url: Base URL where the app is being served, which + ``path`` is relative to. If not given, built from + :data:`PREFERRED_URL_SCHEME`, ``subdomain``, + :data:`SERVER_NAME`, and :data:`APPLICATION_ROOT`. + :param subdomain: Subdomain name to append to :data:`SERVER_NAME`. + :param url_scheme: Scheme to use instead of + :data:`PREFERRED_URL_SCHEME`. + :param json: If given, this is serialized as JSON and passed as + ``data``. Also defaults ``content_type`` to + ``application/json``. + :param args: other positional arguments passed to + :class:`~werkzeug.test.EnvironBuilder`. + :param kwargs: other keyword arguments passed to + :class:`~werkzeug.test.EnvironBuilder`. + """ + + def __init__( + self, + app: Flask, + path: str = "/", + base_url: str | None = None, + subdomain: str | None = None, + url_scheme: str | None = None, + *args: t.Any, + **kwargs: t.Any, + ) -> None: + assert not (base_url or subdomain or url_scheme) or ( + base_url is not None + ) != bool(subdomain or url_scheme), ( + 'Cannot pass "subdomain" or "url_scheme" with "base_url".' + ) + + if base_url is None: + http_host = app.config.get("SERVER_NAME") or "localhost" + app_root = app.config["APPLICATION_ROOT"] + + if subdomain: + http_host = f"{subdomain}.{http_host}" + + if url_scheme is None: + url_scheme = app.config["PREFERRED_URL_SCHEME"] + + url = urlsplit(path) + base_url = ( + f"{url.scheme or url_scheme}://{url.netloc or http_host}" + f"/{app_root.lstrip('/')}" + ) + path = url.path + + if url.query: + path = f"{path}?{url.query}" + + self.app = app + super().__init__(path, base_url, *args, **kwargs) + + def json_dumps(self, obj: t.Any, **kwargs: t.Any) -> str: + """Serialize ``obj`` to a JSON-formatted string. + + The serialization will be configured according to the config associated + with this EnvironBuilder's ``app``. + """ + return self.app.json.dumps(obj, **kwargs) + + +_werkzeug_version = "" + + +def _get_werkzeug_version() -> str: + global _werkzeug_version + + if not _werkzeug_version: + _werkzeug_version = importlib.metadata.version("werkzeug") + + return _werkzeug_version + + +class FlaskClient(Client): + """Works like a regular Werkzeug test client but has knowledge about + Flask's contexts to defer the cleanup of the request context until + the end of a ``with`` block. For general information about how to + use this class refer to :class:`werkzeug.test.Client`. + + .. versionchanged:: 0.12 + `app.test_client()` includes preset default environment, which can be + set after instantiation of the `app.test_client()` object in + `client.environ_base`. + + Basic usage is outlined in the :doc:`/testing` chapter. + """ + + application: Flask + + def __init__(self, *args: t.Any, **kwargs: t.Any) -> None: + super().__init__(*args, **kwargs) + self.preserve_context = False + self._new_contexts: list[t.ContextManager[t.Any]] = [] + self._context_stack = ExitStack() + self.environ_base = { + "REMOTE_ADDR": "127.0.0.1", + "HTTP_USER_AGENT": f"Werkzeug/{_get_werkzeug_version()}", + } + + @contextmanager + def session_transaction( + self, *args: t.Any, **kwargs: t.Any + ) -> t.Iterator[SessionMixin]: + """When used in combination with a ``with`` statement this opens a + session transaction. This can be used to modify the session that + the test client uses. Once the ``with`` block is left the session is + stored back. + + :: + + with client.session_transaction() as session: + session['value'] = 42 + + Internally this is implemented by going through a temporary test + request context and since session handling could depend on + request variables this function accepts the same arguments as + :meth:`~flask.Flask.test_request_context` which are directly + passed through. + """ + if self._cookies is None: + raise TypeError( + "Cookies are disabled. Create a client with 'use_cookies=True'." + ) + + app = self.application + ctx = app.test_request_context(*args, **kwargs) + self._add_cookies_to_wsgi(ctx.request.environ) + + with ctx: + sess = app.session_interface.open_session(app, ctx.request) + + if sess is None: + raise RuntimeError("Session backend did not open a session.") + + yield sess + resp = app.response_class() + + if app.session_interface.is_null_session(sess): + return + + with ctx: + app.session_interface.save_session(app, sess, resp) + + self._update_cookies_from_response( + ctx.request.host.partition(":")[0], + ctx.request.path, + resp.headers.getlist("Set-Cookie"), + ) + + def _copy_environ(self, other: WSGIEnvironment) -> WSGIEnvironment: + out = {**self.environ_base, **other} + + if self.preserve_context: + out["werkzeug.debug.preserve_context"] = self._new_contexts.append + + return out + + def _request_from_builder_args( + self, args: tuple[t.Any, ...], kwargs: dict[str, t.Any] + ) -> BaseRequest: + kwargs["environ_base"] = self._copy_environ(kwargs.get("environ_base", {})) + builder = EnvironBuilder(self.application, *args, **kwargs) + + try: + return builder.get_request() + finally: + builder.close() + + def open( + self, + *args: t.Any, + buffered: bool = False, + follow_redirects: bool = False, + **kwargs: t.Any, + ) -> TestResponse: + if args and isinstance( + args[0], (werkzeug.test.EnvironBuilder, dict, BaseRequest) + ): + if isinstance(args[0], werkzeug.test.EnvironBuilder): + builder = copy(args[0]) + builder.environ_base = self._copy_environ(builder.environ_base or {}) # type: ignore[arg-type] + request = builder.get_request() + elif isinstance(args[0], dict): + request = EnvironBuilder.from_environ( + args[0], app=self.application, environ_base=self._copy_environ({}) + ).get_request() + else: + # isinstance(args[0], BaseRequest) + request = copy(args[0]) + request.environ = self._copy_environ(request.environ) + else: + # request is None + request = self._request_from_builder_args(args, kwargs) + + # Pop any previously preserved contexts. This prevents contexts + # from being preserved across redirects or multiple requests + # within a single block. + self._context_stack.close() + + response = super().open( + request, + buffered=buffered, + follow_redirects=follow_redirects, + ) + response.json_module = self.application.json # type: ignore[assignment] + + # Re-push contexts that were preserved during the request. + for cm in self._new_contexts: + self._context_stack.enter_context(cm) + + self._new_contexts.clear() + return response + + def __enter__(self) -> FlaskClient: + if self.preserve_context: + raise RuntimeError("Cannot nest client invocations") + self.preserve_context = True + return self + + def __exit__( + self, + exc_type: type | None, + exc_value: BaseException | None, + tb: TracebackType | None, + ) -> None: + self.preserve_context = False + self._context_stack.close() + + +class FlaskCliRunner(CliRunner): + """A :class:`~click.testing.CliRunner` for testing a Flask app's + CLI commands. Typically created using + :meth:`~flask.Flask.test_cli_runner`. See :ref:`testing-cli`. + """ + + def __init__(self, app: Flask, **kwargs: t.Any) -> None: + self.app = app + super().__init__(**kwargs) + + def invoke( # type: ignore + self, cli: t.Any = None, args: t.Any = None, **kwargs: t.Any + ) -> Result: + """Invokes a CLI command in an isolated environment. See + :meth:`CliRunner.invoke ` for + full method documentation. See :ref:`testing-cli` for examples. + + If the ``obj`` argument is not given, passes an instance of + :class:`~flask.cli.ScriptInfo` that knows how to load the Flask + app being tested. + + :param cli: Command object to invoke. Default is the app's + :attr:`~flask.app.Flask.cli` group. + :param args: List of strings to invoke the command with. + + :return: a :class:`~click.testing.Result` object. + """ + if cli is None: + cli = self.app.cli + + if "obj" not in kwargs: + kwargs["obj"] = ScriptInfo(create_app=lambda: self.app) + + return super().invoke(cli, args, **kwargs) diff --git a/backend/venv/Lib/site-packages/flask/typing.py b/backend/venv/Lib/site-packages/flask/typing.py new file mode 100644 index 0000000..6b70c40 --- /dev/null +++ b/backend/venv/Lib/site-packages/flask/typing.py @@ -0,0 +1,93 @@ +from __future__ import annotations + +import collections.abc as cabc +import typing as t + +if t.TYPE_CHECKING: # pragma: no cover + from _typeshed.wsgi import WSGIApplication # noqa: F401 + from werkzeug.datastructures import Headers # noqa: F401 + from werkzeug.sansio.response import Response # noqa: F401 + +# The possible types that are directly convertible or are a Response object. +ResponseValue = t.Union[ + "Response", + str, + bytes, + list[t.Any], + # Only dict is actually accepted, but Mapping allows for TypedDict. + t.Mapping[str, t.Any], + t.Iterator[str], + t.Iterator[bytes], + cabc.AsyncIterable[str], # for Quart, until App is generic. + cabc.AsyncIterable[bytes], +] + +# the possible types for an individual HTTP header +# This should be a Union, but mypy doesn't pass unless it's a TypeVar. +HeaderValue = t.Union[str, list[str], tuple[str, ...]] + +# the possible types for HTTP headers +HeadersValue = t.Union[ + "Headers", + t.Mapping[str, HeaderValue], + t.Sequence[tuple[str, HeaderValue]], +] + +# The possible types returned by a route function. +ResponseReturnValue = t.Union[ + ResponseValue, + tuple[ResponseValue, HeadersValue], + tuple[ResponseValue, int], + tuple[ResponseValue, int, HeadersValue], + "WSGIApplication", +] + +# Allow any subclass of werkzeug.Response, such as the one from Flask, +# as a callback argument. Using werkzeug.Response directly makes a +# callback annotated with flask.Response fail type checking. +ResponseClass = t.TypeVar("ResponseClass", bound="Response") + +AppOrBlueprintKey = t.Optional[str] # The App key is None, whereas blueprints are named +AfterRequestCallable = t.Union[ + t.Callable[[ResponseClass], ResponseClass], + t.Callable[[ResponseClass], t.Awaitable[ResponseClass]], +] +BeforeFirstRequestCallable = t.Union[ + t.Callable[[], None], t.Callable[[], t.Awaitable[None]] +] +BeforeRequestCallable = t.Union[ + t.Callable[[], t.Optional[ResponseReturnValue]], + t.Callable[[], t.Awaitable[t.Optional[ResponseReturnValue]]], +] +ShellContextProcessorCallable = t.Callable[[], dict[str, t.Any]] +TeardownCallable = t.Union[ + t.Callable[[t.Optional[BaseException]], None], + t.Callable[[t.Optional[BaseException]], t.Awaitable[None]], +] +TemplateContextProcessorCallable = t.Union[ + t.Callable[[], dict[str, t.Any]], + t.Callable[[], t.Awaitable[dict[str, t.Any]]], +] +TemplateFilterCallable = t.Callable[..., t.Any] +TemplateGlobalCallable = t.Callable[..., t.Any] +TemplateTestCallable = t.Callable[..., bool] +URLDefaultCallable = t.Callable[[str, dict[str, t.Any]], None] +URLValuePreprocessorCallable = t.Callable[ + [t.Optional[str], t.Optional[dict[str, t.Any]]], None +] + +# This should take Exception, but that either breaks typing the argument +# with a specific exception, or decorating multiple times with different +# exceptions (and using a union type on the argument). +# https://github.com/pallets/flask/issues/4095 +# https://github.com/pallets/flask/issues/4295 +# https://github.com/pallets/flask/issues/4297 +ErrorHandlerCallable = t.Union[ + t.Callable[[t.Any], ResponseReturnValue], + t.Callable[[t.Any], t.Awaitable[ResponseReturnValue]], +] + +RouteCallable = t.Union[ + t.Callable[..., ResponseReturnValue], + t.Callable[..., t.Awaitable[ResponseReturnValue]], +] diff --git a/backend/venv/Lib/site-packages/flask/views.py b/backend/venv/Lib/site-packages/flask/views.py new file mode 100644 index 0000000..53fe976 --- /dev/null +++ b/backend/venv/Lib/site-packages/flask/views.py @@ -0,0 +1,191 @@ +from __future__ import annotations + +import typing as t + +from . import typing as ft +from .globals import current_app +from .globals import request + +F = t.TypeVar("F", bound=t.Callable[..., t.Any]) + +http_method_funcs = frozenset( + ["get", "post", "head", "options", "delete", "put", "trace", "patch"] +) + + +class View: + """Subclass this class and override :meth:`dispatch_request` to + create a generic class-based view. Call :meth:`as_view` to create a + view function that creates an instance of the class with the given + arguments and calls its ``dispatch_request`` method with any URL + variables. + + See :doc:`views` for a detailed guide. + + .. code-block:: python + + class Hello(View): + init_every_request = False + + def dispatch_request(self, name): + return f"Hello, {name}!" + + app.add_url_rule( + "/hello/", view_func=Hello.as_view("hello") + ) + + Set :attr:`methods` on the class to change what methods the view + accepts. + + Set :attr:`decorators` on the class to apply a list of decorators to + the generated view function. Decorators applied to the class itself + will not be applied to the generated view function! + + Set :attr:`init_every_request` to ``False`` for efficiency, unless + you need to store request-global data on ``self``. + """ + + #: The methods this view is registered for. Uses the same default + #: (``["GET", "HEAD", "OPTIONS"]``) as ``route`` and + #: ``add_url_rule`` by default. + methods: t.ClassVar[t.Collection[str] | None] = None + + #: Control whether the ``OPTIONS`` method is handled automatically. + #: Uses the same default (``True``) as ``route`` and + #: ``add_url_rule`` by default. + provide_automatic_options: t.ClassVar[bool | None] = None + + #: A list of decorators to apply, in order, to the generated view + #: function. Remember that ``@decorator`` syntax is applied bottom + #: to top, so the first decorator in the list would be the bottom + #: decorator. + #: + #: .. versionadded:: 0.8 + decorators: t.ClassVar[list[t.Callable[..., t.Any]]] = [] + + #: Create a new instance of this view class for every request by + #: default. If a view subclass sets this to ``False``, the same + #: instance is used for every request. + #: + #: A single instance is more efficient, especially if complex setup + #: is done during init. However, storing data on ``self`` is no + #: longer safe across requests, and :data:`~flask.g` should be used + #: instead. + #: + #: .. versionadded:: 2.2 + init_every_request: t.ClassVar[bool] = True + + def dispatch_request(self) -> ft.ResponseReturnValue: + """The actual view function behavior. Subclasses must override + this and return a valid response. Any variables from the URL + rule are passed as keyword arguments. + """ + raise NotImplementedError() + + @classmethod + def as_view( + cls, name: str, *class_args: t.Any, **class_kwargs: t.Any + ) -> ft.RouteCallable: + """Convert the class into a view function that can be registered + for a route. + + By default, the generated view will create a new instance of the + view class for every request and call its + :meth:`dispatch_request` method. If the view class sets + :attr:`init_every_request` to ``False``, the same instance will + be used for every request. + + Except for ``name``, all other arguments passed to this method + are forwarded to the view class ``__init__`` method. + + .. versionchanged:: 2.2 + Added the ``init_every_request`` class attribute. + """ + if cls.init_every_request: + + def view(**kwargs: t.Any) -> ft.ResponseReturnValue: + self = view.view_class( # type: ignore[attr-defined] + *class_args, **class_kwargs + ) + return current_app.ensure_sync(self.dispatch_request)(**kwargs) # type: ignore[no-any-return] + + else: + self = cls(*class_args, **class_kwargs) # pyright: ignore + + def view(**kwargs: t.Any) -> ft.ResponseReturnValue: + return current_app.ensure_sync(self.dispatch_request)(**kwargs) # type: ignore[no-any-return] + + if cls.decorators: + view.__name__ = name + view.__module__ = cls.__module__ + for decorator in cls.decorators: + view = decorator(view) + + # We attach the view class to the view function for two reasons: + # first of all it allows us to easily figure out what class-based + # view this thing came from, secondly it's also used for instantiating + # the view class so you can actually replace it with something else + # for testing purposes and debugging. + view.view_class = cls # type: ignore + view.__name__ = name + view.__doc__ = cls.__doc__ + view.__module__ = cls.__module__ + view.methods = cls.methods # type: ignore + view.provide_automatic_options = cls.provide_automatic_options # type: ignore + return view + + +class MethodView(View): + """Dispatches request methods to the corresponding instance methods. + For example, if you implement a ``get`` method, it will be used to + handle ``GET`` requests. + + This can be useful for defining a REST API. + + :attr:`methods` is automatically set based on the methods defined on + the class. + + See :doc:`views` for a detailed guide. + + .. code-block:: python + + class CounterAPI(MethodView): + def get(self): + return str(session.get("counter", 0)) + + def post(self): + session["counter"] = session.get("counter", 0) + 1 + return redirect(url_for("counter")) + + app.add_url_rule( + "/counter", view_func=CounterAPI.as_view("counter") + ) + """ + + def __init_subclass__(cls, **kwargs: t.Any) -> None: + super().__init_subclass__(**kwargs) + + if "methods" not in cls.__dict__: + methods = set() + + for base in cls.__bases__: + if getattr(base, "methods", None): + methods.update(base.methods) # type: ignore[attr-defined] + + for key in http_method_funcs: + if hasattr(cls, key): + methods.add(key.upper()) + + if methods: + cls.methods = methods + + def dispatch_request(self, **kwargs: t.Any) -> ft.ResponseReturnValue: + meth = getattr(self, request.method.lower(), None) + + # If the request method is HEAD and we don't have a handler for it + # retry with GET. + if meth is None and request.method == "HEAD": + meth = getattr(self, "get", None) + + assert meth is not None, f"Unimplemented method {request.method!r}" + return current_app.ensure_sync(meth)(**kwargs) # type: ignore[no-any-return] diff --git a/backend/venv/Lib/site-packages/flask/wrappers.py b/backend/venv/Lib/site-packages/flask/wrappers.py new file mode 100644 index 0000000..bab6102 --- /dev/null +++ b/backend/venv/Lib/site-packages/flask/wrappers.py @@ -0,0 +1,257 @@ +from __future__ import annotations + +import typing as t + +from werkzeug.exceptions import BadRequest +from werkzeug.exceptions import HTTPException +from werkzeug.wrappers import Request as RequestBase +from werkzeug.wrappers import Response as ResponseBase + +from . import json +from .globals import current_app +from .helpers import _split_blueprint_path + +if t.TYPE_CHECKING: # pragma: no cover + from werkzeug.routing import Rule + + +class Request(RequestBase): + """The request object used by default in Flask. Remembers the + matched endpoint and view arguments. + + It is what ends up as :class:`~flask.request`. If you want to replace + the request object used you can subclass this and set + :attr:`~flask.Flask.request_class` to your subclass. + + The request object is a :class:`~werkzeug.wrappers.Request` subclass and + provides all of the attributes Werkzeug defines plus a few Flask + specific ones. + """ + + json_module: t.Any = json + + #: The internal URL rule that matched the request. This can be + #: useful to inspect which methods are allowed for the URL from + #: a before/after handler (``request.url_rule.methods``) etc. + #: Though if the request's method was invalid for the URL rule, + #: the valid list is available in ``routing_exception.valid_methods`` + #: instead (an attribute of the Werkzeug exception + #: :exc:`~werkzeug.exceptions.MethodNotAllowed`) + #: because the request was never internally bound. + #: + #: .. versionadded:: 0.6 + url_rule: Rule | None = None + + #: A dict of view arguments that matched the request. If an exception + #: happened when matching, this will be ``None``. + view_args: dict[str, t.Any] | None = None + + #: If matching the URL failed, this is the exception that will be + #: raised / was raised as part of the request handling. This is + #: usually a :exc:`~werkzeug.exceptions.NotFound` exception or + #: something similar. + routing_exception: HTTPException | None = None + + _max_content_length: int | None = None + _max_form_memory_size: int | None = None + _max_form_parts: int | None = None + + @property + def max_content_length(self) -> int | None: + """The maximum number of bytes that will be read during this request. If + this limit is exceeded, a 413 :exc:`~werkzeug.exceptions.RequestEntityTooLarge` + error is raised. If it is set to ``None``, no limit is enforced at the + Flask application level. However, if it is ``None`` and the request has + no ``Content-Length`` header and the WSGI server does not indicate that + it terminates the stream, then no data is read to avoid an infinite + stream. + + Each request defaults to the :data:`MAX_CONTENT_LENGTH` config, which + defaults to ``None``. It can be set on a specific ``request`` to apply + the limit to that specific view. This should be set appropriately based + on an application's or view's specific needs. + + .. versionchanged:: 3.1 + This can be set per-request. + + .. versionchanged:: 0.6 + This is configurable through Flask config. + """ + if self._max_content_length is not None: + return self._max_content_length + + if not current_app: + return super().max_content_length + + return current_app.config["MAX_CONTENT_LENGTH"] # type: ignore[no-any-return] + + @max_content_length.setter + def max_content_length(self, value: int | None) -> None: + self._max_content_length = value + + @property + def max_form_memory_size(self) -> int | None: + """The maximum size in bytes any non-file form field may be in a + ``multipart/form-data`` body. If this limit is exceeded, a 413 + :exc:`~werkzeug.exceptions.RequestEntityTooLarge` error is raised. If it + is set to ``None``, no limit is enforced at the Flask application level. + + Each request defaults to the :data:`MAX_FORM_MEMORY_SIZE` config, which + defaults to ``500_000``. It can be set on a specific ``request`` to + apply the limit to that specific view. This should be set appropriately + based on an application's or view's specific needs. + + .. versionchanged:: 3.1 + This is configurable through Flask config. + """ + if self._max_form_memory_size is not None: + return self._max_form_memory_size + + if not current_app: + return super().max_form_memory_size + + return current_app.config["MAX_FORM_MEMORY_SIZE"] # type: ignore[no-any-return] + + @max_form_memory_size.setter + def max_form_memory_size(self, value: int | None) -> None: + self._max_form_memory_size = value + + @property # type: ignore[override] + def max_form_parts(self) -> int | None: + """The maximum number of fields that may be present in a + ``multipart/form-data`` body. If this limit is exceeded, a 413 + :exc:`~werkzeug.exceptions.RequestEntityTooLarge` error is raised. If it + is set to ``None``, no limit is enforced at the Flask application level. + + Each request defaults to the :data:`MAX_FORM_PARTS` config, which + defaults to ``1_000``. It can be set on a specific ``request`` to apply + the limit to that specific view. This should be set appropriately based + on an application's or view's specific needs. + + .. versionchanged:: 3.1 + This is configurable through Flask config. + """ + if self._max_form_parts is not None: + return self._max_form_parts + + if not current_app: + return super().max_form_parts + + return current_app.config["MAX_FORM_PARTS"] # type: ignore[no-any-return] + + @max_form_parts.setter + def max_form_parts(self, value: int | None) -> None: + self._max_form_parts = value + + @property + def endpoint(self) -> str | None: + """The endpoint that matched the request URL. + + This will be ``None`` if matching failed or has not been + performed yet. + + This in combination with :attr:`view_args` can be used to + reconstruct the same URL or a modified URL. + """ + if self.url_rule is not None: + return self.url_rule.endpoint # type: ignore[no-any-return] + + return None + + @property + def blueprint(self) -> str | None: + """The registered name of the current blueprint. + + This will be ``None`` if the endpoint is not part of a + blueprint, or if URL matching failed or has not been performed + yet. + + This does not necessarily match the name the blueprint was + created with. It may have been nested, or registered with a + different name. + """ + endpoint = self.endpoint + + if endpoint is not None and "." in endpoint: + return endpoint.rpartition(".")[0] + + return None + + @property + def blueprints(self) -> list[str]: + """The registered names of the current blueprint upwards through + parent blueprints. + + This will be an empty list if there is no current blueprint, or + if URL matching failed. + + .. versionadded:: 2.0.1 + """ + name = self.blueprint + + if name is None: + return [] + + return _split_blueprint_path(name) + + def _load_form_data(self) -> None: + super()._load_form_data() + + # In debug mode we're replacing the files multidict with an ad-hoc + # subclass that raises a different error for key errors. + if ( + current_app + and current_app.debug + and self.mimetype != "multipart/form-data" + and not self.files + ): + from .debughelpers import attach_enctype_error_multidict + + attach_enctype_error_multidict(self) + + def on_json_loading_failed(self, e: ValueError | None) -> t.Any: + try: + return super().on_json_loading_failed(e) + except BadRequest as ebr: + if current_app and current_app.debug: + raise + + raise BadRequest() from ebr + + +class Response(ResponseBase): + """The response object that is used by default in Flask. Works like the + response object from Werkzeug but is set to have an HTML mimetype by + default. Quite often you don't have to create this object yourself because + :meth:`~flask.Flask.make_response` will take care of that for you. + + If you want to replace the response object used you can subclass this and + set :attr:`~flask.Flask.response_class` to your subclass. + + .. versionchanged:: 1.0 + JSON support is added to the response, like the request. This is useful + when testing to get the test client response data as JSON. + + .. versionchanged:: 1.0 + + Added :attr:`max_cookie_size`. + """ + + default_mimetype: str | None = "text/html" + + json_module = json + + autocorrect_location_header = False + + @property + def max_cookie_size(self) -> int: # type: ignore + """Read-only view of the :data:`MAX_COOKIE_SIZE` config key. + + See :attr:`~werkzeug.wrappers.Response.max_cookie_size` in + Werkzeug's docs. + """ + if current_app: + return current_app.config["MAX_COOKIE_SIZE"] # type: ignore[no-any-return] + + # return Werkzeug's default when not in an app context + return super().max_cookie_size diff --git a/backend/venv/Lib/site-packages/flask_cors-6.0.1.dist-info/INSTALLER b/backend/venv/Lib/site-packages/flask_cors-6.0.1.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/backend/venv/Lib/site-packages/flask_cors-6.0.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/backend/venv/Lib/site-packages/flask_cors-6.0.1.dist-info/METADATA b/backend/venv/Lib/site-packages/flask_cors-6.0.1.dist-info/METADATA new file mode 100644 index 0000000..786a01c --- /dev/null +++ b/backend/venv/Lib/site-packages/flask_cors-6.0.1.dist-info/METADATA @@ -0,0 +1,143 @@ +Metadata-Version: 2.4 +Name: flask-cors +Version: 6.0.1 +Summary: A Flask extension simplifying CORS support +Author-email: Cory Dolphin +Project-URL: Homepage, https://corydolphin.github.io/flask-cors/ +Project-URL: Repository, https://github.com/corydolphin/flask-cors +Project-URL: Documentation, https://corydolphin.github.io/flask-cors/ +Keywords: python +Classifier: Intended Audience :: Developers +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Classifier: Programming Language :: Python :: 3.13 +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Requires-Python: <4.0,>=3.9 +Description-Content-Type: text/x-rst +Requires-Dist: flask>=0.9 +Requires-Dist: Werkzeug>=0.7 + +Flask-CORS +========== + +|Build Status| |Latest Version| |Supported Python versions| +|License| + +A Flask extension for handling Cross Origin Resource Sharing (CORS), making cross-origin AJAX possible. + +This package has a simple philosophy: when you want to enable CORS, you wish to enable it for all use cases on a domain. +This means no mucking around with different allowed headers, methods, etc. + +By default, submission of cookies across domains is disabled due to the security implications. +Please see the documentation for how to enable credential'ed requests, and please make sure you add some sort of `CSRF `__ protection before doing so! + +Installation +------------ + +Install the extension with using pip, or easy\_install. + +.. code:: bash + + $ pip install -U flask-cors + +Usage +----- + +This package exposes a Flask extension which by default enables CORS support on all routes, for all origins and methods. +It allows parameterization of all CORS headers on a per-resource level. +The package also contains a decorator, for those who prefer this approach. + +Simple Usage +~~~~~~~~~~~~ + +In the simplest case, initialize the Flask-Cors extension with default arguments in order to allow CORS for all domains on all routes. +See the full list of options in the `documentation `__. + +.. code:: python + + + from flask import Flask + from flask_cors import CORS + + app = Flask(__name__) + CORS(app) + + @app.route("/") + def helloWorld(): + return "Hello, cross-origin-world!" + +Resource specific CORS +^^^^^^^^^^^^^^^^^^^^^^ + +Alternatively, you can specify CORS options on a resource and origin level of granularity by passing a dictionary as the `resources` option, mapping paths to a set of options. +See the full list of options in the `documentation `__. + +.. code:: python + + app = Flask(__name__) + cors = CORS(app, resources={r"/api/*": {"origins": "*"}}) + + @app.route("/api/v1/users") + def list_users(): + return "user example" + +Route specific CORS via decorator +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This extension also exposes a simple decorator to decorate flask routes with. +Simply add ``@cross_origin()`` below a call to Flask's ``@app.route(..)`` to allow CORS on a given route. +See the full list of options in the `decorator documentation `__. + +.. code:: python + + @app.route("/") + @cross_origin() + def helloWorld(): + return "Hello, cross-origin-world!" + +Documentation +------------- + +For a full list of options, please see the full `documentation `__ + +Troubleshooting +--------------- + +If things aren't working as you expect, enable logging to help understand what is going on under the hood, and why. + +.. code:: python + + logging.getLogger('flask_cors').level = logging.DEBUG + + + +Set Up Your Development Environment +--- +The development environment uses `uv` for Python version management as well as dependency management. +There are helpful Makefile targets to do everything you need. Use `make test` to get started! + + +Contributing +------------ + +Questions, comments or improvements? +Please create an issue on `Github `__, tweet at `@corydolphin `__ or send me an email. +I do my best to include every contribution proposed in any way that I can. + +Credits +------- + +This Flask extension is based upon the `Decorator for the HTTP Access Control `__ written by Armin Ronacher. + +.. |Build Status| image:: https://github.com/corydolphin/flask-cors/actions/workflows/unittests.yaml/badge.svg + :target: https://travis-ci.org/corydolphin/flask-cors +.. |Latest Version| image:: https://img.shields.io/pypi/v/Flask-Cors.svg + :target: https://pypi.python.org/pypi/Flask-Cors/ +.. |Supported Python versions| image:: https://img.shields.io/pypi/pyversions/Flask-Cors.svg + :target: https://img.shields.io/pypi/pyversions/Flask-Cors.svg +.. |License| image:: http://img.shields.io/:license-mit-blue.svg + :target: https://pypi.python.org/pypi/Flask-Cors/ diff --git a/backend/venv/Lib/site-packages/flask_cors-6.0.1.dist-info/RECORD b/backend/venv/Lib/site-packages/flask_cors-6.0.1.dist-info/RECORD new file mode 100644 index 0000000..07553af --- /dev/null +++ b/backend/venv/Lib/site-packages/flask_cors-6.0.1.dist-info/RECORD @@ -0,0 +1,16 @@ +flask_cors-6.0.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +flask_cors-6.0.1.dist-info/METADATA,sha256=vdM_HWOTtWgELoF6BIMIUN4R-VH0ACm8zKIxqyFfuUk,5303 +flask_cors-6.0.1.dist-info/RECORD,, +flask_cors-6.0.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +flask_cors-6.0.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91 +flask_cors-6.0.1.dist-info/top_level.txt,sha256=aWye_0QNZPp_QtPF4ZluLHqnyVLT9CPJsfiGhwqkWuo,11 +flask_cors/__init__.py,sha256=Hnwpy4nxEz4tlcB3enWNXUBctcjgxRnUqa5B5zDabQ4,522 +flask_cors/__pycache__/__init__.cpython-312.pyc,, +flask_cors/__pycache__/core.cpython-312.pyc,, +flask_cors/__pycache__/decorator.cpython-312.pyc,, +flask_cors/__pycache__/extension.cpython-312.pyc,, +flask_cors/__pycache__/version.cpython-312.pyc,, +flask_cors/core.py,sha256=S8Wv7dz9e0FcR386TkBT-T8_VRsjFQGhNiR0jIpUYiY,14416 +flask_cors/decorator.py,sha256=YnPIDyWAfz60t2yxLgoOZLzgWWjZEvxQAPTTV4qfsss,4706 +flask_cors/extension.py,sha256=ONk6eNJiYT7HPEtmmySG8KgjzvAs9xtcJHNYvWLAS9s,8268 +flask_cors/version.py,sha256=unmO3xtN2S1e9meUbIjG3AZVyKxUe4HSZNXDOcpZRJg,22 diff --git a/backend/venv/Lib/site-packages/flask_cors-6.0.1.dist-info/REQUESTED b/backend/venv/Lib/site-packages/flask_cors-6.0.1.dist-info/REQUESTED new file mode 100644 index 0000000..e69de29 diff --git a/backend/venv/Lib/site-packages/flask_cors-6.0.1.dist-info/WHEEL b/backend/venv/Lib/site-packages/flask_cors-6.0.1.dist-info/WHEEL new file mode 100644 index 0000000..e7fa31b --- /dev/null +++ b/backend/venv/Lib/site-packages/flask_cors-6.0.1.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: setuptools (80.9.0) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/backend/venv/Lib/site-packages/flask_cors-6.0.1.dist-info/top_level.txt b/backend/venv/Lib/site-packages/flask_cors-6.0.1.dist-info/top_level.txt new file mode 100644 index 0000000..27af988 --- /dev/null +++ b/backend/venv/Lib/site-packages/flask_cors-6.0.1.dist-info/top_level.txt @@ -0,0 +1 @@ +flask_cors diff --git a/backend/venv/Lib/site-packages/flask_cors/__init__.py b/backend/venv/Lib/site-packages/flask_cors/__init__.py new file mode 100644 index 0000000..732d401 --- /dev/null +++ b/backend/venv/Lib/site-packages/flask_cors/__init__.py @@ -0,0 +1,17 @@ +from .decorator import cross_origin +from .extension import CORS +from .version import __version__ + +__all__ = ["CORS", "__version__", "cross_origin"] + +# Set default logging handler to avoid "No handler found" warnings. +import logging +from logging import NullHandler + +# Set initial level to WARN. Users must manually enable logging for +# flask_cors to see our logging. +rootlogger = logging.getLogger(__name__) +rootlogger.addHandler(NullHandler()) + +if rootlogger.level == logging.NOTSET: + rootlogger.setLevel(logging.WARN) diff --git a/backend/venv/Lib/site-packages/flask_cors/__pycache__/__init__.cpython-312.pyc b/backend/venv/Lib/site-packages/flask_cors/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c9c395fd54133b6844b5c4efff85a8fd275ce261 GIT binary patch literal 773 zcmYLFO-tNR6uobfNn*xWTCw&+RHznb(XRnFr4))5x{#SNT7(dIMDrSBUXtM@j=B+- zT~@l#t_s~1e@a)=4@Lq5rCk)Eivc&Ki_)9vggnT-=iZ!q&U^QxVd#M8*YBTOdI{i1 zR^&$>f{VWhj==$ka0rM=NQO(i6iB8tz!H~(vRNkJf+N2trs9+xg{!8DS>&2fO;iPstEOIUZ7T8oht`W2pJUbT*J{4i2-&jm+RR#Jv7baOtJzq6zGCe%<}X^fj}~9FHtbEGg^tx` zVcS~qHmul7*qs)3ZI{K?OK!(L#n;C7DD^@wq4aKRKh+)uk+Z|uV{r|QvmM7<82S<+ zqzAWpaI*)q-}MKF>V*R2QV(YO8jQ`nTJIXu9b@`r@3XORsGot}g^3PK9Qkj8FEIB_ sGP=@uM;d>qk%4-bmH3;+NC literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/flask_cors/__pycache__/core.cpython-312.pyc b/backend/venv/Lib/site-packages/flask_cors/__pycache__/core.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e76589d80836b20d684138a574ae26995cb6ac59 GIT binary patch literal 15845 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 N{xZ3ss)wb){{mXP$a4Sy literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/flask_cors/__pycache__/extension.cpython-312.pyc b/backend/venv/Lib/site-packages/flask_cors/__pycache__/extension.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..49cad49019cefb898c228316731dd4400fa7040f GIT binary patch literal 8933 zcmcIpU2GfImA=D2Q4$r&wrods6Hn|U5(A2M6DKuPC$S>At`J4?TJi=^Wm6;0B{|Y? zhPiiW{geXSg@H&#uy(Kw+(#D(&;(v={g^KHA$d#D7ip!|3hM<5>@JD|``|!sx7nwj zbMM?CsUN4sq9cf$8QwYfobR0TopbN}vaPL!!0|tS`dwjIC*(izLLCwRWa}T`)Vi!Bo^#ny>djf4m# zGfyhvwQt&XSCdy0PlU(?V#aO|v*~Wgzt?WYZ;*+O1ufb9d%QK0)T&Ko=bf_aQ9Nbz zoigR#?@>lFR&D7Y7|x7d8oDqvQtil7FOzi{&$uPeavfgXk9Qc&)A>@SWOyEBPPM&c zFiznvcgrkGd9{P9#|qRiDdW|B9$Uy14KG_zPi3Wc^3zw9Y&{Lvx53N_%_I{cQ=15z zQ8Ro)n~0bZFe17T0u3VrqnE~vZ*&sUqQf!dSe|9r)*|Kl0CPFlN12tk9Q~57kj@JR zvz)x1bD8cHsBV->wv{!|qO?9Xr$oFviwBSD(tF*o-U0PNnoY z%PUAhrU`Sqj_&4kLr9qlP?*vI7NbZ3A~A^`{8IZtH)+mtKyO3mlv!{Bf&ksJZ7?AY zV1~yyLNByeGC+h^;HaAbRW}?{mo74Fdm$y2^cuBm;(BO0ug?{z12%9DatuV%w6f?IgDoV51}~=dH|fG0h=ggS zp92wMz)NYpzf{tt@T}|PtbCb?2nojNI8|Cl-7_ypv8U7eAk7(N+Y3fXg-0N_`cM_i z(=D!-AbhN88?9q{5r$hOxbPjV*E_l9QK43YzolDudkP~qXE6?HxC|VwPcMKePTnh| zgqR$2i@NPPdB}5gIWOQa?xhfQfivF4bS{>}02x*2kD|*xA%mA_*2-DgUDU=<0V^T& z+&KtJcuK_ew$yOS#c9eg!s|py%1}Y(rx3*wjeiD!@@#zp*X%da}vMf&vA@+S$NQ@JDj9Y}g?66LLH5QYsd^Hmcxm6KVi z!Vdwfi&Jog*Uj}=y1*eqz)g^(ySQ5V6XjvbBh=Rn8|XWDrd}puJv#>h&p~=Uq2Y7# zhni)m9_W-SJ0f+yPIKE5;UmHu0+?no>>!AcTXg(!JC&i%b&;MDxiD9-vOblTO1*QS zq^^<=#3{5fyai`d^Xt^&9x^?GiFvm}v7Lwp0AOnVf7DS#(5JtJbxs5-`Un+Yz|Y=Y z$VIY6pSMs#Z~OJLPlN^9K$(H80h&p>{NXatWjWdw=JI9=A5l*5$B7Kb426kA!3SRh zEu;egFiYgv9-f4{vanYO>RE%+UQQhj8Ga3@U0}{@p$U^y8%l@aKq7$=7N4#2TRN@l z4)SB4GzS9%52dGwe#^<)WrzlhRGux+q7ejq3Ajt|v2rK`m=!M0oJ!UvM^Q-Bjd!My zwtK(}2n}`z{MGLrFL++5@8n6_g*smVp6fev>eQ*@DP8=);TJk@6oIMJS+{unN^+{s zh?=*%U+5MPN+`@Q@E^1W1=rl>KY0@$Q10`G)yF1!5z|8&A_}SC zUXg);KaDK(VzS;kuG7mcG$nBUuC{#d!uj!({@wHagDL&u=op-jUK}499T|hm%W!qE ze|+G(DShz#@cHrcSL)1Gw)k4_8n2LyF0_e$OW4TH@@8PR%tK6jZsZ^cT+C#67|$>w z`Y#S4y%>U=@hUJ{l@{6D)dH;MuMyXg4WD$_Hmx3KfWY`K(jRp5Ey`KcHgyO3K<;}m z3t0gqS;k&P^esrcf&PjFkiDb>VHi|%wf)k^%hN>*+9;rXv1ZUsw`c&_)MZs_JMr(M@>i0`t162SlcIC? zVaFN)I%f^wXVXVZbRz*+@BsAv*au_QZg<05#(Zyoo+|L`FscRJwrmB}guX&IliHqv z9`}G-Sv}c`r(|TxS_#F<%&4Za52IyVM2l*o6qSn6xF*5;n|cA(dbM6Ouxh&M)2TG~Iy?8&(n6t$GE>dpHZE_#i^hH`Vy)t~l)QZ=*pw9D5CxK0Z~|oEw;p-tY

Pf zr@Nhz(1>6i9hwV3owy8#7Aj92=!Y=33T)h!n+$O1<6V|Du%DJ0fLG1%RobLM8}yP6SWr-N@P9q6`Xa5l=-f64F4* z_DL_vCboC`w0c2o0MyH`i^@jK|AvOax|RPeErSk2g4bx=P5^hX?w-KarJd-k0Ubzj zjJkSA<=R_jj_{t^m5^1_kC8pyCNq79(?pE;H4x&Y&Zs@(d-n*Ik&bJCk*wNP#689+ z{I|mY)@$%_n^Zy-l7TaMRJ0#-hDe3X)ISmYmeVX4|DpDenno7j?_+Hw8LGyEEz!6I z8;}`TS|r2O2&Z!WrYB*=MSDwd7m7BY%-IH?75lTW zQt@y-1{<2C1<)-cbjmEYAv>kjx(!FGt>M+iZPe`Ss02*Ye=aw^rWz z@rkuW&z(c-iJpgHk~q4B5Hz5OTipW11R(XU_HOfS;`v+8gsfyOa2~X|0^7cmF#A$;DOQO#%pR`9)J(b1`=R#^ zMaWV_j0+@KC}Cesg4e9(u0++0mDoRp-a7!#HsQ0L*xtucGi_>Y?b{4hf{k{KcNfVe^VM12b+vR+`lajqHI%*o>%6eD=n&w%nWxnb8~ZrMP!MNn6p(STN=!#BdyD z1BA98YOWP66WHUAKD2!-A$6nC+v32;UjXzpk_|7#mZEbF=gFp#YBLaqd;zd{0y=H6 zgNpmOqCg7b4+iw<&+%#}Hg52~pyXxfJbvLW_joplCzuxF25sHKw;msa-i6Fv4lRe5 zNiJ+^fP_}j#z->!Tn zm}9^U)Xb<&w#6ZlpNc@zXT??oe=VJ95S1}0$TvKf)kbU=^)r}&pMZ})T_;~0?focw zKmGbz`t{GWPfxF&yY%@hYv(Slr^nWhj<0r(v%@g%W0H(89ZuLY_ipzhsw|%TD|P=D6poqj)phd6khbr#_Ao}C>{;#T7Wz~>phGroS__6`f+0n)4*Wo` zR>Sc2iN(d)@aTnV)TGnpeD$dCP9tIp;c8pM{c01`GT7&4>{*m@(4P|5n052Eu>Clt zfCPP9ZSr>_S(ms{FTNshn^)U|u+9|9MZ;m}1qmhQnmz^WkH-%3@Zh90a2cNxj;iqr@(8ED?|gN+`O6k^ zMayX$ow>D1`io!~xJ zbge%%uo^$I8E?HG?^=s@tsY5j#CspcN#elGZ?AlN^>FV;-bU-`KSUyJJ&zKkPS9}l8#dk z_mRZQUu|`fgL&<%tvETF(Ks^C&$|ZtVxJv3G)Q7H6=PW2a5p8BskUS?Mb|7t#AK?8 zOy-@kVf(){WiqCl&14vIn*f|0$1@Cj=>(*5h95W!M<3rHUxxZa(fHPPBH?IqtL1of zN|O)Zum)DbE&-Wo3!_AE63JgD)kY-I5TQKbq7Y-dkXc#C7$3|?I?=oA+cxafrKg;}dqf`T@V1p&9f$J7q^;;VjB zjk`eI&#`X#Ru*=NgjB^3@DuM&>zBEByD94(R>H;35!W9H(X5_LwgOqn*XQgxu$7^I z8Fp{18$U2C7$Q=Q;LBi!4i((Ukae&|!Mvqvy90|^@pjzASMLQ;rsW&_YAcLTZLFX+ zzhFVhl4*kVVDVdzq1ReH+F1bq6&~gv!Ut5O-?p~jJiBsswea{%Ptbsr4f#m)n2y{K>V%@#Udg-+$1q z-#K``-c-+rK?eb3zK zyz~8yj+Zt&4nnEv=v;1n*hRWeJvv0%I^>+GjYRKe`+?wP{H&zJ*Vr2{7+Hw- z!NS<{Nwm~?3wG~|BcOtv?=XNBEGgJ LqX)I8g-L$~rxOfQ literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/flask_cors/__pycache__/version.cpython-312.pyc b/backend/venv/Lib/site-packages/flask_cors/__pycache__/version.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..72c4ac380d8bc0ba7be065b71ace57f7f06d2884 GIT binary patch literal 226 zcmX@j%ge<81aE#k&kzIBk3k$5V1zP0a{w9B8B!Rc7%CYxnW|XL^bGV2{WKYGamUA( zr4|)u=I6!7uVnZPQvWO6*(xTq7$_QJWME{J9pj&u>QayUl0@I9~|Hl zQ=XcdZ5mUQUtEx58k3ZmoSmAN5>u9%R~F-wnG{o;S(2(-02ED3Pc4o~%SkNGj!(`n uD%OWur&myUi^C>2KczG$)vkyQXfMdI#UQ_YU}j`wyul~h$X&z&G` literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/flask_cors/core.py b/backend/venv/Lib/site-packages/flask_cors/core.py new file mode 100644 index 0000000..8df343c --- /dev/null +++ b/backend/venv/Lib/site-packages/flask_cors/core.py @@ -0,0 +1,399 @@ +import logging +import re +from collections.abc import Iterable +from datetime import timedelta + +from flask import current_app, request +from werkzeug.datastructures import Headers, MultiDict + +LOG = logging.getLogger(__name__) + +# Response Headers +ACL_ORIGIN = "Access-Control-Allow-Origin" +ACL_METHODS = "Access-Control-Allow-Methods" +ACL_ALLOW_HEADERS = "Access-Control-Allow-Headers" +ACL_EXPOSE_HEADERS = "Access-Control-Expose-Headers" +ACL_CREDENTIALS = "Access-Control-Allow-Credentials" +ACL_MAX_AGE = "Access-Control-Max-Age" +ACL_RESPONSE_PRIVATE_NETWORK = "Access-Control-Allow-Private-Network" + +# Request Header +ACL_REQUEST_METHOD = "Access-Control-Request-Method" +ACL_REQUEST_HEADERS = "Access-Control-Request-Headers" +ACL_REQUEST_HEADER_PRIVATE_NETWORK = "Access-Control-Request-Private-Network" + +ALL_METHODS = ["GET", "HEAD", "POST", "OPTIONS", "PUT", "PATCH", "DELETE"] +CONFIG_OPTIONS = [ + "CORS_ORIGINS", + "CORS_METHODS", + "CORS_ALLOW_HEADERS", + "CORS_EXPOSE_HEADERS", + "CORS_SUPPORTS_CREDENTIALS", + "CORS_MAX_AGE", + "CORS_SEND_WILDCARD", + "CORS_AUTOMATIC_OPTIONS", + "CORS_VARY_HEADER", + "CORS_RESOURCES", + "CORS_INTERCEPT_EXCEPTIONS", + "CORS_ALWAYS_SEND", + "CORS_ALLOW_PRIVATE_NETWORK", +] +# Attribute added to request object by decorator to indicate that CORS +# was evaluated, in case the decorator and extension are both applied +# to a view. +FLASK_CORS_EVALUATED = "_FLASK_CORS_EVALUATED" + +# Strange, but this gets the type of a compiled regex, which is otherwise not +# exposed in a public API. +RegexObject = type(re.compile("")) +DEFAULT_OPTIONS = dict( + origins="*", + methods=ALL_METHODS, + allow_headers="*", + expose_headers=None, + supports_credentials=False, + max_age=None, + send_wildcard=False, + automatic_options=True, + vary_header=True, + resources=r"/*", + intercept_exceptions=True, + always_send=True, + allow_private_network=False, +) + + +def parse_resources(resources): + if isinstance(resources, dict): + # To make the API more consistent with the decorator, allow a + # resource of '*', which is not actually a valid regexp. + resources = [(re_fix(k), v) for k, v in resources.items()] + + # Sort patterns with static (literal) paths first, then by regex specificity + def sort_key(pair): + pattern, _ = pair + if isinstance(pattern, RegexObject): + return (1, 0, -pattern.pattern.count("/"), -len(pattern.pattern)) + elif probably_regex(pattern): + return (1, 1, -pattern.count("/"), -len(pattern)) + else: + return (0, 0, -pattern.count("/"), -len(pattern)) + + return sorted(resources, key=sort_key) + + elif isinstance(resources, str): + return [(re_fix(resources), {})] + + elif isinstance(resources, Iterable): + return [(re_fix(r), {}) for r in resources] + + # Type of compiled regex is not part of the public API. Test for this + # at runtime. + elif isinstance(resources, RegexObject): + return [(re_fix(resources), {})] + + else: + raise ValueError("Unexpected value for resources argument.") + + +def get_regexp_pattern(regexp): + """ + Helper that returns regexp pattern from given value. + + :param regexp: regular expression to stringify + :type regexp: _sre.SRE_Pattern or str + :returns: string representation of given regexp pattern + :rtype: str + """ + try: + return regexp.pattern + except AttributeError: + return str(regexp) + + +def get_cors_origins(options, request_origin): + origins = options.get("origins") + wildcard = r".*" in origins + + # If the Origin header is not present terminate this set of steps. + # The request is outside the scope of this specification.-- W3Spec + if request_origin: + LOG.debug("CORS request received with 'Origin' %s", request_origin) + + # If the allowed origins is an asterisk or 'wildcard', always match + if wildcard and options.get("send_wildcard"): + LOG.debug("Allowed origins are set to '*'. Sending wildcard CORS header.") + return ["*"] + # If the value of the Origin header is a case-insensitive match + # for any of the values in list of origins. + # NOTE: Per RFC 1035 and RFC 4343 schemes and hostnames are case insensitive. + elif try_match_any_pattern(request_origin, origins, caseSensitive=False): + LOG.debug( + "The request's Origin header matches. Sending CORS headers.", + ) + # Add a single Access-Control-Allow-Origin header, with either + # the value of the Origin header or the string "*" as value. + # -- W3Spec + return [request_origin] + else: + LOG.debug("The request's Origin header does not match any of allowed origins.") + return None + + elif options.get("always_send"): + if wildcard: + # If wildcard is in the origins, even if 'send_wildcard' is False, + # simply send the wildcard. Unless supports_credentials is True, + # since that is forbidden by the spec.. + # It is the most-likely to be correct thing to do (the only other + # option is to return nothing, which almost certainly not what + # the developer wants if the '*' origin was specified. + if options.get("supports_credentials"): + return None + else: + return ["*"] + else: + # Return all origins that are not regexes. + return sorted([o for o in origins if not probably_regex(o)]) + + # Terminate these steps, return the original request untouched. + else: + LOG.debug( + "The request did not contain an 'Origin' header. This means the browser or client did not request CORS, ensure the Origin Header is set." + ) + return None + + +def get_allow_headers(options, acl_request_headers): + if acl_request_headers: + request_headers = [h.strip() for h in acl_request_headers.split(",")] + + # any header that matches in the allow_headers + matching_headers = filter(lambda h: try_match_any_pattern(h, options.get("allow_headers"), caseSensitive=False), request_headers) + + return ", ".join(sorted(matching_headers)) + + return None + + +def get_cors_headers(options, request_headers, request_method): + origins_to_set = get_cors_origins(options, request_headers.get("Origin")) + headers = MultiDict() + + if not origins_to_set: # CORS is not enabled for this route + return headers + + for origin in origins_to_set: + headers.add(ACL_ORIGIN, origin) + + headers[ACL_EXPOSE_HEADERS] = options.get("expose_headers") + + if options.get("supports_credentials"): + headers[ACL_CREDENTIALS] = "true" # case sensitive + + if ( + ACL_REQUEST_HEADER_PRIVATE_NETWORK in request_headers + and request_headers.get(ACL_REQUEST_HEADER_PRIVATE_NETWORK) == "true" + ): + allow_private_network = "true" if options.get("allow_private_network") else "false" + headers[ACL_RESPONSE_PRIVATE_NETWORK] = allow_private_network + + # This is a preflight request + # http://www.w3.org/TR/cors/#resource-preflight-requests + if request_method == "OPTIONS": + acl_request_method = request_headers.get(ACL_REQUEST_METHOD, "").upper() + + # If there is no Access-Control-Request-Method header or if parsing + # failed, do not set any additional headers + if acl_request_method and acl_request_method in options.get("methods"): + # If method is not a case-sensitive match for any of the values in + # list of methods do not set any additional headers and terminate + # this set of steps. + headers[ACL_ALLOW_HEADERS] = get_allow_headers(options, request_headers.get(ACL_REQUEST_HEADERS)) + headers[ACL_MAX_AGE] = options.get("max_age") + headers[ACL_METHODS] = options.get("methods") + else: + LOG.info( + "The request's Access-Control-Request-Method header does not match allowed methods. CORS headers will not be applied." + ) + + # http://www.w3.org/TR/cors/#resource-implementation + if options.get("vary_header"): + # Only set header if the origin returned will vary dynamically, + # i.e. if we are not returning an asterisk, and there are multiple + # origins that can be matched. + if headers[ACL_ORIGIN] == "*": + pass + elif ( + len(options.get("origins")) > 1 + or len(origins_to_set) > 1 + or any(map(probably_regex, options.get("origins"))) + ): + headers.add("Vary", "Origin") + + return MultiDict((k, v) for k, v in headers.items() if v) + + +def set_cors_headers(resp, options): + """ + Performs the actual evaluation of Flask-CORS options and actually + modifies the response object. + + This function is used both in the decorator and the after_request + callback + """ + + # If CORS has already been evaluated via the decorator, skip + if hasattr(resp, FLASK_CORS_EVALUATED): + LOG.debug("CORS have been already evaluated, skipping") + return resp + + # Some libraries, like OAuthlib, set resp.headers to non Multidict + # objects (Werkzeug Headers work as well). This is a problem because + # headers allow repeated values. + if not isinstance(resp.headers, Headers) and not isinstance(resp.headers, MultiDict): + resp.headers = MultiDict(resp.headers) + + headers_to_set = get_cors_headers(options, request.headers, request.method) + + LOG.debug("Settings CORS headers: %s", str(headers_to_set)) + + for k, v in headers_to_set.items(): + resp.headers.add(k, v) + + return resp + + +def probably_regex(maybe_regex): + if isinstance(maybe_regex, RegexObject): + return True + else: + common_regex_chars = ["*", "\\", "]", "?", "$", "^", "[", "]", "(", ")"] + # Use common characters used in regular expressions as a proxy + # for if this string is in fact a regex. + return any(c in maybe_regex for c in common_regex_chars) + + +def re_fix(reg): + """ + Replace the invalid regex r'*' with the valid, wildcard regex r'/.*' to + enable the CORS app extension to have a more user friendly api. + """ + return r".*" if reg == r"*" else reg + + +def try_match_any_pattern(inst, patterns, caseSensitive=True): + return any(try_match_pattern(inst, pattern, caseSensitive) for pattern in patterns) + +def try_match_pattern(value, pattern, caseSensitive=True): + """ + Safely attempts to match a pattern or string to a value. This + function can be used to match request origins, headers, or paths. + The value of caseSensitive should be set in accordance to the + data being compared e.g. origins and headers are case insensitive + whereas paths are case-sensitive + """ + if isinstance(pattern, RegexObject): + return re.match(pattern, value) + if probably_regex(pattern): + flags = 0 if caseSensitive else re.IGNORECASE + try: + return re.match(pattern, value, flags=flags) + except re.error: + return False + try: + v = str(value) + p = str(pattern) + return v == p if caseSensitive else v.casefold() == p.casefold() + except Exception: + return value == pattern + +def get_cors_options(appInstance, *dicts): + """ + Compute CORS options for an application by combining the DEFAULT_OPTIONS, + the app's configuration-specified options and any dictionaries passed. The + last specified option wins. + """ + options = DEFAULT_OPTIONS.copy() + options.update(get_app_kwarg_dict(appInstance)) + if dicts: + for d in dicts: + options.update(d) + + return serialize_options(options) + + +def get_app_kwarg_dict(appInstance=None): + """Returns the dictionary of CORS specific app configurations.""" + app = appInstance or current_app + + # In order to support blueprints which do not have a config attribute + app_config = getattr(app, "config", {}) + + return {k.lower().replace("cors_", ""): app_config.get(k) for k in CONFIG_OPTIONS if app_config.get(k) is not None} + + +def flexible_str(obj): + """ + A more flexible str function which intelligently handles stringifying + strings, lists and other iterables. The results are lexographically sorted + to ensure generated responses are consistent when iterables such as Set + are used. + """ + if obj is None: + return None + elif not isinstance(obj, str) and isinstance(obj, Iterable): + return ", ".join(str(item) for item in sorted(obj)) + else: + return str(obj) + + +def serialize_option(options_dict, key, upper=False): + if key in options_dict: + value = flexible_str(options_dict[key]) + options_dict[key] = value.upper() if upper else value + + +def ensure_iterable(inst): + """ + Wraps scalars or string types as a list, or returns the iterable instance. + """ + if isinstance(inst, str) or not isinstance(inst, Iterable): + return [inst] + else: + return inst + + +def sanitize_regex_param(param): + return [re_fix(x) for x in ensure_iterable(param)] + + +def serialize_options(opts): + """ + A helper method to serialize and processes the options dictionary. + """ + options = (opts or {}).copy() + + for key in opts.keys(): + if key not in DEFAULT_OPTIONS: + LOG.warning("Unknown option passed to Flask-CORS: %s", key) + + # Ensure origins is a list of allowed origins with at least one entry. + options["origins"] = sanitize_regex_param(options.get("origins")) + options["allow_headers"] = sanitize_regex_param(options.get("allow_headers")) + + # This is expressly forbidden by the spec. Raise a value error so people + # don't get burned in production. + if r".*" in options["origins"] and options["supports_credentials"] and options["send_wildcard"]: + raise ValueError( + "Cannot use supports_credentials in conjunction with" + "an origin string of '*'. See: " + "http://www.w3.org/TR/cors/#resource-requests" + ) + + serialize_option(options, "expose_headers") + serialize_option(options, "methods", upper=True) + + if isinstance(options.get("max_age"), timedelta): + options["max_age"] = str(int(options["max_age"].total_seconds())) + + return options diff --git a/backend/venv/Lib/site-packages/flask_cors/decorator.py b/backend/venv/Lib/site-packages/flask_cors/decorator.py new file mode 100644 index 0000000..f8915b6 --- /dev/null +++ b/backend/venv/Lib/site-packages/flask_cors/decorator.py @@ -0,0 +1,129 @@ +import logging +from functools import update_wrapper + +from flask import current_app, make_response, request + +from .core import FLASK_CORS_EVALUATED, get_cors_options, set_cors_headers + +LOG = logging.getLogger(__name__) + + +def cross_origin(*args, **kwargs): + """ + This function is the decorator which is used to wrap a Flask route with. + In the simplest case, simply use the default parameters to allow all + origins in what is the most permissive configuration. If this method + modifies state or performs authentication which may be brute-forced, you + should add some degree of protection, such as Cross Site Request Forgery + protection. + + :param origins: + The origin, or list of origins to allow requests from. + The origin(s) may be regular expressions, case-sensitive strings, + or else an asterisk + + Default : '*' + :type origins: list, string or regex + + :param methods: + The method or list of methods which the allowed origins are allowed to + access for non-simple requests. + + Default : [GET, HEAD, POST, OPTIONS, PUT, PATCH, DELETE] + :type methods: list or string + + :param expose_headers: + The header or list which are safe to expose to the API of a CORS API + specification. + + Default : None + :type expose_headers: list or string + + :param allow_headers: + The header or list of header field names which can be used when this + resource is accessed by allowed origins. The header(s) may be regular + expressions, case-sensitive strings, or else an asterisk. + + Default : '*', allow all headers + :type allow_headers: list, string or regex + + :param supports_credentials: + Allows users to make authenticated requests. If true, injects the + `Access-Control-Allow-Credentials` header in responses. This allows + cookies and credentials to be submitted across domains. + + :note: This option cannot be used in conjunction with a '*' origin + + Default : False + :type supports_credentials: bool + + :param max_age: + The maximum time for which this CORS request maybe cached. This value + is set as the `Access-Control-Max-Age` header. + + Default : None + :type max_age: timedelta, integer, string or None + + :param send_wildcard: If True, and the origins parameter is `*`, a wildcard + `Access-Control-Allow-Origin` header is sent, rather than the + request's `Origin` header. + + Default : False + :type send_wildcard: bool + + :param vary_header: + If True, the header Vary: Origin will be returned as per the W3 + implementation guidelines. + + Setting this header when the `Access-Control-Allow-Origin` is + dynamically generated (e.g. when there is more than one allowed + origin, and an Origin than '*' is returned) informs CDNs and other + caches that the CORS headers are dynamic, and cannot be cached. + + If False, the Vary header will never be injected or altered. + + Default : True + :type vary_header: bool + + :param automatic_options: + Only applies to the `cross_origin` decorator. If True, Flask-CORS will + override Flask's default OPTIONS handling to return CORS headers for + OPTIONS requests. + + Default : True + :type automatic_options: bool + + """ + _options = kwargs + + def decorator(f): + LOG.debug("Enabling %s for cross_origin using options:%s", f, _options) + + # If True, intercept OPTIONS requests by modifying the view function, + # replicating Flask's default behavior, and wrapping the response with + # CORS headers. + # + # If f.provide_automatic_options is unset or True, Flask's route + # decorator (which is actually wraps the function object we return) + # intercepts OPTIONS handling, and requests will not have CORS headers + if _options.get("automatic_options", True): + f.required_methods = getattr(f, "required_methods", set()) + f.required_methods.add("OPTIONS") + f.provide_automatic_options = False + + def wrapped_function(*args, **kwargs): + # Handle setting of Flask-Cors parameters + options = get_cors_options(current_app, _options) + + if options.get("automatic_options") and request.method == "OPTIONS": + resp = current_app.make_default_options_response() + else: + resp = make_response(f(*args, **kwargs)) + + set_cors_headers(resp, options) + setattr(resp, FLASK_CORS_EVALUATED, True) + return resp + + return update_wrapper(wrapped_function, f) + + return decorator diff --git a/backend/venv/Lib/site-packages/flask_cors/extension.py b/backend/venv/Lib/site-packages/flask_cors/extension.py new file mode 100644 index 0000000..434f65e --- /dev/null +++ b/backend/venv/Lib/site-packages/flask_cors/extension.py @@ -0,0 +1,206 @@ +import logging +from urllib.parse import unquote + +from flask import request + +from .core import ACL_ORIGIN, get_cors_options, get_regexp_pattern, parse_resources, set_cors_headers, try_match_pattern + +LOG = logging.getLogger(__name__) + + +class CORS: + """ + Initializes Cross Origin Resource sharing for the application. The + arguments are identical to `cross_origin`, with the addition of a + `resources` parameter. The resources parameter defines a series of regular + expressions for resource paths to match and optionally, the associated + options to be applied to the particular resource. These options are + identical to the arguments to `cross_origin`. + + The settings for CORS are determined in the following order + + 1. Resource level settings (e.g when passed as a dictionary) + 2. Keyword argument settings + 3. App level configuration settings (e.g. CORS_*) + 4. Default settings + + Note: as it is possible for multiple regular expressions to match a + resource path, the regular expressions are first sorted by length, + from longest to shortest, in order to attempt to match the most + specific regular expression. This allows the definition of a + number of specific resource options, with a wildcard fallback + for all other resources. + + :param resources: + The series of regular expression and (optionally) associated CORS + options to be applied to the given resource path. + + If the argument is a dictionary, it's keys must be regular expressions, + and the values must be a dictionary of kwargs, identical to the kwargs + of this function. + + If the argument is a list, it is expected to be a list of regular + expressions, for which the app-wide configured options are applied. + + If the argument is a string, it is expected to be a regular expression + for which the app-wide configured options are applied. + + Default : Match all and apply app-level configuration + + :type resources: dict, iterable or string + + :param origins: + The origin, or list of origins to allow requests from. + The origin(s) may be regular expressions, case-sensitive strings, + or else an asterisk. + + .. note:: + + origins must include the schema and the port (if not port 80), + e.g., + `CORS(app, origins=["http://localhost:8000", "https://example.com"])`. + + Default : '*' + :type origins: list, string or regex + + :param methods: + The method or list of methods which the allowed origins are allowed to + access for non-simple requests. + + Default : [GET, HEAD, POST, OPTIONS, PUT, PATCH, DELETE] + :type methods: list or string + + :param expose_headers: + The header or list which are safe to expose to the API of a CORS API + specification. + + Default : None + :type expose_headers: list or string + + :param allow_headers: + The header or list of header field names which can be used when this + resource is accessed by allowed origins. The header(s) may be regular + expressions, case-sensitive strings, or else an asterisk. + + Default : '*', allow all headers + :type allow_headers: list, string or regex + + :param supports_credentials: + Allows users to make authenticated requests. If true, injects the + `Access-Control-Allow-Credentials` header in responses. This allows + cookies and credentials to be submitted across domains. + + :note: This option cannot be used in conjunction with a '*' origin + + Default : False + :type supports_credentials: bool + + :param max_age: + The maximum time for which this CORS request maybe cached. This value + is set as the `Access-Control-Max-Age` header. + + Default : None + :type max_age: timedelta, integer, string or None + + :param send_wildcard: If True, and the origins parameter is `*`, a wildcard + `Access-Control-Allow-Origin` header is sent, rather than the + request's `Origin` header. + + Default : False + :type send_wildcard: bool + + :param vary_header: + If True, the header Vary: Origin will be returned as per the W3 + implementation guidelines. + + Setting this header when the `Access-Control-Allow-Origin` is + dynamically generated (e.g. when there is more than one allowed + origin, and an Origin than '*' is returned) informs CDNs and other + caches that the CORS headers are dynamic, and cannot be cached. + + If False, the Vary header will never be injected or altered. + + Default : True + :type vary_header: bool + + :param allow_private_network: + If True, the response header `Access-Control-Allow-Private-Network` + will be set with the value 'true' whenever the request header + `Access-Control-Request-Private-Network` has a value 'true'. + + If False, the response header `Access-Control-Allow-Private-Network` + will be set with the value 'false' whenever the request header + `Access-Control-Request-Private-Network` has a value of 'true'. + + If the request header `Access-Control-Request-Private-Network` is + not present or has a value other than 'true', the response header + `Access-Control-Allow-Private-Network` will not be set. + + Default : True + :type allow_private_network: bool + """ + + def __init__(self, app=None, **kwargs): + self._options = kwargs + if app is not None: + self.init_app(app, **kwargs) + + def init_app(self, app, **kwargs): + # The resources and options may be specified in the App Config, the CORS constructor + # or the kwargs to the call to init_app. + options = get_cors_options(app, self._options, kwargs) + + # Flatten our resources into a list of the form + # (pattern_or_regexp, dictionary_of_options) + resources = parse_resources(options.get("resources")) + + # Compute the options for each resource by combining the options from + # the app's configuration, the constructor, the kwargs to init_app, and + # finally the options specified in the resources dictionary. + resources = [(pattern, get_cors_options(app, options, opts)) for (pattern, opts) in resources] + + # Create a human-readable form of these resources by converting the compiled + # regular expressions into strings. + resources_human = {get_regexp_pattern(pattern): opts for (pattern, opts) in resources} + LOG.debug("Configuring CORS with resources: %s", resources_human) + + cors_after_request = make_after_request_function(resources) + app.after_request(cors_after_request) + + # Wrap exception handlers with cross_origin + # These error handlers will still respect the behavior of the route + if options.get("intercept_exceptions", True): + + def _after_request_decorator(f): + def wrapped_function(*args, **kwargs): + return cors_after_request(app.make_response(f(*args, **kwargs))) + + return wrapped_function + + if hasattr(app, "handle_exception"): + app.handle_exception = _after_request_decorator(app.handle_exception) + app.handle_user_exception = _after_request_decorator(app.handle_user_exception) + + +def make_after_request_function(resources): + def cors_after_request(resp): + # If CORS headers are set in a view decorator, pass + if resp.headers is not None and resp.headers.get(ACL_ORIGIN): + LOG.debug("CORS have been already evaluated, skipping") + return resp + normalized_path = unquote(request.path) + for res_regex, res_options in resources: + if try_match_pattern(normalized_path, res_regex, caseSensitive=True): + LOG.debug( + "Request to '%r' matches CORS resource '%s'. Using options: %s", + request.path, + get_regexp_pattern(res_regex), + res_options, + ) + set_cors_headers(resp, res_options) + break + else: + LOG.debug("No CORS rule matches") + return resp + + return cors_after_request diff --git a/backend/venv/Lib/site-packages/flask_cors/version.py b/backend/venv/Lib/site-packages/flask_cors/version.py new file mode 100644 index 0000000..79a961b --- /dev/null +++ b/backend/venv/Lib/site-packages/flask_cors/version.py @@ -0,0 +1 @@ +__version__ = "6.0.1" diff --git a/backend/venv/Lib/site-packages/idna-3.10.dist-info/INSTALLER b/backend/venv/Lib/site-packages/idna-3.10.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/backend/venv/Lib/site-packages/idna-3.10.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/backend/venv/Lib/site-packages/idna-3.10.dist-info/LICENSE.md b/backend/venv/Lib/site-packages/idna-3.10.dist-info/LICENSE.md new file mode 100644 index 0000000..19b6b45 --- /dev/null +++ b/backend/venv/Lib/site-packages/idna-3.10.dist-info/LICENSE.md @@ -0,0 +1,31 @@ +BSD 3-Clause License + +Copyright (c) 2013-2024, Kim Davies and contributors. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/backend/venv/Lib/site-packages/idna-3.10.dist-info/METADATA b/backend/venv/Lib/site-packages/idna-3.10.dist-info/METADATA new file mode 100644 index 0000000..c42623e --- /dev/null +++ b/backend/venv/Lib/site-packages/idna-3.10.dist-info/METADATA @@ -0,0 +1,250 @@ +Metadata-Version: 2.1 +Name: idna +Version: 3.10 +Summary: Internationalized Domain Names in Applications (IDNA) +Author-email: Kim Davies +Requires-Python: >=3.6 +Description-Content-Type: text/x-rst +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: Intended Audience :: System Administrators +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Classifier: Programming Language :: Python :: 3.13 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Topic :: Internet :: Name Service (DNS) +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: Utilities +Requires-Dist: ruff >= 0.6.2 ; extra == "all" +Requires-Dist: mypy >= 1.11.2 ; extra == "all" +Requires-Dist: pytest >= 8.3.2 ; extra == "all" +Requires-Dist: flake8 >= 7.1.1 ; extra == "all" +Project-URL: Changelog, https://github.com/kjd/idna/blob/master/HISTORY.rst +Project-URL: Issue tracker, https://github.com/kjd/idna/issues +Project-URL: Source, https://github.com/kjd/idna +Provides-Extra: all + +Internationalized Domain Names in Applications (IDNA) +===================================================== + +Support for the Internationalized Domain Names in +Applications (IDNA) protocol as specified in `RFC 5891 +`_. This is the latest version of +the protocol and is sometimes referred to as “IDNA 2008”. + +This library also provides support for Unicode Technical +Standard 46, `Unicode IDNA Compatibility Processing +`_. + +This acts as a suitable replacement for the “encodings.idna” +module that comes with the Python standard library, but which +only supports the older superseded IDNA specification (`RFC 3490 +`_). + +Basic functions are simply executed: + +.. code-block:: pycon + + >>> import idna + >>> idna.encode('ドメイン.テスト') + b'xn--eckwd4c7c.xn--zckzah' + >>> print(idna.decode('xn--eckwd4c7c.xn--zckzah')) + ドメイン.テスト + + +Installation +------------ + +This package is available for installation from PyPI: + +.. code-block:: bash + + $ python3 -m pip install idna + + +Usage +----- + +For typical usage, the ``encode`` and ``decode`` functions will take a +domain name argument and perform a conversion to A-labels or U-labels +respectively. + +.. code-block:: pycon + + >>> import idna + >>> idna.encode('ドメイン.テスト') + b'xn--eckwd4c7c.xn--zckzah' + >>> print(idna.decode('xn--eckwd4c7c.xn--zckzah')) + ドメイン.テスト + +You may use the codec encoding and decoding methods using the +``idna.codec`` module: + +.. code-block:: pycon + + >>> import idna.codec + >>> print('домен.испытание'.encode('idna2008')) + b'xn--d1acufc.xn--80akhbyknj4f' + >>> print(b'xn--d1acufc.xn--80akhbyknj4f'.decode('idna2008')) + домен.испытание + +Conversions can be applied at a per-label basis using the ``ulabel`` or +``alabel`` functions if necessary: + +.. code-block:: pycon + + >>> idna.alabel('测试') + b'xn--0zwm56d' + +Compatibility Mapping (UTS #46) ++++++++++++++++++++++++++++++++ + +As described in `RFC 5895 `_, the +IDNA specification does not normalize input from different potential +ways a user may input a domain name. This functionality, known as +a “mapping”, is considered by the specification to be a local +user-interface issue distinct from IDNA conversion functionality. + +This library provides one such mapping that was developed by the +Unicode Consortium. Known as `Unicode IDNA Compatibility Processing +`_, it provides for both a regular +mapping for typical applications, as well as a transitional mapping to +help migrate from older IDNA 2003 applications. Strings are +preprocessed according to Section 4.4 “Preprocessing for IDNA2008” +prior to the IDNA operations. + +For example, “Königsgäßchen” is not a permissible label as *LATIN +CAPITAL LETTER K* is not allowed (nor are capital letters in general). +UTS 46 will convert this into lower case prior to applying the IDNA +conversion. + +.. code-block:: pycon + + >>> import idna + >>> idna.encode('Königsgäßchen') + ... + idna.core.InvalidCodepoint: Codepoint U+004B at position 1 of 'Königsgäßchen' not allowed + >>> idna.encode('Königsgäßchen', uts46=True) + b'xn--knigsgchen-b4a3dun' + >>> print(idna.decode('xn--knigsgchen-b4a3dun')) + königsgäßchen + +Transitional processing provides conversions to help transition from +the older 2003 standard to the current standard. For example, in the +original IDNA specification, the *LATIN SMALL LETTER SHARP S* (ß) was +converted into two *LATIN SMALL LETTER S* (ss), whereas in the current +IDNA specification this conversion is not performed. + +.. code-block:: pycon + + >>> idna.encode('Königsgäßchen', uts46=True, transitional=True) + 'xn--knigsgsschen-lcb0w' + +Implementers should use transitional processing with caution, only in +rare cases where conversion from legacy labels to current labels must be +performed (i.e. IDNA implementations that pre-date 2008). For typical +applications that just need to convert labels, transitional processing +is unlikely to be beneficial and could produce unexpected incompatible +results. + +``encodings.idna`` Compatibility +++++++++++++++++++++++++++++++++ + +Function calls from the Python built-in ``encodings.idna`` module are +mapped to their IDNA 2008 equivalents using the ``idna.compat`` module. +Simply substitute the ``import`` clause in your code to refer to the new +module name. + +Exceptions +---------- + +All errors raised during the conversion following the specification +should raise an exception derived from the ``idna.IDNAError`` base +class. + +More specific exceptions that may be generated as ``idna.IDNABidiError`` +when the error reflects an illegal combination of left-to-right and +right-to-left characters in a label; ``idna.InvalidCodepoint`` when +a specific codepoint is an illegal character in an IDN label (i.e. +INVALID); and ``idna.InvalidCodepointContext`` when the codepoint is +illegal based on its positional context (i.e. it is CONTEXTO or CONTEXTJ +but the contextual requirements are not satisfied.) + +Building and Diagnostics +------------------------ + +The IDNA and UTS 46 functionality relies upon pre-calculated lookup +tables for performance. These tables are derived from computing against +eligibility criteria in the respective standards. These tables are +computed using the command-line script ``tools/idna-data``. + +This tool will fetch relevant codepoint data from the Unicode repository +and perform the required calculations to identify eligibility. There are +three main modes: + +* ``idna-data make-libdata``. Generates ``idnadata.py`` and + ``uts46data.py``, the pre-calculated lookup tables used for IDNA and + UTS 46 conversions. Implementers who wish to track this library against + a different Unicode version may use this tool to manually generate a + different version of the ``idnadata.py`` and ``uts46data.py`` files. + +* ``idna-data make-table``. Generate a table of the IDNA disposition + (e.g. PVALID, CONTEXTJ, CONTEXTO) in the format found in Appendix + B.1 of RFC 5892 and the pre-computed tables published by `IANA + `_. + +* ``idna-data U+0061``. Prints debugging output on the various + properties associated with an individual Unicode codepoint (in this + case, U+0061), that are used to assess the IDNA and UTS 46 status of a + codepoint. This is helpful in debugging or analysis. + +The tool accepts a number of arguments, described using ``idna-data +-h``. Most notably, the ``--version`` argument allows the specification +of the version of Unicode to be used in computing the table data. For +example, ``idna-data --version 9.0.0 make-libdata`` will generate +library data against Unicode 9.0.0. + + +Additional Notes +---------------- + +* **Packages**. The latest tagged release version is published in the + `Python Package Index `_. + +* **Version support**. This library supports Python 3.6 and higher. + As this library serves as a low-level toolkit for a variety of + applications, many of which strive for broad compatibility with older + Python versions, there is no rush to remove older interpreter support. + Removing support for older versions should be well justified in that the + maintenance burden has become too high. + +* **Python 2**. Python 2 is supported by version 2.x of this library. + Use "idna<3" in your requirements file if you need this library for + a Python 2 application. Be advised that these versions are no longer + actively developed. + +* **Testing**. The library has a test suite based on each rule of the + IDNA specification, as well as tests that are provided as part of the + Unicode Technical Standard 46, `Unicode IDNA Compatibility Processing + `_. + +* **Emoji**. It is an occasional request to support emoji domains in + this library. Encoding of symbols like emoji is expressly prohibited by + the technical standard IDNA 2008 and emoji domains are broadly phased + out across the domain industry due to associated security risks. For + now, applications that need to support these non-compliant labels + may wish to consider trying the encode/decode operation in this library + first, and then falling back to using `encodings.idna`. See `the Github + project `_ for more discussion. + diff --git a/backend/venv/Lib/site-packages/idna-3.10.dist-info/RECORD b/backend/venv/Lib/site-packages/idna-3.10.dist-info/RECORD new file mode 100644 index 0000000..54f6609 --- /dev/null +++ b/backend/venv/Lib/site-packages/idna-3.10.dist-info/RECORD @@ -0,0 +1,22 @@ +idna-3.10.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +idna-3.10.dist-info/LICENSE.md,sha256=pZ8LDvNjWHQQmkRhykT_enDVBpboFHZ7-vch1Mmw2w8,1541 +idna-3.10.dist-info/METADATA,sha256=URR5ZyDfQ1PCEGhkYoojqfi2Ra0tau2--lhwG4XSfjI,10158 +idna-3.10.dist-info/RECORD,, +idna-3.10.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81 +idna/__init__.py,sha256=MPqNDLZbXqGaNdXxAFhiqFPKEQXju2jNQhCey6-5eJM,868 +idna/__pycache__/__init__.cpython-312.pyc,, +idna/__pycache__/codec.cpython-312.pyc,, +idna/__pycache__/compat.cpython-312.pyc,, +idna/__pycache__/core.cpython-312.pyc,, +idna/__pycache__/idnadata.cpython-312.pyc,, +idna/__pycache__/intranges.cpython-312.pyc,, +idna/__pycache__/package_data.cpython-312.pyc,, +idna/__pycache__/uts46data.cpython-312.pyc,, +idna/codec.py,sha256=PEew3ItwzjW4hymbasnty2N2OXvNcgHB-JjrBuxHPYY,3422 +idna/compat.py,sha256=RzLy6QQCdl9784aFhb2EX9EKGCJjg0P3PilGdeXXcx8,316 +idna/core.py,sha256=YJYyAMnwiQEPjVC4-Fqu_p4CJ6yKKuDGmppBNQNQpFs,13239 +idna/idnadata.py,sha256=W30GcIGvtOWYwAjZj4ZjuouUutC6ffgNuyjJy7fZ-lo,78306 +idna/intranges.py,sha256=amUtkdhYcQG8Zr-CoMM_kVRacxkivC1WgxN1b63KKdU,1898 +idna/package_data.py,sha256=q59S3OXsc5VI8j6vSD0sGBMyk6zZ4vWFREE88yCJYKs,21 +idna/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +idna/uts46data.py,sha256=rt90K9J40gUSwppDPCrhjgi5AA6pWM65dEGRSf6rIhM,239289 diff --git a/backend/venv/Lib/site-packages/idna-3.10.dist-info/WHEEL b/backend/venv/Lib/site-packages/idna-3.10.dist-info/WHEEL new file mode 100644 index 0000000..3b5e64b --- /dev/null +++ b/backend/venv/Lib/site-packages/idna-3.10.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: flit 3.9.0 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/backend/venv/Lib/site-packages/idna/__init__.py b/backend/venv/Lib/site-packages/idna/__init__.py new file mode 100644 index 0000000..cfdc030 --- /dev/null +++ b/backend/venv/Lib/site-packages/idna/__init__.py @@ -0,0 +1,45 @@ +from .core import ( + IDNABidiError, + IDNAError, + InvalidCodepoint, + InvalidCodepointContext, + alabel, + check_bidi, + check_hyphen_ok, + check_initial_combiner, + check_label, + check_nfc, + decode, + encode, + ulabel, + uts46_remap, + valid_contextj, + valid_contexto, + valid_label_length, + valid_string_length, +) +from .intranges import intranges_contain +from .package_data import __version__ + +__all__ = [ + "__version__", + "IDNABidiError", + "IDNAError", + "InvalidCodepoint", + "InvalidCodepointContext", + "alabel", + "check_bidi", + "check_hyphen_ok", + "check_initial_combiner", + "check_label", + "check_nfc", + "decode", + "encode", + "intranges_contain", + "ulabel", + "uts46_remap", + "valid_contextj", + "valid_contexto", + "valid_label_length", + "valid_string_length", +] diff --git a/backend/venv/Lib/site-packages/idna/__pycache__/__init__.cpython-312.pyc b/backend/venv/Lib/site-packages/idna/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..23a303e1d51f90cd92a9b5d41893119de3c16e77 GIT binary patch literal 893 zcmbu7J&)5c7{~3jO`E3adwUFs4T%hQpo(Ka2nkw-lTLRC#9~FVoW!)Iu@gCI;YL0M zI~$*cZ(xZDA;g9_p+ijANnto77Cij&Jpb7L=kd#X&uarcKK=N-ifaITG|BH_?Sk_{ z2X8luZ&6(nPhR6^+(7)OM;@#jCSyMFmdRYFY_Q zu!4~UM=1}Ppi;S&UO6~bBA!Rej%lPzE1QbyyQ!wQn!S!}w`Q|-a4P6RvMmi3G+!5K7Cbq9 z`uI3_N$L79kZGPJhe4=asfdFu72DvLg+a~=y1%QH2P_ukCdTGLV0@6Bsn$K7#+!uR qm)CSj^FZ@`jjuHb;e|DV)&=+*-){iue*o9N)hDj?x+$;f6~6$m%=Op+ literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/idna/__pycache__/codec.cpython-312.pyc b/backend/venv/Lib/site-packages/idna/__pycache__/codec.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bbca1cf3f57e17729e37e88aa6af7d0dc54c2bdf GIT binary patch literal 4983 zcmd6qUu;v?8NkoA@4deMlh}^)hd2R}KohJkDGN)B0M6 z#es}!eb|xxopZnQ-S3=x{`}5&{?^v!Advp~uSe&9(niRa_)tq?wNUL5`4nnrmJ(Rn!E#5ljajZ+dYGjHES+FEw1s5{ zvvh%Fo6-)p!%wi~O)s&20B% zWRYz$r&whR{H^eDf+EgZ*vE)6zbJ%ktX`ftB1gPOfd=oi589uEkR11&q z9Us3CKA|c>8o#K7gNk-RPiMj>Pn>#lDtt*%E=+`JTFWFS!ZXp>1x1y^7Zvqlcq%>< z*5bM{ngMO}oT7!}vKoB>XFN8RnPZ)pcd?NlGZ%sr+n)q+nUtK~{MpZ(+wXVut@OXV z)*meP2XCKQ?VnohIKJXK{tvgWfA4+8~*`rW0+ReUP?2ZIGq|9P3!XZb*@c8civY zh~bDtQfWDx#Ih?A`B^ratkzgz*->1ohA=ayE1F@AtL8#t{l7`r$eW!8h7*bc*O~S@ zh(+?X#U_jt_N^1hZdh6N>BQ}>JJ#F&;(@6$s=w|)lL^ygmuYhP_C7G#|EEX=EzCC1 za}56V#7+-*DvyC^LPHZ6WQGRCR)vEk3qU&D{5GTGs2Zb6N>TM_@(2SGZEOcan2iI| zs0Td9s@!Gm;<>~~@Kbg!eJ3QS`%l#OKWmGL1|1f7nO_icJnhW!vVgGDL|H_QEWAuq zd(Nua%re+mu;v_D5M|o}XoKXP?-Q~h<-|k{sEsCwjysU0oK#~`E$2wiMunVBmgZps zz?V(OiD

ps}W!wH%|p0uQ#So4Bc6axC7Wqc>Hfj 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

mw^B4wn!SbxXID=*RU3CfAe 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 literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/idna/__pycache__/uts46data.cpython-312.pyc b/backend/venv/Lib/site-packages/idna/__pycache__/uts46data.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fa58fc550c0b3237afafb283828aea9f58cd727e GIT binary patch literal 158853 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 vP3d-+HIGm2Y^U_)nC+~yx1`%+*0daU>22vN% Tuple[bytes, int]: + if errors != "strict": + raise IDNAError('Unsupported error handling "{}"'.format(errors)) + + if not data: + return b"", 0 + + return encode(data), len(data) + + def decode(self, data: bytes, errors: str = "strict") -> Tuple[str, int]: + if errors != "strict": + raise IDNAError('Unsupported error handling "{}"'.format(errors)) + + if not data: + return "", 0 + + return decode(data), len(data) + + +class IncrementalEncoder(codecs.BufferedIncrementalEncoder): + def _buffer_encode(self, data: str, errors: str, final: bool) -> Tuple[bytes, int]: + if errors != "strict": + raise IDNAError('Unsupported error handling "{}"'.format(errors)) + + if not data: + return b"", 0 + + labels = _unicode_dots_re.split(data) + trailing_dot = b"" + if labels: + if not labels[-1]: + trailing_dot = b"." + del labels[-1] + elif not final: + # Keep potentially unfinished label until the next call + del labels[-1] + if labels: + trailing_dot = b"." + + result = [] + size = 0 + for label in labels: + result.append(alabel(label)) + if size: + size += 1 + size += len(label) + + # Join with U+002E + result_bytes = b".".join(result) + trailing_dot + size += len(trailing_dot) + return result_bytes, size + + +class IncrementalDecoder(codecs.BufferedIncrementalDecoder): + def _buffer_decode(self, data: Any, errors: str, final: bool) -> Tuple[str, int]: + if errors != "strict": + raise IDNAError('Unsupported error handling "{}"'.format(errors)) + + if not data: + return ("", 0) + + if not isinstance(data, str): + data = str(data, "ascii") + + labels = _unicode_dots_re.split(data) + trailing_dot = "" + if labels: + if not labels[-1]: + trailing_dot = "." + del labels[-1] + elif not final: + # Keep potentially unfinished label until the next call + del labels[-1] + if labels: + trailing_dot = "." + + result = [] + size = 0 + for label in labels: + result.append(ulabel(label)) + if size: + size += 1 + size += len(label) + + result_str = ".".join(result) + trailing_dot + size += len(trailing_dot) + return (result_str, size) + + +class StreamWriter(Codec, codecs.StreamWriter): + pass + + +class StreamReader(Codec, codecs.StreamReader): + pass + + +def search_function(name: str) -> Optional[codecs.CodecInfo]: + if name != "idna2008": + return None + return codecs.CodecInfo( + name=name, + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamwriter=StreamWriter, + streamreader=StreamReader, + ) + + +codecs.register(search_function) diff --git a/backend/venv/Lib/site-packages/idna/compat.py b/backend/venv/Lib/site-packages/idna/compat.py new file mode 100644 index 0000000..1df9f2a --- /dev/null +++ b/backend/venv/Lib/site-packages/idna/compat.py @@ -0,0 +1,15 @@ +from typing import Any, Union + +from .core import decode, encode + + +def ToASCII(label: str) -> bytes: + return encode(label) + + +def ToUnicode(label: Union[bytes, bytearray]) -> str: + return decode(label) + + +def nameprep(s: Any) -> None: + raise NotImplementedError("IDNA 2008 does not utilise nameprep protocol") diff --git a/backend/venv/Lib/site-packages/idna/core.py b/backend/venv/Lib/site-packages/idna/core.py new file mode 100644 index 0000000..9115f12 --- /dev/null +++ b/backend/venv/Lib/site-packages/idna/core.py @@ -0,0 +1,437 @@ +import bisect +import re +import unicodedata +from typing import Optional, Union + +from . import idnadata +from .intranges import intranges_contain + +_virama_combining_class = 9 +_alabel_prefix = b"xn--" +_unicode_dots_re = re.compile("[\u002e\u3002\uff0e\uff61]") + + +class IDNAError(UnicodeError): + """Base exception for all IDNA-encoding related problems""" + + pass + + +class IDNABidiError(IDNAError): + """Exception when bidirectional requirements are not satisfied""" + + pass + + +class InvalidCodepoint(IDNAError): + """Exception when a disallowed or unallocated codepoint is used""" + + pass + + +class InvalidCodepointContext(IDNAError): + """Exception when the codepoint is not valid in the context it is used""" + + pass + + +def _combining_class(cp: int) -> int: + v = unicodedata.combining(chr(cp)) + if v == 0: + if not unicodedata.name(chr(cp)): + raise ValueError("Unknown character in unicodedata") + return v + + +def _is_script(cp: str, script: str) -> bool: + return intranges_contain(ord(cp), idnadata.scripts[script]) + + +def _punycode(s: str) -> bytes: + return s.encode("punycode") + + +def _unot(s: int) -> str: + return "U+{:04X}".format(s) + + +def valid_label_length(label: Union[bytes, str]) -> bool: + if len(label) > 63: + return False + return True + + +def valid_string_length(label: Union[bytes, str], trailing_dot: bool) -> bool: + if len(label) > (254 if trailing_dot else 253): + return False + return True + + +def check_bidi(label: str, check_ltr: bool = False) -> bool: + # Bidi rules should only be applied if string contains RTL characters + bidi_label = False + for idx, cp in enumerate(label, 1): + direction = unicodedata.bidirectional(cp) + if direction == "": + # String likely comes from a newer version of Unicode + raise IDNABidiError("Unknown directionality in label {} at position {}".format(repr(label), idx)) + if direction in ["R", "AL", "AN"]: + bidi_label = True + if not bidi_label and not check_ltr: + return True + + # Bidi rule 1 + direction = unicodedata.bidirectional(label[0]) + if direction in ["R", "AL"]: + rtl = True + elif direction == "L": + rtl = False + else: + raise IDNABidiError("First codepoint in label {} must be directionality L, R or AL".format(repr(label))) + + valid_ending = False + number_type: Optional[str] = None + for idx, cp in enumerate(label, 1): + direction = unicodedata.bidirectional(cp) + + if rtl: + # Bidi rule 2 + if direction not in [ + "R", + "AL", + "AN", + "EN", + "ES", + "CS", + "ET", + "ON", + "BN", + "NSM", + ]: + raise IDNABidiError("Invalid direction for codepoint at position {} in a right-to-left label".format(idx)) + # Bidi rule 3 + if direction in ["R", "AL", "EN", "AN"]: + valid_ending = True + elif direction != "NSM": + valid_ending = False + # Bidi rule 4 + if direction in ["AN", "EN"]: + if not number_type: + number_type = direction + else: + if number_type != direction: + raise IDNABidiError("Can not mix numeral types in a right-to-left label") + else: + # Bidi rule 5 + if direction not in ["L", "EN", "ES", "CS", "ET", "ON", "BN", "NSM"]: + raise IDNABidiError("Invalid direction for codepoint at position {} in a left-to-right label".format(idx)) + # Bidi rule 6 + if direction in ["L", "EN"]: + valid_ending = True + elif direction != "NSM": + valid_ending = False + + if not valid_ending: + raise IDNABidiError("Label ends with illegal codepoint directionality") + + return True + + +def check_initial_combiner(label: str) -> bool: + if unicodedata.category(label[0])[0] == "M": + raise IDNAError("Label begins with an illegal combining character") + return True + + +def check_hyphen_ok(label: str) -> bool: + if label[2:4] == "--": + raise IDNAError("Label has disallowed hyphens in 3rd and 4th position") + if label[0] == "-" or label[-1] == "-": + raise IDNAError("Label must not start or end with a hyphen") + return True + + +def check_nfc(label: str) -> None: + if unicodedata.normalize("NFC", label) != label: + raise IDNAError("Label must be in Normalization Form C") + + +def valid_contextj(label: str, pos: int) -> bool: + cp_value = ord(label[pos]) + + if cp_value == 0x200C: + if pos > 0: + if _combining_class(ord(label[pos - 1])) == _virama_combining_class: + return True + + ok = False + for i in range(pos - 1, -1, -1): + joining_type = idnadata.joining_types.get(ord(label[i])) + if joining_type == ord("T"): + continue + elif joining_type in [ord("L"), ord("D")]: + ok = True + break + else: + break + + if not ok: + return False + + ok = False + for i in range(pos + 1, len(label)): + joining_type = idnadata.joining_types.get(ord(label[i])) + if joining_type == ord("T"): + continue + elif joining_type in [ord("R"), ord("D")]: + ok = True + break + else: + break + return ok + + if cp_value == 0x200D: + if pos > 0: + if _combining_class(ord(label[pos - 1])) == _virama_combining_class: + return True + return False + + else: + return False + + +def valid_contexto(label: str, pos: int, exception: bool = False) -> bool: + cp_value = ord(label[pos]) + + if cp_value == 0x00B7: + if 0 < pos < len(label) - 1: + if ord(label[pos - 1]) == 0x006C and ord(label[pos + 1]) == 0x006C: + return True + return False + + elif cp_value == 0x0375: + if pos < len(label) - 1 and len(label) > 1: + return _is_script(label[pos + 1], "Greek") + return False + + elif cp_value == 0x05F3 or cp_value == 0x05F4: + if pos > 0: + return _is_script(label[pos - 1], "Hebrew") + return False + + elif cp_value == 0x30FB: + for cp in label: + if cp == "\u30fb": + continue + if _is_script(cp, "Hiragana") or _is_script(cp, "Katakana") or _is_script(cp, "Han"): + return True + return False + + elif 0x660 <= cp_value <= 0x669: + for cp in label: + if 0x6F0 <= ord(cp) <= 0x06F9: + return False + return True + + elif 0x6F0 <= cp_value <= 0x6F9: + for cp in label: + if 0x660 <= ord(cp) <= 0x0669: + return False + return True + + return False + + +def check_label(label: Union[str, bytes, bytearray]) -> None: + if isinstance(label, (bytes, bytearray)): + label = label.decode("utf-8") + if len(label) == 0: + raise IDNAError("Empty Label") + + check_nfc(label) + check_hyphen_ok(label) + check_initial_combiner(label) + + for pos, cp in enumerate(label): + cp_value = ord(cp) + if intranges_contain(cp_value, idnadata.codepoint_classes["PVALID"]): + continue + elif intranges_contain(cp_value, idnadata.codepoint_classes["CONTEXTJ"]): + try: + if not valid_contextj(label, pos): + raise InvalidCodepointContext( + "Joiner {} not allowed at position {} in {}".format(_unot(cp_value), pos + 1, repr(label)) + ) + except ValueError: + raise IDNAError( + "Unknown codepoint adjacent to joiner {} at position {} in {}".format( + _unot(cp_value), pos + 1, repr(label) + ) + ) + elif intranges_contain(cp_value, idnadata.codepoint_classes["CONTEXTO"]): + if not valid_contexto(label, pos): + raise InvalidCodepointContext( + "Codepoint {} not allowed at position {} in {}".format(_unot(cp_value), pos + 1, repr(label)) + ) + else: + raise InvalidCodepoint( + "Codepoint {} at position {} of {} not allowed".format(_unot(cp_value), pos + 1, repr(label)) + ) + + check_bidi(label) + + +def alabel(label: str) -> bytes: + try: + label_bytes = label.encode("ascii") + ulabel(label_bytes) + if not valid_label_length(label_bytes): + raise IDNAError("Label too long") + return label_bytes + except UnicodeEncodeError: + pass + + check_label(label) + label_bytes = _alabel_prefix + _punycode(label) + + if not valid_label_length(label_bytes): + raise IDNAError("Label too long") + + return label_bytes + + +def ulabel(label: Union[str, bytes, bytearray]) -> str: + if not isinstance(label, (bytes, bytearray)): + try: + label_bytes = label.encode("ascii") + except UnicodeEncodeError: + check_label(label) + return label + else: + label_bytes = label + + label_bytes = label_bytes.lower() + if label_bytes.startswith(_alabel_prefix): + label_bytes = label_bytes[len(_alabel_prefix) :] + if not label_bytes: + raise IDNAError("Malformed A-label, no Punycode eligible content found") + if label_bytes.decode("ascii")[-1] == "-": + raise IDNAError("A-label must not end with a hyphen") + else: + check_label(label_bytes) + return label_bytes.decode("ascii") + + try: + label = label_bytes.decode("punycode") + except UnicodeError: + raise IDNAError("Invalid A-label") + check_label(label) + return label + + +def uts46_remap(domain: str, std3_rules: bool = True, transitional: bool = False) -> str: + """Re-map the characters in the string according to UTS46 processing.""" + from .uts46data import uts46data + + output = "" + + for pos, char in enumerate(domain): + code_point = ord(char) + try: + uts46row = uts46data[code_point if code_point < 256 else bisect.bisect_left(uts46data, (code_point, "Z")) - 1] + status = uts46row[1] + replacement: Optional[str] = None + if len(uts46row) == 3: + replacement = uts46row[2] + if ( + status == "V" + or (status == "D" and not transitional) + or (status == "3" and not std3_rules and replacement is None) + ): + output += char + elif replacement is not None and ( + status == "M" or (status == "3" and not std3_rules) or (status == "D" and transitional) + ): + output += replacement + elif status != "I": + raise IndexError() + except IndexError: + raise InvalidCodepoint( + "Codepoint {} not allowed at position {} in {}".format(_unot(code_point), pos + 1, repr(domain)) + ) + + return unicodedata.normalize("NFC", output) + + +def encode( + s: Union[str, bytes, bytearray], + strict: bool = False, + uts46: bool = False, + std3_rules: bool = False, + transitional: bool = False, +) -> bytes: + if not isinstance(s, str): + try: + s = str(s, "ascii") + except UnicodeDecodeError: + raise IDNAError("should pass a unicode string to the function rather than a byte string.") + if uts46: + s = uts46_remap(s, std3_rules, transitional) + trailing_dot = False + result = [] + if strict: + labels = s.split(".") + else: + labels = _unicode_dots_re.split(s) + if not labels or labels == [""]: + raise IDNAError("Empty domain") + if labels[-1] == "": + del labels[-1] + trailing_dot = True + for label in labels: + s = alabel(label) + if s: + result.append(s) + else: + raise IDNAError("Empty label") + if trailing_dot: + result.append(b"") + s = b".".join(result) + if not valid_string_length(s, trailing_dot): + raise IDNAError("Domain too long") + return s + + +def decode( + s: Union[str, bytes, bytearray], + strict: bool = False, + uts46: bool = False, + std3_rules: bool = False, +) -> str: + try: + if not isinstance(s, str): + s = str(s, "ascii") + except UnicodeDecodeError: + raise IDNAError("Invalid ASCII in A-label") + if uts46: + s = uts46_remap(s, std3_rules, False) + trailing_dot = False + result = [] + if not strict: + labels = _unicode_dots_re.split(s) + else: + labels = s.split(".") + if not labels or labels == [""]: + raise IDNAError("Empty domain") + if not labels[-1]: + del labels[-1] + trailing_dot = True + for label in labels: + s = ulabel(label) + if s: + result.append(s) + else: + raise IDNAError("Empty label") + if trailing_dot: + result.append("") + return ".".join(result) diff --git a/backend/venv/Lib/site-packages/idna/idnadata.py b/backend/venv/Lib/site-packages/idna/idnadata.py new file mode 100644 index 0000000..4be6004 --- /dev/null +++ b/backend/venv/Lib/site-packages/idna/idnadata.py @@ -0,0 +1,4243 @@ +# This file is automatically generated by tools/idna-data + +__version__ = "15.1.0" +scripts = { + "Greek": ( + 0x37000000374, + 0x37500000378, + 0x37A0000037E, + 0x37F00000380, + 0x38400000385, + 0x38600000387, + 0x3880000038B, + 0x38C0000038D, + 0x38E000003A2, + 0x3A3000003E2, + 0x3F000000400, + 0x1D2600001D2B, + 0x1D5D00001D62, + 0x1D6600001D6B, + 0x1DBF00001DC0, + 0x1F0000001F16, + 0x1F1800001F1E, + 0x1F2000001F46, + 0x1F4800001F4E, + 0x1F5000001F58, + 0x1F5900001F5A, + 0x1F5B00001F5C, + 0x1F5D00001F5E, + 0x1F5F00001F7E, + 0x1F8000001FB5, + 0x1FB600001FC5, + 0x1FC600001FD4, + 0x1FD600001FDC, + 0x1FDD00001FF0, + 0x1FF200001FF5, + 0x1FF600001FFF, + 0x212600002127, + 0xAB650000AB66, + 0x101400001018F, + 0x101A0000101A1, + 0x1D2000001D246, + ), + "Han": ( + 0x2E8000002E9A, + 0x2E9B00002EF4, + 0x2F0000002FD6, + 0x300500003006, + 0x300700003008, + 0x30210000302A, + 0x30380000303C, + 0x340000004DC0, + 0x4E000000A000, + 0xF9000000FA6E, + 0xFA700000FADA, + 0x16FE200016FE4, + 0x16FF000016FF2, + 0x200000002A6E0, + 0x2A7000002B73A, + 0x2B7400002B81E, + 0x2B8200002CEA2, + 0x2CEB00002EBE1, + 0x2EBF00002EE5E, + 0x2F8000002FA1E, + 0x300000003134B, + 0x31350000323B0, + ), + "Hebrew": ( + 0x591000005C8, + 0x5D0000005EB, + 0x5EF000005F5, + 0xFB1D0000FB37, + 0xFB380000FB3D, + 0xFB3E0000FB3F, + 0xFB400000FB42, + 0xFB430000FB45, + 0xFB460000FB50, + ), + "Hiragana": ( + 0x304100003097, + 0x309D000030A0, + 0x1B0010001B120, + 0x1B1320001B133, + 0x1B1500001B153, + 0x1F2000001F201, + ), + "Katakana": ( + 0x30A1000030FB, + 0x30FD00003100, + 0x31F000003200, + 0x32D0000032FF, + 0x330000003358, + 0xFF660000FF70, + 0xFF710000FF9E, + 0x1AFF00001AFF4, + 0x1AFF50001AFFC, + 0x1AFFD0001AFFF, + 0x1B0000001B001, + 0x1B1200001B123, + 0x1B1550001B156, + 0x1B1640001B168, + ), +} +joining_types = { + 0xAD: 84, + 0x300: 84, + 0x301: 84, + 0x302: 84, + 0x303: 84, + 0x304: 84, + 0x305: 84, + 0x306: 84, + 0x307: 84, + 0x308: 84, + 0x309: 84, + 0x30A: 84, + 0x30B: 84, + 0x30C: 84, + 0x30D: 84, + 0x30E: 84, + 0x30F: 84, + 0x310: 84, + 0x311: 84, + 0x312: 84, + 0x313: 84, + 0x314: 84, + 0x315: 84, + 0x316: 84, + 0x317: 84, + 0x318: 84, + 0x319: 84, + 0x31A: 84, + 0x31B: 84, + 0x31C: 84, + 0x31D: 84, + 0x31E: 84, + 0x31F: 84, + 0x320: 84, + 0x321: 84, + 0x322: 84, + 0x323: 84, + 0x324: 84, + 0x325: 84, + 0x326: 84, + 0x327: 84, + 0x328: 84, + 0x329: 84, + 0x32A: 84, + 0x32B: 84, + 0x32C: 84, + 0x32D: 84, + 0x32E: 84, + 0x32F: 84, + 0x330: 84, + 0x331: 84, + 0x332: 84, + 0x333: 84, + 0x334: 84, + 0x335: 84, + 0x336: 84, + 0x337: 84, + 0x338: 84, + 0x339: 84, + 0x33A: 84, + 0x33B: 84, + 0x33C: 84, + 0x33D: 84, + 0x33E: 84, + 0x33F: 84, + 0x340: 84, + 0x341: 84, + 0x342: 84, + 0x343: 84, + 0x344: 84, + 0x345: 84, + 0x346: 84, + 0x347: 84, + 0x348: 84, + 0x349: 84, + 0x34A: 84, + 0x34B: 84, + 0x34C: 84, + 0x34D: 84, + 0x34E: 84, + 0x34F: 84, + 0x350: 84, + 0x351: 84, + 0x352: 84, + 0x353: 84, + 0x354: 84, + 0x355: 84, + 0x356: 84, + 0x357: 84, + 0x358: 84, + 0x359: 84, + 0x35A: 84, + 0x35B: 84, + 0x35C: 84, + 0x35D: 84, + 0x35E: 84, + 0x35F: 84, + 0x360: 84, + 0x361: 84, + 0x362: 84, + 0x363: 84, + 0x364: 84, + 0x365: 84, + 0x366: 84, + 0x367: 84, + 0x368: 84, + 0x369: 84, + 0x36A: 84, + 0x36B: 84, + 0x36C: 84, + 0x36D: 84, + 0x36E: 84, + 0x36F: 84, + 0x483: 84, + 0x484: 84, + 0x485: 84, + 0x486: 84, + 0x487: 84, + 0x488: 84, + 0x489: 84, + 0x591: 84, + 0x592: 84, + 0x593: 84, + 0x594: 84, + 0x595: 84, + 0x596: 84, + 0x597: 84, + 0x598: 84, + 0x599: 84, + 0x59A: 84, + 0x59B: 84, + 0x59C: 84, + 0x59D: 84, + 0x59E: 84, + 0x59F: 84, + 0x5A0: 84, + 0x5A1: 84, + 0x5A2: 84, + 0x5A3: 84, + 0x5A4: 84, + 0x5A5: 84, + 0x5A6: 84, + 0x5A7: 84, + 0x5A8: 84, + 0x5A9: 84, + 0x5AA: 84, + 0x5AB: 84, + 0x5AC: 84, + 0x5AD: 84, + 0x5AE: 84, + 0x5AF: 84, + 0x5B0: 84, + 0x5B1: 84, + 0x5B2: 84, + 0x5B3: 84, + 0x5B4: 84, + 0x5B5: 84, + 0x5B6: 84, + 0x5B7: 84, + 0x5B8: 84, + 0x5B9: 84, + 0x5BA: 84, + 0x5BB: 84, + 0x5BC: 84, + 0x5BD: 84, + 0x5BF: 84, + 0x5C1: 84, + 0x5C2: 84, + 0x5C4: 84, + 0x5C5: 84, + 0x5C7: 84, + 0x610: 84, + 0x611: 84, + 0x612: 84, + 0x613: 84, + 0x614: 84, + 0x615: 84, + 0x616: 84, + 0x617: 84, + 0x618: 84, + 0x619: 84, + 0x61A: 84, + 0x61C: 84, + 0x620: 68, + 0x622: 82, + 0x623: 82, + 0x624: 82, + 0x625: 82, + 0x626: 68, + 0x627: 82, + 0x628: 68, + 0x629: 82, + 0x62A: 68, + 0x62B: 68, + 0x62C: 68, + 0x62D: 68, + 0x62E: 68, + 0x62F: 82, + 0x630: 82, + 0x631: 82, + 0x632: 82, + 0x633: 68, + 0x634: 68, + 0x635: 68, + 0x636: 68, + 0x637: 68, + 0x638: 68, + 0x639: 68, + 0x63A: 68, + 0x63B: 68, + 0x63C: 68, + 0x63D: 68, + 0x63E: 68, + 0x63F: 68, + 0x640: 67, + 0x641: 68, + 0x642: 68, + 0x643: 68, + 0x644: 68, + 0x645: 68, + 0x646: 68, + 0x647: 68, + 0x648: 82, + 0x649: 68, + 0x64A: 68, + 0x64B: 84, + 0x64C: 84, + 0x64D: 84, + 0x64E: 84, + 0x64F: 84, + 0x650: 84, + 0x651: 84, + 0x652: 84, + 0x653: 84, + 0x654: 84, + 0x655: 84, + 0x656: 84, + 0x657: 84, + 0x658: 84, + 0x659: 84, + 0x65A: 84, + 0x65B: 84, + 0x65C: 84, + 0x65D: 84, + 0x65E: 84, + 0x65F: 84, + 0x66E: 68, + 0x66F: 68, + 0x670: 84, + 0x671: 82, + 0x672: 82, + 0x673: 82, + 0x675: 82, + 0x676: 82, + 0x677: 82, + 0x678: 68, + 0x679: 68, + 0x67A: 68, + 0x67B: 68, + 0x67C: 68, + 0x67D: 68, + 0x67E: 68, + 0x67F: 68, + 0x680: 68, + 0x681: 68, + 0x682: 68, + 0x683: 68, + 0x684: 68, + 0x685: 68, + 0x686: 68, + 0x687: 68, + 0x688: 82, + 0x689: 82, + 0x68A: 82, + 0x68B: 82, + 0x68C: 82, + 0x68D: 82, + 0x68E: 82, + 0x68F: 82, + 0x690: 82, + 0x691: 82, + 0x692: 82, + 0x693: 82, + 0x694: 82, + 0x695: 82, + 0x696: 82, + 0x697: 82, + 0x698: 82, + 0x699: 82, + 0x69A: 68, + 0x69B: 68, + 0x69C: 68, + 0x69D: 68, + 0x69E: 68, + 0x69F: 68, + 0x6A0: 68, + 0x6A1: 68, + 0x6A2: 68, + 0x6A3: 68, + 0x6A4: 68, + 0x6A5: 68, + 0x6A6: 68, + 0x6A7: 68, + 0x6A8: 68, + 0x6A9: 68, + 0x6AA: 68, + 0x6AB: 68, + 0x6AC: 68, + 0x6AD: 68, + 0x6AE: 68, + 0x6AF: 68, + 0x6B0: 68, + 0x6B1: 68, + 0x6B2: 68, + 0x6B3: 68, + 0x6B4: 68, + 0x6B5: 68, + 0x6B6: 68, + 0x6B7: 68, + 0x6B8: 68, + 0x6B9: 68, + 0x6BA: 68, + 0x6BB: 68, + 0x6BC: 68, + 0x6BD: 68, + 0x6BE: 68, + 0x6BF: 68, + 0x6C0: 82, + 0x6C1: 68, + 0x6C2: 68, + 0x6C3: 82, + 0x6C4: 82, + 0x6C5: 82, + 0x6C6: 82, + 0x6C7: 82, + 0x6C8: 82, + 0x6C9: 82, + 0x6CA: 82, + 0x6CB: 82, + 0x6CC: 68, + 0x6CD: 82, + 0x6CE: 68, + 0x6CF: 82, + 0x6D0: 68, + 0x6D1: 68, + 0x6D2: 82, + 0x6D3: 82, + 0x6D5: 82, + 0x6D6: 84, + 0x6D7: 84, + 0x6D8: 84, + 0x6D9: 84, + 0x6DA: 84, + 0x6DB: 84, + 0x6DC: 84, + 0x6DF: 84, + 0x6E0: 84, + 0x6E1: 84, + 0x6E2: 84, + 0x6E3: 84, + 0x6E4: 84, + 0x6E7: 84, + 0x6E8: 84, + 0x6EA: 84, + 0x6EB: 84, + 0x6EC: 84, + 0x6ED: 84, + 0x6EE: 82, + 0x6EF: 82, + 0x6FA: 68, + 0x6FB: 68, + 0x6FC: 68, + 0x6FF: 68, + 0x70F: 84, + 0x710: 82, + 0x711: 84, + 0x712: 68, + 0x713: 68, + 0x714: 68, + 0x715: 82, + 0x716: 82, + 0x717: 82, + 0x718: 82, + 0x719: 82, + 0x71A: 68, + 0x71B: 68, + 0x71C: 68, + 0x71D: 68, + 0x71E: 82, + 0x71F: 68, + 0x720: 68, + 0x721: 68, + 0x722: 68, + 0x723: 68, + 0x724: 68, + 0x725: 68, + 0x726: 68, + 0x727: 68, + 0x728: 82, + 0x729: 68, + 0x72A: 82, + 0x72B: 68, + 0x72C: 82, + 0x72D: 68, + 0x72E: 68, + 0x72F: 82, + 0x730: 84, + 0x731: 84, + 0x732: 84, + 0x733: 84, + 0x734: 84, + 0x735: 84, + 0x736: 84, + 0x737: 84, + 0x738: 84, + 0x739: 84, + 0x73A: 84, + 0x73B: 84, + 0x73C: 84, + 0x73D: 84, + 0x73E: 84, + 0x73F: 84, + 0x740: 84, + 0x741: 84, + 0x742: 84, + 0x743: 84, + 0x744: 84, + 0x745: 84, + 0x746: 84, + 0x747: 84, + 0x748: 84, + 0x749: 84, + 0x74A: 84, + 0x74D: 82, + 0x74E: 68, + 0x74F: 68, + 0x750: 68, + 0x751: 68, + 0x752: 68, + 0x753: 68, + 0x754: 68, + 0x755: 68, + 0x756: 68, + 0x757: 68, + 0x758: 68, + 0x759: 82, + 0x75A: 82, + 0x75B: 82, + 0x75C: 68, + 0x75D: 68, + 0x75E: 68, + 0x75F: 68, + 0x760: 68, + 0x761: 68, + 0x762: 68, + 0x763: 68, + 0x764: 68, + 0x765: 68, + 0x766: 68, + 0x767: 68, + 0x768: 68, + 0x769: 68, + 0x76A: 68, + 0x76B: 82, + 0x76C: 82, + 0x76D: 68, + 0x76E: 68, + 0x76F: 68, + 0x770: 68, + 0x771: 82, + 0x772: 68, + 0x773: 82, + 0x774: 82, + 0x775: 68, + 0x776: 68, + 0x777: 68, + 0x778: 82, + 0x779: 82, + 0x77A: 68, + 0x77B: 68, + 0x77C: 68, + 0x77D: 68, + 0x77E: 68, + 0x77F: 68, + 0x7A6: 84, + 0x7A7: 84, + 0x7A8: 84, + 0x7A9: 84, + 0x7AA: 84, + 0x7AB: 84, + 0x7AC: 84, + 0x7AD: 84, + 0x7AE: 84, + 0x7AF: 84, + 0x7B0: 84, + 0x7CA: 68, + 0x7CB: 68, + 0x7CC: 68, + 0x7CD: 68, + 0x7CE: 68, + 0x7CF: 68, + 0x7D0: 68, + 0x7D1: 68, + 0x7D2: 68, + 0x7D3: 68, + 0x7D4: 68, + 0x7D5: 68, + 0x7D6: 68, + 0x7D7: 68, + 0x7D8: 68, + 0x7D9: 68, + 0x7DA: 68, + 0x7DB: 68, + 0x7DC: 68, + 0x7DD: 68, + 0x7DE: 68, + 0x7DF: 68, + 0x7E0: 68, + 0x7E1: 68, + 0x7E2: 68, + 0x7E3: 68, + 0x7E4: 68, + 0x7E5: 68, + 0x7E6: 68, + 0x7E7: 68, + 0x7E8: 68, + 0x7E9: 68, + 0x7EA: 68, + 0x7EB: 84, + 0x7EC: 84, + 0x7ED: 84, + 0x7EE: 84, + 0x7EF: 84, + 0x7F0: 84, + 0x7F1: 84, + 0x7F2: 84, + 0x7F3: 84, + 0x7FA: 67, + 0x7FD: 84, + 0x816: 84, + 0x817: 84, + 0x818: 84, + 0x819: 84, + 0x81B: 84, + 0x81C: 84, + 0x81D: 84, + 0x81E: 84, + 0x81F: 84, + 0x820: 84, + 0x821: 84, + 0x822: 84, + 0x823: 84, + 0x825: 84, + 0x826: 84, + 0x827: 84, + 0x829: 84, + 0x82A: 84, + 0x82B: 84, + 0x82C: 84, + 0x82D: 84, + 0x840: 82, + 0x841: 68, + 0x842: 68, + 0x843: 68, + 0x844: 68, + 0x845: 68, + 0x846: 82, + 0x847: 82, + 0x848: 68, + 0x849: 82, + 0x84A: 68, + 0x84B: 68, + 0x84C: 68, + 0x84D: 68, + 0x84E: 68, + 0x84F: 68, + 0x850: 68, + 0x851: 68, + 0x852: 68, + 0x853: 68, + 0x854: 82, + 0x855: 68, + 0x856: 82, + 0x857: 82, + 0x858: 82, + 0x859: 84, + 0x85A: 84, + 0x85B: 84, + 0x860: 68, + 0x862: 68, + 0x863: 68, + 0x864: 68, + 0x865: 68, + 0x867: 82, + 0x868: 68, + 0x869: 82, + 0x86A: 82, + 0x870: 82, + 0x871: 82, + 0x872: 82, + 0x873: 82, + 0x874: 82, + 0x875: 82, + 0x876: 82, + 0x877: 82, + 0x878: 82, + 0x879: 82, + 0x87A: 82, + 0x87B: 82, + 0x87C: 82, + 0x87D: 82, + 0x87E: 82, + 0x87F: 82, + 0x880: 82, + 0x881: 82, + 0x882: 82, + 0x883: 67, + 0x884: 67, + 0x885: 67, + 0x886: 68, + 0x889: 68, + 0x88A: 68, + 0x88B: 68, + 0x88C: 68, + 0x88D: 68, + 0x88E: 82, + 0x898: 84, + 0x899: 84, + 0x89A: 84, + 0x89B: 84, + 0x89C: 84, + 0x89D: 84, + 0x89E: 84, + 0x89F: 84, + 0x8A0: 68, + 0x8A1: 68, + 0x8A2: 68, + 0x8A3: 68, + 0x8A4: 68, + 0x8A5: 68, + 0x8A6: 68, + 0x8A7: 68, + 0x8A8: 68, + 0x8A9: 68, + 0x8AA: 82, + 0x8AB: 82, + 0x8AC: 82, + 0x8AE: 82, + 0x8AF: 68, + 0x8B0: 68, + 0x8B1: 82, + 0x8B2: 82, + 0x8B3: 68, + 0x8B4: 68, + 0x8B5: 68, + 0x8B6: 68, + 0x8B7: 68, + 0x8B8: 68, + 0x8B9: 82, + 0x8BA: 68, + 0x8BB: 68, + 0x8BC: 68, + 0x8BD: 68, + 0x8BE: 68, + 0x8BF: 68, + 0x8C0: 68, + 0x8C1: 68, + 0x8C2: 68, + 0x8C3: 68, + 0x8C4: 68, + 0x8C5: 68, + 0x8C6: 68, + 0x8C7: 68, + 0x8C8: 68, + 0x8CA: 84, + 0x8CB: 84, + 0x8CC: 84, + 0x8CD: 84, + 0x8CE: 84, + 0x8CF: 84, + 0x8D0: 84, + 0x8D1: 84, + 0x8D2: 84, + 0x8D3: 84, + 0x8D4: 84, + 0x8D5: 84, + 0x8D6: 84, + 0x8D7: 84, + 0x8D8: 84, + 0x8D9: 84, + 0x8DA: 84, + 0x8DB: 84, + 0x8DC: 84, + 0x8DD: 84, + 0x8DE: 84, + 0x8DF: 84, + 0x8E0: 84, + 0x8E1: 84, + 0x8E3: 84, + 0x8E4: 84, + 0x8E5: 84, + 0x8E6: 84, + 0x8E7: 84, + 0x8E8: 84, + 0x8E9: 84, + 0x8EA: 84, + 0x8EB: 84, + 0x8EC: 84, + 0x8ED: 84, + 0x8EE: 84, + 0x8EF: 84, + 0x8F0: 84, + 0x8F1: 84, + 0x8F2: 84, + 0x8F3: 84, + 0x8F4: 84, + 0x8F5: 84, + 0x8F6: 84, + 0x8F7: 84, + 0x8F8: 84, + 0x8F9: 84, + 0x8FA: 84, + 0x8FB: 84, + 0x8FC: 84, + 0x8FD: 84, + 0x8FE: 84, + 0x8FF: 84, + 0x900: 84, + 0x901: 84, + 0x902: 84, + 0x93A: 84, + 0x93C: 84, + 0x941: 84, + 0x942: 84, + 0x943: 84, + 0x944: 84, + 0x945: 84, + 0x946: 84, + 0x947: 84, + 0x948: 84, + 0x94D: 84, + 0x951: 84, + 0x952: 84, + 0x953: 84, + 0x954: 84, + 0x955: 84, + 0x956: 84, + 0x957: 84, + 0x962: 84, + 0x963: 84, + 0x981: 84, + 0x9BC: 84, + 0x9C1: 84, + 0x9C2: 84, + 0x9C3: 84, + 0x9C4: 84, + 0x9CD: 84, + 0x9E2: 84, + 0x9E3: 84, + 0x9FE: 84, + 0xA01: 84, + 0xA02: 84, + 0xA3C: 84, + 0xA41: 84, + 0xA42: 84, + 0xA47: 84, + 0xA48: 84, + 0xA4B: 84, + 0xA4C: 84, + 0xA4D: 84, + 0xA51: 84, + 0xA70: 84, + 0xA71: 84, + 0xA75: 84, + 0xA81: 84, + 0xA82: 84, + 0xABC: 84, + 0xAC1: 84, + 0xAC2: 84, + 0xAC3: 84, + 0xAC4: 84, + 0xAC5: 84, + 0xAC7: 84, + 0xAC8: 84, + 0xACD: 84, + 0xAE2: 84, + 0xAE3: 84, + 0xAFA: 84, + 0xAFB: 84, + 0xAFC: 84, + 0xAFD: 84, + 0xAFE: 84, + 0xAFF: 84, + 0xB01: 84, + 0xB3C: 84, + 0xB3F: 84, + 0xB41: 84, + 0xB42: 84, + 0xB43: 84, + 0xB44: 84, + 0xB4D: 84, + 0xB55: 84, + 0xB56: 84, + 0xB62: 84, + 0xB63: 84, + 0xB82: 84, + 0xBC0: 84, + 0xBCD: 84, + 0xC00: 84, + 0xC04: 84, + 0xC3C: 84, + 0xC3E: 84, + 0xC3F: 84, + 0xC40: 84, + 0xC46: 84, + 0xC47: 84, + 0xC48: 84, + 0xC4A: 84, + 0xC4B: 84, + 0xC4C: 84, + 0xC4D: 84, + 0xC55: 84, + 0xC56: 84, + 0xC62: 84, + 0xC63: 84, + 0xC81: 84, + 0xCBC: 84, + 0xCBF: 84, + 0xCC6: 84, + 0xCCC: 84, + 0xCCD: 84, + 0xCE2: 84, + 0xCE3: 84, + 0xD00: 84, + 0xD01: 84, + 0xD3B: 84, + 0xD3C: 84, + 0xD41: 84, + 0xD42: 84, + 0xD43: 84, + 0xD44: 84, + 0xD4D: 84, + 0xD62: 84, + 0xD63: 84, + 0xD81: 84, + 0xDCA: 84, + 0xDD2: 84, + 0xDD3: 84, + 0xDD4: 84, + 0xDD6: 84, + 0xE31: 84, + 0xE34: 84, + 0xE35: 84, + 0xE36: 84, + 0xE37: 84, + 0xE38: 84, + 0xE39: 84, + 0xE3A: 84, + 0xE47: 84, + 0xE48: 84, + 0xE49: 84, + 0xE4A: 84, + 0xE4B: 84, + 0xE4C: 84, + 0xE4D: 84, + 0xE4E: 84, + 0xEB1: 84, + 0xEB4: 84, + 0xEB5: 84, + 0xEB6: 84, + 0xEB7: 84, + 0xEB8: 84, + 0xEB9: 84, + 0xEBA: 84, + 0xEBB: 84, + 0xEBC: 84, + 0xEC8: 84, + 0xEC9: 84, + 0xECA: 84, + 0xECB: 84, + 0xECC: 84, + 0xECD: 84, + 0xECE: 84, + 0xF18: 84, + 0xF19: 84, + 0xF35: 84, + 0xF37: 84, + 0xF39: 84, + 0xF71: 84, + 0xF72: 84, + 0xF73: 84, + 0xF74: 84, + 0xF75: 84, + 0xF76: 84, + 0xF77: 84, + 0xF78: 84, + 0xF79: 84, + 0xF7A: 84, + 0xF7B: 84, + 0xF7C: 84, + 0xF7D: 84, + 0xF7E: 84, + 0xF80: 84, + 0xF81: 84, + 0xF82: 84, + 0xF83: 84, + 0xF84: 84, + 0xF86: 84, + 0xF87: 84, + 0xF8D: 84, + 0xF8E: 84, + 0xF8F: 84, + 0xF90: 84, + 0xF91: 84, + 0xF92: 84, + 0xF93: 84, + 0xF94: 84, + 0xF95: 84, + 0xF96: 84, + 0xF97: 84, + 0xF99: 84, + 0xF9A: 84, + 0xF9B: 84, + 0xF9C: 84, + 0xF9D: 84, + 0xF9E: 84, + 0xF9F: 84, + 0xFA0: 84, + 0xFA1: 84, + 0xFA2: 84, + 0xFA3: 84, + 0xFA4: 84, + 0xFA5: 84, + 0xFA6: 84, + 0xFA7: 84, + 0xFA8: 84, + 0xFA9: 84, + 0xFAA: 84, + 0xFAB: 84, + 0xFAC: 84, + 0xFAD: 84, + 0xFAE: 84, + 0xFAF: 84, + 0xFB0: 84, + 0xFB1: 84, + 0xFB2: 84, + 0xFB3: 84, + 0xFB4: 84, + 0xFB5: 84, + 0xFB6: 84, + 0xFB7: 84, + 0xFB8: 84, + 0xFB9: 84, + 0xFBA: 84, + 0xFBB: 84, + 0xFBC: 84, + 0xFC6: 84, + 0x102D: 84, + 0x102E: 84, + 0x102F: 84, + 0x1030: 84, + 0x1032: 84, + 0x1033: 84, + 0x1034: 84, + 0x1035: 84, + 0x1036: 84, + 0x1037: 84, + 0x1039: 84, + 0x103A: 84, + 0x103D: 84, + 0x103E: 84, + 0x1058: 84, + 0x1059: 84, + 0x105E: 84, + 0x105F: 84, + 0x1060: 84, + 0x1071: 84, + 0x1072: 84, + 0x1073: 84, + 0x1074: 84, + 0x1082: 84, + 0x1085: 84, + 0x1086: 84, + 0x108D: 84, + 0x109D: 84, + 0x135D: 84, + 0x135E: 84, + 0x135F: 84, + 0x1712: 84, + 0x1713: 84, + 0x1714: 84, + 0x1732: 84, + 0x1733: 84, + 0x1752: 84, + 0x1753: 84, + 0x1772: 84, + 0x1773: 84, + 0x17B4: 84, + 0x17B5: 84, + 0x17B7: 84, + 0x17B8: 84, + 0x17B9: 84, + 0x17BA: 84, + 0x17BB: 84, + 0x17BC: 84, + 0x17BD: 84, + 0x17C6: 84, + 0x17C9: 84, + 0x17CA: 84, + 0x17CB: 84, + 0x17CC: 84, + 0x17CD: 84, + 0x17CE: 84, + 0x17CF: 84, + 0x17D0: 84, + 0x17D1: 84, + 0x17D2: 84, + 0x17D3: 84, + 0x17DD: 84, + 0x1807: 68, + 0x180A: 67, + 0x180B: 84, + 0x180C: 84, + 0x180D: 84, + 0x180F: 84, + 0x1820: 68, + 0x1821: 68, + 0x1822: 68, + 0x1823: 68, + 0x1824: 68, + 0x1825: 68, + 0x1826: 68, + 0x1827: 68, + 0x1828: 68, + 0x1829: 68, + 0x182A: 68, + 0x182B: 68, + 0x182C: 68, + 0x182D: 68, + 0x182E: 68, + 0x182F: 68, + 0x1830: 68, + 0x1831: 68, + 0x1832: 68, + 0x1833: 68, + 0x1834: 68, + 0x1835: 68, + 0x1836: 68, + 0x1837: 68, + 0x1838: 68, + 0x1839: 68, + 0x183A: 68, + 0x183B: 68, + 0x183C: 68, + 0x183D: 68, + 0x183E: 68, + 0x183F: 68, + 0x1840: 68, + 0x1841: 68, + 0x1842: 68, + 0x1843: 68, + 0x1844: 68, + 0x1845: 68, + 0x1846: 68, + 0x1847: 68, + 0x1848: 68, + 0x1849: 68, + 0x184A: 68, + 0x184B: 68, + 0x184C: 68, + 0x184D: 68, + 0x184E: 68, + 0x184F: 68, + 0x1850: 68, + 0x1851: 68, + 0x1852: 68, + 0x1853: 68, + 0x1854: 68, + 0x1855: 68, + 0x1856: 68, + 0x1857: 68, + 0x1858: 68, + 0x1859: 68, + 0x185A: 68, + 0x185B: 68, + 0x185C: 68, + 0x185D: 68, + 0x185E: 68, + 0x185F: 68, + 0x1860: 68, + 0x1861: 68, + 0x1862: 68, + 0x1863: 68, + 0x1864: 68, + 0x1865: 68, + 0x1866: 68, + 0x1867: 68, + 0x1868: 68, + 0x1869: 68, + 0x186A: 68, + 0x186B: 68, + 0x186C: 68, + 0x186D: 68, + 0x186E: 68, + 0x186F: 68, + 0x1870: 68, + 0x1871: 68, + 0x1872: 68, + 0x1873: 68, + 0x1874: 68, + 0x1875: 68, + 0x1876: 68, + 0x1877: 68, + 0x1878: 68, + 0x1885: 84, + 0x1886: 84, + 0x1887: 68, + 0x1888: 68, + 0x1889: 68, + 0x188A: 68, + 0x188B: 68, + 0x188C: 68, + 0x188D: 68, + 0x188E: 68, + 0x188F: 68, + 0x1890: 68, + 0x1891: 68, + 0x1892: 68, + 0x1893: 68, + 0x1894: 68, + 0x1895: 68, + 0x1896: 68, + 0x1897: 68, + 0x1898: 68, + 0x1899: 68, + 0x189A: 68, + 0x189B: 68, + 0x189C: 68, + 0x189D: 68, + 0x189E: 68, + 0x189F: 68, + 0x18A0: 68, + 0x18A1: 68, + 0x18A2: 68, + 0x18A3: 68, + 0x18A4: 68, + 0x18A5: 68, + 0x18A6: 68, + 0x18A7: 68, + 0x18A8: 68, + 0x18A9: 84, + 0x18AA: 68, + 0x1920: 84, + 0x1921: 84, + 0x1922: 84, + 0x1927: 84, + 0x1928: 84, + 0x1932: 84, + 0x1939: 84, + 0x193A: 84, + 0x193B: 84, + 0x1A17: 84, + 0x1A18: 84, + 0x1A1B: 84, + 0x1A56: 84, + 0x1A58: 84, + 0x1A59: 84, + 0x1A5A: 84, + 0x1A5B: 84, + 0x1A5C: 84, + 0x1A5D: 84, + 0x1A5E: 84, + 0x1A60: 84, + 0x1A62: 84, + 0x1A65: 84, + 0x1A66: 84, + 0x1A67: 84, + 0x1A68: 84, + 0x1A69: 84, + 0x1A6A: 84, + 0x1A6B: 84, + 0x1A6C: 84, + 0x1A73: 84, + 0x1A74: 84, + 0x1A75: 84, + 0x1A76: 84, + 0x1A77: 84, + 0x1A78: 84, + 0x1A79: 84, + 0x1A7A: 84, + 0x1A7B: 84, + 0x1A7C: 84, + 0x1A7F: 84, + 0x1AB0: 84, + 0x1AB1: 84, + 0x1AB2: 84, + 0x1AB3: 84, + 0x1AB4: 84, + 0x1AB5: 84, + 0x1AB6: 84, + 0x1AB7: 84, + 0x1AB8: 84, + 0x1AB9: 84, + 0x1ABA: 84, + 0x1ABB: 84, + 0x1ABC: 84, + 0x1ABD: 84, + 0x1ABE: 84, + 0x1ABF: 84, + 0x1AC0: 84, + 0x1AC1: 84, + 0x1AC2: 84, + 0x1AC3: 84, + 0x1AC4: 84, + 0x1AC5: 84, + 0x1AC6: 84, + 0x1AC7: 84, + 0x1AC8: 84, + 0x1AC9: 84, + 0x1ACA: 84, + 0x1ACB: 84, + 0x1ACC: 84, + 0x1ACD: 84, + 0x1ACE: 84, + 0x1B00: 84, + 0x1B01: 84, + 0x1B02: 84, + 0x1B03: 84, + 0x1B34: 84, + 0x1B36: 84, + 0x1B37: 84, + 0x1B38: 84, + 0x1B39: 84, + 0x1B3A: 84, + 0x1B3C: 84, + 0x1B42: 84, + 0x1B6B: 84, + 0x1B6C: 84, + 0x1B6D: 84, + 0x1B6E: 84, + 0x1B6F: 84, + 0x1B70: 84, + 0x1B71: 84, + 0x1B72: 84, + 0x1B73: 84, + 0x1B80: 84, + 0x1B81: 84, + 0x1BA2: 84, + 0x1BA3: 84, + 0x1BA4: 84, + 0x1BA5: 84, + 0x1BA8: 84, + 0x1BA9: 84, + 0x1BAB: 84, + 0x1BAC: 84, + 0x1BAD: 84, + 0x1BE6: 84, + 0x1BE8: 84, + 0x1BE9: 84, + 0x1BED: 84, + 0x1BEF: 84, + 0x1BF0: 84, + 0x1BF1: 84, + 0x1C2C: 84, + 0x1C2D: 84, + 0x1C2E: 84, + 0x1C2F: 84, + 0x1C30: 84, + 0x1C31: 84, + 0x1C32: 84, + 0x1C33: 84, + 0x1C36: 84, + 0x1C37: 84, + 0x1CD0: 84, + 0x1CD1: 84, + 0x1CD2: 84, + 0x1CD4: 84, + 0x1CD5: 84, + 0x1CD6: 84, + 0x1CD7: 84, + 0x1CD8: 84, + 0x1CD9: 84, + 0x1CDA: 84, + 0x1CDB: 84, + 0x1CDC: 84, + 0x1CDD: 84, + 0x1CDE: 84, + 0x1CDF: 84, + 0x1CE0: 84, + 0x1CE2: 84, + 0x1CE3: 84, + 0x1CE4: 84, + 0x1CE5: 84, + 0x1CE6: 84, + 0x1CE7: 84, + 0x1CE8: 84, + 0x1CED: 84, + 0x1CF4: 84, + 0x1CF8: 84, + 0x1CF9: 84, + 0x1DC0: 84, + 0x1DC1: 84, + 0x1DC2: 84, + 0x1DC3: 84, + 0x1DC4: 84, + 0x1DC5: 84, + 0x1DC6: 84, + 0x1DC7: 84, + 0x1DC8: 84, + 0x1DC9: 84, + 0x1DCA: 84, + 0x1DCB: 84, + 0x1DCC: 84, + 0x1DCD: 84, + 0x1DCE: 84, + 0x1DCF: 84, + 0x1DD0: 84, + 0x1DD1: 84, + 0x1DD2: 84, + 0x1DD3: 84, + 0x1DD4: 84, + 0x1DD5: 84, + 0x1DD6: 84, + 0x1DD7: 84, + 0x1DD8: 84, + 0x1DD9: 84, + 0x1DDA: 84, + 0x1DDB: 84, + 0x1DDC: 84, + 0x1DDD: 84, + 0x1DDE: 84, + 0x1DDF: 84, + 0x1DE0: 84, + 0x1DE1: 84, + 0x1DE2: 84, + 0x1DE3: 84, + 0x1DE4: 84, + 0x1DE5: 84, + 0x1DE6: 84, + 0x1DE7: 84, + 0x1DE8: 84, + 0x1DE9: 84, + 0x1DEA: 84, + 0x1DEB: 84, + 0x1DEC: 84, + 0x1DED: 84, + 0x1DEE: 84, + 0x1DEF: 84, + 0x1DF0: 84, + 0x1DF1: 84, + 0x1DF2: 84, + 0x1DF3: 84, + 0x1DF4: 84, + 0x1DF5: 84, + 0x1DF6: 84, + 0x1DF7: 84, + 0x1DF8: 84, + 0x1DF9: 84, + 0x1DFA: 84, + 0x1DFB: 84, + 0x1DFC: 84, + 0x1DFD: 84, + 0x1DFE: 84, + 0x1DFF: 84, + 0x200B: 84, + 0x200D: 67, + 0x200E: 84, + 0x200F: 84, + 0x202A: 84, + 0x202B: 84, + 0x202C: 84, + 0x202D: 84, + 0x202E: 84, + 0x2060: 84, + 0x2061: 84, + 0x2062: 84, + 0x2063: 84, + 0x2064: 84, + 0x206A: 84, + 0x206B: 84, + 0x206C: 84, + 0x206D: 84, + 0x206E: 84, + 0x206F: 84, + 0x20D0: 84, + 0x20D1: 84, + 0x20D2: 84, + 0x20D3: 84, + 0x20D4: 84, + 0x20D5: 84, + 0x20D6: 84, + 0x20D7: 84, + 0x20D8: 84, + 0x20D9: 84, + 0x20DA: 84, + 0x20DB: 84, + 0x20DC: 84, + 0x20DD: 84, + 0x20DE: 84, + 0x20DF: 84, + 0x20E0: 84, + 0x20E1: 84, + 0x20E2: 84, + 0x20E3: 84, + 0x20E4: 84, + 0x20E5: 84, + 0x20E6: 84, + 0x20E7: 84, + 0x20E8: 84, + 0x20E9: 84, + 0x20EA: 84, + 0x20EB: 84, + 0x20EC: 84, + 0x20ED: 84, + 0x20EE: 84, + 0x20EF: 84, + 0x20F0: 84, + 0x2CEF: 84, + 0x2CF0: 84, + 0x2CF1: 84, + 0x2D7F: 84, + 0x2DE0: 84, + 0x2DE1: 84, + 0x2DE2: 84, + 0x2DE3: 84, + 0x2DE4: 84, + 0x2DE5: 84, + 0x2DE6: 84, + 0x2DE7: 84, + 0x2DE8: 84, + 0x2DE9: 84, + 0x2DEA: 84, + 0x2DEB: 84, + 0x2DEC: 84, + 0x2DED: 84, + 0x2DEE: 84, + 0x2DEF: 84, + 0x2DF0: 84, + 0x2DF1: 84, + 0x2DF2: 84, + 0x2DF3: 84, + 0x2DF4: 84, + 0x2DF5: 84, + 0x2DF6: 84, + 0x2DF7: 84, + 0x2DF8: 84, + 0x2DF9: 84, + 0x2DFA: 84, + 0x2DFB: 84, + 0x2DFC: 84, + 0x2DFD: 84, + 0x2DFE: 84, + 0x2DFF: 84, + 0x302A: 84, + 0x302B: 84, + 0x302C: 84, + 0x302D: 84, + 0x3099: 84, + 0x309A: 84, + 0xA66F: 84, + 0xA670: 84, + 0xA671: 84, + 0xA672: 84, + 0xA674: 84, + 0xA675: 84, + 0xA676: 84, + 0xA677: 84, + 0xA678: 84, + 0xA679: 84, + 0xA67A: 84, + 0xA67B: 84, + 0xA67C: 84, + 0xA67D: 84, + 0xA69E: 84, + 0xA69F: 84, + 0xA6F0: 84, + 0xA6F1: 84, + 0xA802: 84, + 0xA806: 84, + 0xA80B: 84, + 0xA825: 84, + 0xA826: 84, + 0xA82C: 84, + 0xA840: 68, + 0xA841: 68, + 0xA842: 68, + 0xA843: 68, + 0xA844: 68, + 0xA845: 68, + 0xA846: 68, + 0xA847: 68, + 0xA848: 68, + 0xA849: 68, + 0xA84A: 68, + 0xA84B: 68, + 0xA84C: 68, + 0xA84D: 68, + 0xA84E: 68, + 0xA84F: 68, + 0xA850: 68, + 0xA851: 68, + 0xA852: 68, + 0xA853: 68, + 0xA854: 68, + 0xA855: 68, + 0xA856: 68, + 0xA857: 68, + 0xA858: 68, + 0xA859: 68, + 0xA85A: 68, + 0xA85B: 68, + 0xA85C: 68, + 0xA85D: 68, + 0xA85E: 68, + 0xA85F: 68, + 0xA860: 68, + 0xA861: 68, + 0xA862: 68, + 0xA863: 68, + 0xA864: 68, + 0xA865: 68, + 0xA866: 68, + 0xA867: 68, + 0xA868: 68, + 0xA869: 68, + 0xA86A: 68, + 0xA86B: 68, + 0xA86C: 68, + 0xA86D: 68, + 0xA86E: 68, + 0xA86F: 68, + 0xA870: 68, + 0xA871: 68, + 0xA872: 76, + 0xA8C4: 84, + 0xA8C5: 84, + 0xA8E0: 84, + 0xA8E1: 84, + 0xA8E2: 84, + 0xA8E3: 84, + 0xA8E4: 84, + 0xA8E5: 84, + 0xA8E6: 84, + 0xA8E7: 84, + 0xA8E8: 84, + 0xA8E9: 84, + 0xA8EA: 84, + 0xA8EB: 84, + 0xA8EC: 84, + 0xA8ED: 84, + 0xA8EE: 84, + 0xA8EF: 84, + 0xA8F0: 84, + 0xA8F1: 84, + 0xA8FF: 84, + 0xA926: 84, + 0xA927: 84, + 0xA928: 84, + 0xA929: 84, + 0xA92A: 84, + 0xA92B: 84, + 0xA92C: 84, + 0xA92D: 84, + 0xA947: 84, + 0xA948: 84, + 0xA949: 84, + 0xA94A: 84, + 0xA94B: 84, + 0xA94C: 84, + 0xA94D: 84, + 0xA94E: 84, + 0xA94F: 84, + 0xA950: 84, + 0xA951: 84, + 0xA980: 84, + 0xA981: 84, + 0xA982: 84, + 0xA9B3: 84, + 0xA9B6: 84, + 0xA9B7: 84, + 0xA9B8: 84, + 0xA9B9: 84, + 0xA9BC: 84, + 0xA9BD: 84, + 0xA9E5: 84, + 0xAA29: 84, + 0xAA2A: 84, + 0xAA2B: 84, + 0xAA2C: 84, + 0xAA2D: 84, + 0xAA2E: 84, + 0xAA31: 84, + 0xAA32: 84, + 0xAA35: 84, + 0xAA36: 84, + 0xAA43: 84, + 0xAA4C: 84, + 0xAA7C: 84, + 0xAAB0: 84, + 0xAAB2: 84, + 0xAAB3: 84, + 0xAAB4: 84, + 0xAAB7: 84, + 0xAAB8: 84, + 0xAABE: 84, + 0xAABF: 84, + 0xAAC1: 84, + 0xAAEC: 84, + 0xAAED: 84, + 0xAAF6: 84, + 0xABE5: 84, + 0xABE8: 84, + 0xABED: 84, + 0xFB1E: 84, + 0xFE00: 84, + 0xFE01: 84, + 0xFE02: 84, + 0xFE03: 84, + 0xFE04: 84, + 0xFE05: 84, + 0xFE06: 84, + 0xFE07: 84, + 0xFE08: 84, + 0xFE09: 84, + 0xFE0A: 84, + 0xFE0B: 84, + 0xFE0C: 84, + 0xFE0D: 84, + 0xFE0E: 84, + 0xFE0F: 84, + 0xFE20: 84, + 0xFE21: 84, + 0xFE22: 84, + 0xFE23: 84, + 0xFE24: 84, + 0xFE25: 84, + 0xFE26: 84, + 0xFE27: 84, + 0xFE28: 84, + 0xFE29: 84, + 0xFE2A: 84, + 0xFE2B: 84, + 0xFE2C: 84, + 0xFE2D: 84, + 0xFE2E: 84, + 0xFE2F: 84, + 0xFEFF: 84, + 0xFFF9: 84, + 0xFFFA: 84, + 0xFFFB: 84, + 0x101FD: 84, + 0x102E0: 84, + 0x10376: 84, + 0x10377: 84, + 0x10378: 84, + 0x10379: 84, + 0x1037A: 84, + 0x10A01: 84, + 0x10A02: 84, + 0x10A03: 84, + 0x10A05: 84, + 0x10A06: 84, + 0x10A0C: 84, + 0x10A0D: 84, + 0x10A0E: 84, + 0x10A0F: 84, + 0x10A38: 84, + 0x10A39: 84, + 0x10A3A: 84, + 0x10A3F: 84, + 0x10AC0: 68, + 0x10AC1: 68, + 0x10AC2: 68, + 0x10AC3: 68, + 0x10AC4: 68, + 0x10AC5: 82, + 0x10AC7: 82, + 0x10AC9: 82, + 0x10ACA: 82, + 0x10ACD: 76, + 0x10ACE: 82, + 0x10ACF: 82, + 0x10AD0: 82, + 0x10AD1: 82, + 0x10AD2: 82, + 0x10AD3: 68, + 0x10AD4: 68, + 0x10AD5: 68, + 0x10AD6: 68, + 0x10AD7: 76, + 0x10AD8: 68, + 0x10AD9: 68, + 0x10ADA: 68, + 0x10ADB: 68, + 0x10ADC: 68, + 0x10ADD: 82, + 0x10ADE: 68, + 0x10ADF: 68, + 0x10AE0: 68, + 0x10AE1: 82, + 0x10AE4: 82, + 0x10AE5: 84, + 0x10AE6: 84, + 0x10AEB: 68, + 0x10AEC: 68, + 0x10AED: 68, + 0x10AEE: 68, + 0x10AEF: 82, + 0x10B80: 68, + 0x10B81: 82, + 0x10B82: 68, + 0x10B83: 82, + 0x10B84: 82, + 0x10B85: 82, + 0x10B86: 68, + 0x10B87: 68, + 0x10B88: 68, + 0x10B89: 82, + 0x10B8A: 68, + 0x10B8B: 68, + 0x10B8C: 82, + 0x10B8D: 68, + 0x10B8E: 82, + 0x10B8F: 82, + 0x10B90: 68, + 0x10B91: 82, + 0x10BA9: 82, + 0x10BAA: 82, + 0x10BAB: 82, + 0x10BAC: 82, + 0x10BAD: 68, + 0x10BAE: 68, + 0x10D00: 76, + 0x10D01: 68, + 0x10D02: 68, + 0x10D03: 68, + 0x10D04: 68, + 0x10D05: 68, + 0x10D06: 68, + 0x10D07: 68, + 0x10D08: 68, + 0x10D09: 68, + 0x10D0A: 68, + 0x10D0B: 68, + 0x10D0C: 68, + 0x10D0D: 68, + 0x10D0E: 68, + 0x10D0F: 68, + 0x10D10: 68, + 0x10D11: 68, + 0x10D12: 68, + 0x10D13: 68, + 0x10D14: 68, + 0x10D15: 68, + 0x10D16: 68, + 0x10D17: 68, + 0x10D18: 68, + 0x10D19: 68, + 0x10D1A: 68, + 0x10D1B: 68, + 0x10D1C: 68, + 0x10D1D: 68, + 0x10D1E: 68, + 0x10D1F: 68, + 0x10D20: 68, + 0x10D21: 68, + 0x10D22: 82, + 0x10D23: 68, + 0x10D24: 84, + 0x10D25: 84, + 0x10D26: 84, + 0x10D27: 84, + 0x10EAB: 84, + 0x10EAC: 84, + 0x10EFD: 84, + 0x10EFE: 84, + 0x10EFF: 84, + 0x10F30: 68, + 0x10F31: 68, + 0x10F32: 68, + 0x10F33: 82, + 0x10F34: 68, + 0x10F35: 68, + 0x10F36: 68, + 0x10F37: 68, + 0x10F38: 68, + 0x10F39: 68, + 0x10F3A: 68, + 0x10F3B: 68, + 0x10F3C: 68, + 0x10F3D: 68, + 0x10F3E: 68, + 0x10F3F: 68, + 0x10F40: 68, + 0x10F41: 68, + 0x10F42: 68, + 0x10F43: 68, + 0x10F44: 68, + 0x10F46: 84, + 0x10F47: 84, + 0x10F48: 84, + 0x10F49: 84, + 0x10F4A: 84, + 0x10F4B: 84, + 0x10F4C: 84, + 0x10F4D: 84, + 0x10F4E: 84, + 0x10F4F: 84, + 0x10F50: 84, + 0x10F51: 68, + 0x10F52: 68, + 0x10F53: 68, + 0x10F54: 82, + 0x10F70: 68, + 0x10F71: 68, + 0x10F72: 68, + 0x10F73: 68, + 0x10F74: 82, + 0x10F75: 82, + 0x10F76: 68, + 0x10F77: 68, + 0x10F78: 68, + 0x10F79: 68, + 0x10F7A: 68, + 0x10F7B: 68, + 0x10F7C: 68, + 0x10F7D: 68, + 0x10F7E: 68, + 0x10F7F: 68, + 0x10F80: 68, + 0x10F81: 68, + 0x10F82: 84, + 0x10F83: 84, + 0x10F84: 84, + 0x10F85: 84, + 0x10FB0: 68, + 0x10FB2: 68, + 0x10FB3: 68, + 0x10FB4: 82, + 0x10FB5: 82, + 0x10FB6: 82, + 0x10FB8: 68, + 0x10FB9: 82, + 0x10FBA: 82, + 0x10FBB: 68, + 0x10FBC: 68, + 0x10FBD: 82, + 0x10FBE: 68, + 0x10FBF: 68, + 0x10FC1: 68, + 0x10FC2: 82, + 0x10FC3: 82, + 0x10FC4: 68, + 0x10FC9: 82, + 0x10FCA: 68, + 0x10FCB: 76, + 0x11001: 84, + 0x11038: 84, + 0x11039: 84, + 0x1103A: 84, + 0x1103B: 84, + 0x1103C: 84, + 0x1103D: 84, + 0x1103E: 84, + 0x1103F: 84, + 0x11040: 84, + 0x11041: 84, + 0x11042: 84, + 0x11043: 84, + 0x11044: 84, + 0x11045: 84, + 0x11046: 84, + 0x11070: 84, + 0x11073: 84, + 0x11074: 84, + 0x1107F: 84, + 0x11080: 84, + 0x11081: 84, + 0x110B3: 84, + 0x110B4: 84, + 0x110B5: 84, + 0x110B6: 84, + 0x110B9: 84, + 0x110BA: 84, + 0x110C2: 84, + 0x11100: 84, + 0x11101: 84, + 0x11102: 84, + 0x11127: 84, + 0x11128: 84, + 0x11129: 84, + 0x1112A: 84, + 0x1112B: 84, + 0x1112D: 84, + 0x1112E: 84, + 0x1112F: 84, + 0x11130: 84, + 0x11131: 84, + 0x11132: 84, + 0x11133: 84, + 0x11134: 84, + 0x11173: 84, + 0x11180: 84, + 0x11181: 84, + 0x111B6: 84, + 0x111B7: 84, + 0x111B8: 84, + 0x111B9: 84, + 0x111BA: 84, + 0x111BB: 84, + 0x111BC: 84, + 0x111BD: 84, + 0x111BE: 84, + 0x111C9: 84, + 0x111CA: 84, + 0x111CB: 84, + 0x111CC: 84, + 0x111CF: 84, + 0x1122F: 84, + 0x11230: 84, + 0x11231: 84, + 0x11234: 84, + 0x11236: 84, + 0x11237: 84, + 0x1123E: 84, + 0x11241: 84, + 0x112DF: 84, + 0x112E3: 84, + 0x112E4: 84, + 0x112E5: 84, + 0x112E6: 84, + 0x112E7: 84, + 0x112E8: 84, + 0x112E9: 84, + 0x112EA: 84, + 0x11300: 84, + 0x11301: 84, + 0x1133B: 84, + 0x1133C: 84, + 0x11340: 84, + 0x11366: 84, + 0x11367: 84, + 0x11368: 84, + 0x11369: 84, + 0x1136A: 84, + 0x1136B: 84, + 0x1136C: 84, + 0x11370: 84, + 0x11371: 84, + 0x11372: 84, + 0x11373: 84, + 0x11374: 84, + 0x11438: 84, + 0x11439: 84, + 0x1143A: 84, + 0x1143B: 84, + 0x1143C: 84, + 0x1143D: 84, + 0x1143E: 84, + 0x1143F: 84, + 0x11442: 84, + 0x11443: 84, + 0x11444: 84, + 0x11446: 84, + 0x1145E: 84, + 0x114B3: 84, + 0x114B4: 84, + 0x114B5: 84, + 0x114B6: 84, + 0x114B7: 84, + 0x114B8: 84, + 0x114BA: 84, + 0x114BF: 84, + 0x114C0: 84, + 0x114C2: 84, + 0x114C3: 84, + 0x115B2: 84, + 0x115B3: 84, + 0x115B4: 84, + 0x115B5: 84, + 0x115BC: 84, + 0x115BD: 84, + 0x115BF: 84, + 0x115C0: 84, + 0x115DC: 84, + 0x115DD: 84, + 0x11633: 84, + 0x11634: 84, + 0x11635: 84, + 0x11636: 84, + 0x11637: 84, + 0x11638: 84, + 0x11639: 84, + 0x1163A: 84, + 0x1163D: 84, + 0x1163F: 84, + 0x11640: 84, + 0x116AB: 84, + 0x116AD: 84, + 0x116B0: 84, + 0x116B1: 84, + 0x116B2: 84, + 0x116B3: 84, + 0x116B4: 84, + 0x116B5: 84, + 0x116B7: 84, + 0x1171D: 84, + 0x1171E: 84, + 0x1171F: 84, + 0x11722: 84, + 0x11723: 84, + 0x11724: 84, + 0x11725: 84, + 0x11727: 84, + 0x11728: 84, + 0x11729: 84, + 0x1172A: 84, + 0x1172B: 84, + 0x1182F: 84, + 0x11830: 84, + 0x11831: 84, + 0x11832: 84, + 0x11833: 84, + 0x11834: 84, + 0x11835: 84, + 0x11836: 84, + 0x11837: 84, + 0x11839: 84, + 0x1183A: 84, + 0x1193B: 84, + 0x1193C: 84, + 0x1193E: 84, + 0x11943: 84, + 0x119D4: 84, + 0x119D5: 84, + 0x119D6: 84, + 0x119D7: 84, + 0x119DA: 84, + 0x119DB: 84, + 0x119E0: 84, + 0x11A01: 84, + 0x11A02: 84, + 0x11A03: 84, + 0x11A04: 84, + 0x11A05: 84, + 0x11A06: 84, + 0x11A07: 84, + 0x11A08: 84, + 0x11A09: 84, + 0x11A0A: 84, + 0x11A33: 84, + 0x11A34: 84, + 0x11A35: 84, + 0x11A36: 84, + 0x11A37: 84, + 0x11A38: 84, + 0x11A3B: 84, + 0x11A3C: 84, + 0x11A3D: 84, + 0x11A3E: 84, + 0x11A47: 84, + 0x11A51: 84, + 0x11A52: 84, + 0x11A53: 84, + 0x11A54: 84, + 0x11A55: 84, + 0x11A56: 84, + 0x11A59: 84, + 0x11A5A: 84, + 0x11A5B: 84, + 0x11A8A: 84, + 0x11A8B: 84, + 0x11A8C: 84, + 0x11A8D: 84, + 0x11A8E: 84, + 0x11A8F: 84, + 0x11A90: 84, + 0x11A91: 84, + 0x11A92: 84, + 0x11A93: 84, + 0x11A94: 84, + 0x11A95: 84, + 0x11A96: 84, + 0x11A98: 84, + 0x11A99: 84, + 0x11C30: 84, + 0x11C31: 84, + 0x11C32: 84, + 0x11C33: 84, + 0x11C34: 84, + 0x11C35: 84, + 0x11C36: 84, + 0x11C38: 84, + 0x11C39: 84, + 0x11C3A: 84, + 0x11C3B: 84, + 0x11C3C: 84, + 0x11C3D: 84, + 0x11C3F: 84, + 0x11C92: 84, + 0x11C93: 84, + 0x11C94: 84, + 0x11C95: 84, + 0x11C96: 84, + 0x11C97: 84, + 0x11C98: 84, + 0x11C99: 84, + 0x11C9A: 84, + 0x11C9B: 84, + 0x11C9C: 84, + 0x11C9D: 84, + 0x11C9E: 84, + 0x11C9F: 84, + 0x11CA0: 84, + 0x11CA1: 84, + 0x11CA2: 84, + 0x11CA3: 84, + 0x11CA4: 84, + 0x11CA5: 84, + 0x11CA6: 84, + 0x11CA7: 84, + 0x11CAA: 84, + 0x11CAB: 84, + 0x11CAC: 84, + 0x11CAD: 84, + 0x11CAE: 84, + 0x11CAF: 84, + 0x11CB0: 84, + 0x11CB2: 84, + 0x11CB3: 84, + 0x11CB5: 84, + 0x11CB6: 84, + 0x11D31: 84, + 0x11D32: 84, + 0x11D33: 84, + 0x11D34: 84, + 0x11D35: 84, + 0x11D36: 84, + 0x11D3A: 84, + 0x11D3C: 84, + 0x11D3D: 84, + 0x11D3F: 84, + 0x11D40: 84, + 0x11D41: 84, + 0x11D42: 84, + 0x11D43: 84, + 0x11D44: 84, + 0x11D45: 84, + 0x11D47: 84, + 0x11D90: 84, + 0x11D91: 84, + 0x11D95: 84, + 0x11D97: 84, + 0x11EF3: 84, + 0x11EF4: 84, + 0x11F00: 84, + 0x11F01: 84, + 0x11F36: 84, + 0x11F37: 84, + 0x11F38: 84, + 0x11F39: 84, + 0x11F3A: 84, + 0x11F40: 84, + 0x11F42: 84, + 0x13430: 84, + 0x13431: 84, + 0x13432: 84, + 0x13433: 84, + 0x13434: 84, + 0x13435: 84, + 0x13436: 84, + 0x13437: 84, + 0x13438: 84, + 0x13439: 84, + 0x1343A: 84, + 0x1343B: 84, + 0x1343C: 84, + 0x1343D: 84, + 0x1343E: 84, + 0x1343F: 84, + 0x13440: 84, + 0x13447: 84, + 0x13448: 84, + 0x13449: 84, + 0x1344A: 84, + 0x1344B: 84, + 0x1344C: 84, + 0x1344D: 84, + 0x1344E: 84, + 0x1344F: 84, + 0x13450: 84, + 0x13451: 84, + 0x13452: 84, + 0x13453: 84, + 0x13454: 84, + 0x13455: 84, + 0x16AF0: 84, + 0x16AF1: 84, + 0x16AF2: 84, + 0x16AF3: 84, + 0x16AF4: 84, + 0x16B30: 84, + 0x16B31: 84, + 0x16B32: 84, + 0x16B33: 84, + 0x16B34: 84, + 0x16B35: 84, + 0x16B36: 84, + 0x16F4F: 84, + 0x16F8F: 84, + 0x16F90: 84, + 0x16F91: 84, + 0x16F92: 84, + 0x16FE4: 84, + 0x1BC9D: 84, + 0x1BC9E: 84, + 0x1BCA0: 84, + 0x1BCA1: 84, + 0x1BCA2: 84, + 0x1BCA3: 84, + 0x1CF00: 84, + 0x1CF01: 84, + 0x1CF02: 84, + 0x1CF03: 84, + 0x1CF04: 84, + 0x1CF05: 84, + 0x1CF06: 84, + 0x1CF07: 84, + 0x1CF08: 84, + 0x1CF09: 84, + 0x1CF0A: 84, + 0x1CF0B: 84, + 0x1CF0C: 84, + 0x1CF0D: 84, + 0x1CF0E: 84, + 0x1CF0F: 84, + 0x1CF10: 84, + 0x1CF11: 84, + 0x1CF12: 84, + 0x1CF13: 84, + 0x1CF14: 84, + 0x1CF15: 84, + 0x1CF16: 84, + 0x1CF17: 84, + 0x1CF18: 84, + 0x1CF19: 84, + 0x1CF1A: 84, + 0x1CF1B: 84, + 0x1CF1C: 84, + 0x1CF1D: 84, + 0x1CF1E: 84, + 0x1CF1F: 84, + 0x1CF20: 84, + 0x1CF21: 84, + 0x1CF22: 84, + 0x1CF23: 84, + 0x1CF24: 84, + 0x1CF25: 84, + 0x1CF26: 84, + 0x1CF27: 84, + 0x1CF28: 84, + 0x1CF29: 84, + 0x1CF2A: 84, + 0x1CF2B: 84, + 0x1CF2C: 84, + 0x1CF2D: 84, + 0x1CF30: 84, + 0x1CF31: 84, + 0x1CF32: 84, + 0x1CF33: 84, + 0x1CF34: 84, + 0x1CF35: 84, + 0x1CF36: 84, + 0x1CF37: 84, + 0x1CF38: 84, + 0x1CF39: 84, + 0x1CF3A: 84, + 0x1CF3B: 84, + 0x1CF3C: 84, + 0x1CF3D: 84, + 0x1CF3E: 84, + 0x1CF3F: 84, + 0x1CF40: 84, + 0x1CF41: 84, + 0x1CF42: 84, + 0x1CF43: 84, + 0x1CF44: 84, + 0x1CF45: 84, + 0x1CF46: 84, + 0x1D167: 84, + 0x1D168: 84, + 0x1D169: 84, + 0x1D173: 84, + 0x1D174: 84, + 0x1D175: 84, + 0x1D176: 84, + 0x1D177: 84, + 0x1D178: 84, + 0x1D179: 84, + 0x1D17A: 84, + 0x1D17B: 84, + 0x1D17C: 84, + 0x1D17D: 84, + 0x1D17E: 84, + 0x1D17F: 84, + 0x1D180: 84, + 0x1D181: 84, + 0x1D182: 84, + 0x1D185: 84, + 0x1D186: 84, + 0x1D187: 84, + 0x1D188: 84, + 0x1D189: 84, + 0x1D18A: 84, + 0x1D18B: 84, + 0x1D1AA: 84, + 0x1D1AB: 84, + 0x1D1AC: 84, + 0x1D1AD: 84, + 0x1D242: 84, + 0x1D243: 84, + 0x1D244: 84, + 0x1DA00: 84, + 0x1DA01: 84, + 0x1DA02: 84, + 0x1DA03: 84, + 0x1DA04: 84, + 0x1DA05: 84, + 0x1DA06: 84, + 0x1DA07: 84, + 0x1DA08: 84, + 0x1DA09: 84, + 0x1DA0A: 84, + 0x1DA0B: 84, + 0x1DA0C: 84, + 0x1DA0D: 84, + 0x1DA0E: 84, + 0x1DA0F: 84, + 0x1DA10: 84, + 0x1DA11: 84, + 0x1DA12: 84, + 0x1DA13: 84, + 0x1DA14: 84, + 0x1DA15: 84, + 0x1DA16: 84, + 0x1DA17: 84, + 0x1DA18: 84, + 0x1DA19: 84, + 0x1DA1A: 84, + 0x1DA1B: 84, + 0x1DA1C: 84, + 0x1DA1D: 84, + 0x1DA1E: 84, + 0x1DA1F: 84, + 0x1DA20: 84, + 0x1DA21: 84, + 0x1DA22: 84, + 0x1DA23: 84, + 0x1DA24: 84, + 0x1DA25: 84, + 0x1DA26: 84, + 0x1DA27: 84, + 0x1DA28: 84, + 0x1DA29: 84, + 0x1DA2A: 84, + 0x1DA2B: 84, + 0x1DA2C: 84, + 0x1DA2D: 84, + 0x1DA2E: 84, + 0x1DA2F: 84, + 0x1DA30: 84, + 0x1DA31: 84, + 0x1DA32: 84, + 0x1DA33: 84, + 0x1DA34: 84, + 0x1DA35: 84, + 0x1DA36: 84, + 0x1DA3B: 84, + 0x1DA3C: 84, + 0x1DA3D: 84, + 0x1DA3E: 84, + 0x1DA3F: 84, + 0x1DA40: 84, + 0x1DA41: 84, + 0x1DA42: 84, + 0x1DA43: 84, + 0x1DA44: 84, + 0x1DA45: 84, + 0x1DA46: 84, + 0x1DA47: 84, + 0x1DA48: 84, + 0x1DA49: 84, + 0x1DA4A: 84, + 0x1DA4B: 84, + 0x1DA4C: 84, + 0x1DA4D: 84, + 0x1DA4E: 84, + 0x1DA4F: 84, + 0x1DA50: 84, + 0x1DA51: 84, + 0x1DA52: 84, + 0x1DA53: 84, + 0x1DA54: 84, + 0x1DA55: 84, + 0x1DA56: 84, + 0x1DA57: 84, + 0x1DA58: 84, + 0x1DA59: 84, + 0x1DA5A: 84, + 0x1DA5B: 84, + 0x1DA5C: 84, + 0x1DA5D: 84, + 0x1DA5E: 84, + 0x1DA5F: 84, + 0x1DA60: 84, + 0x1DA61: 84, + 0x1DA62: 84, + 0x1DA63: 84, + 0x1DA64: 84, + 0x1DA65: 84, + 0x1DA66: 84, + 0x1DA67: 84, + 0x1DA68: 84, + 0x1DA69: 84, + 0x1DA6A: 84, + 0x1DA6B: 84, + 0x1DA6C: 84, + 0x1DA75: 84, + 0x1DA84: 84, + 0x1DA9B: 84, + 0x1DA9C: 84, + 0x1DA9D: 84, + 0x1DA9E: 84, + 0x1DA9F: 84, + 0x1DAA1: 84, + 0x1DAA2: 84, + 0x1DAA3: 84, + 0x1DAA4: 84, + 0x1DAA5: 84, + 0x1DAA6: 84, + 0x1DAA7: 84, + 0x1DAA8: 84, + 0x1DAA9: 84, + 0x1DAAA: 84, + 0x1DAAB: 84, + 0x1DAAC: 84, + 0x1DAAD: 84, + 0x1DAAE: 84, + 0x1DAAF: 84, + 0x1E000: 84, + 0x1E001: 84, + 0x1E002: 84, + 0x1E003: 84, + 0x1E004: 84, + 0x1E005: 84, + 0x1E006: 84, + 0x1E008: 84, + 0x1E009: 84, + 0x1E00A: 84, + 0x1E00B: 84, + 0x1E00C: 84, + 0x1E00D: 84, + 0x1E00E: 84, + 0x1E00F: 84, + 0x1E010: 84, + 0x1E011: 84, + 0x1E012: 84, + 0x1E013: 84, + 0x1E014: 84, + 0x1E015: 84, + 0x1E016: 84, + 0x1E017: 84, + 0x1E018: 84, + 0x1E01B: 84, + 0x1E01C: 84, + 0x1E01D: 84, + 0x1E01E: 84, + 0x1E01F: 84, + 0x1E020: 84, + 0x1E021: 84, + 0x1E023: 84, + 0x1E024: 84, + 0x1E026: 84, + 0x1E027: 84, + 0x1E028: 84, + 0x1E029: 84, + 0x1E02A: 84, + 0x1E08F: 84, + 0x1E130: 84, + 0x1E131: 84, + 0x1E132: 84, + 0x1E133: 84, + 0x1E134: 84, + 0x1E135: 84, + 0x1E136: 84, + 0x1E2AE: 84, + 0x1E2EC: 84, + 0x1E2ED: 84, + 0x1E2EE: 84, + 0x1E2EF: 84, + 0x1E4EC: 84, + 0x1E4ED: 84, + 0x1E4EE: 84, + 0x1E4EF: 84, + 0x1E8D0: 84, + 0x1E8D1: 84, + 0x1E8D2: 84, + 0x1E8D3: 84, + 0x1E8D4: 84, + 0x1E8D5: 84, + 0x1E8D6: 84, + 0x1E900: 68, + 0x1E901: 68, + 0x1E902: 68, + 0x1E903: 68, + 0x1E904: 68, + 0x1E905: 68, + 0x1E906: 68, + 0x1E907: 68, + 0x1E908: 68, + 0x1E909: 68, + 0x1E90A: 68, + 0x1E90B: 68, + 0x1E90C: 68, + 0x1E90D: 68, + 0x1E90E: 68, + 0x1E90F: 68, + 0x1E910: 68, + 0x1E911: 68, + 0x1E912: 68, + 0x1E913: 68, + 0x1E914: 68, + 0x1E915: 68, + 0x1E916: 68, + 0x1E917: 68, + 0x1E918: 68, + 0x1E919: 68, + 0x1E91A: 68, + 0x1E91B: 68, + 0x1E91C: 68, + 0x1E91D: 68, + 0x1E91E: 68, + 0x1E91F: 68, + 0x1E920: 68, + 0x1E921: 68, + 0x1E922: 68, + 0x1E923: 68, + 0x1E924: 68, + 0x1E925: 68, + 0x1E926: 68, + 0x1E927: 68, + 0x1E928: 68, + 0x1E929: 68, + 0x1E92A: 68, + 0x1E92B: 68, + 0x1E92C: 68, + 0x1E92D: 68, + 0x1E92E: 68, + 0x1E92F: 68, + 0x1E930: 68, + 0x1E931: 68, + 0x1E932: 68, + 0x1E933: 68, + 0x1E934: 68, + 0x1E935: 68, + 0x1E936: 68, + 0x1E937: 68, + 0x1E938: 68, + 0x1E939: 68, + 0x1E93A: 68, + 0x1E93B: 68, + 0x1E93C: 68, + 0x1E93D: 68, + 0x1E93E: 68, + 0x1E93F: 68, + 0x1E940: 68, + 0x1E941: 68, + 0x1E942: 68, + 0x1E943: 68, + 0x1E944: 84, + 0x1E945: 84, + 0x1E946: 84, + 0x1E947: 84, + 0x1E948: 84, + 0x1E949: 84, + 0x1E94A: 84, + 0x1E94B: 84, + 0xE0001: 84, + 0xE0020: 84, + 0xE0021: 84, + 0xE0022: 84, + 0xE0023: 84, + 0xE0024: 84, + 0xE0025: 84, + 0xE0026: 84, + 0xE0027: 84, + 0xE0028: 84, + 0xE0029: 84, + 0xE002A: 84, + 0xE002B: 84, + 0xE002C: 84, + 0xE002D: 84, + 0xE002E: 84, + 0xE002F: 84, + 0xE0030: 84, + 0xE0031: 84, + 0xE0032: 84, + 0xE0033: 84, + 0xE0034: 84, + 0xE0035: 84, + 0xE0036: 84, + 0xE0037: 84, + 0xE0038: 84, + 0xE0039: 84, + 0xE003A: 84, + 0xE003B: 84, + 0xE003C: 84, + 0xE003D: 84, + 0xE003E: 84, + 0xE003F: 84, + 0xE0040: 84, + 0xE0041: 84, + 0xE0042: 84, + 0xE0043: 84, + 0xE0044: 84, + 0xE0045: 84, + 0xE0046: 84, + 0xE0047: 84, + 0xE0048: 84, + 0xE0049: 84, + 0xE004A: 84, + 0xE004B: 84, + 0xE004C: 84, + 0xE004D: 84, + 0xE004E: 84, + 0xE004F: 84, + 0xE0050: 84, + 0xE0051: 84, + 0xE0052: 84, + 0xE0053: 84, + 0xE0054: 84, + 0xE0055: 84, + 0xE0056: 84, + 0xE0057: 84, + 0xE0058: 84, + 0xE0059: 84, + 0xE005A: 84, + 0xE005B: 84, + 0xE005C: 84, + 0xE005D: 84, + 0xE005E: 84, + 0xE005F: 84, + 0xE0060: 84, + 0xE0061: 84, + 0xE0062: 84, + 0xE0063: 84, + 0xE0064: 84, + 0xE0065: 84, + 0xE0066: 84, + 0xE0067: 84, + 0xE0068: 84, + 0xE0069: 84, + 0xE006A: 84, + 0xE006B: 84, + 0xE006C: 84, + 0xE006D: 84, + 0xE006E: 84, + 0xE006F: 84, + 0xE0070: 84, + 0xE0071: 84, + 0xE0072: 84, + 0xE0073: 84, + 0xE0074: 84, + 0xE0075: 84, + 0xE0076: 84, + 0xE0077: 84, + 0xE0078: 84, + 0xE0079: 84, + 0xE007A: 84, + 0xE007B: 84, + 0xE007C: 84, + 0xE007D: 84, + 0xE007E: 84, + 0xE007F: 84, + 0xE0100: 84, + 0xE0101: 84, + 0xE0102: 84, + 0xE0103: 84, + 0xE0104: 84, + 0xE0105: 84, + 0xE0106: 84, + 0xE0107: 84, + 0xE0108: 84, + 0xE0109: 84, + 0xE010A: 84, + 0xE010B: 84, + 0xE010C: 84, + 0xE010D: 84, + 0xE010E: 84, + 0xE010F: 84, + 0xE0110: 84, + 0xE0111: 84, + 0xE0112: 84, + 0xE0113: 84, + 0xE0114: 84, + 0xE0115: 84, + 0xE0116: 84, + 0xE0117: 84, + 0xE0118: 84, + 0xE0119: 84, + 0xE011A: 84, + 0xE011B: 84, + 0xE011C: 84, + 0xE011D: 84, + 0xE011E: 84, + 0xE011F: 84, + 0xE0120: 84, + 0xE0121: 84, + 0xE0122: 84, + 0xE0123: 84, + 0xE0124: 84, + 0xE0125: 84, + 0xE0126: 84, + 0xE0127: 84, + 0xE0128: 84, + 0xE0129: 84, + 0xE012A: 84, + 0xE012B: 84, + 0xE012C: 84, + 0xE012D: 84, + 0xE012E: 84, + 0xE012F: 84, + 0xE0130: 84, + 0xE0131: 84, + 0xE0132: 84, + 0xE0133: 84, + 0xE0134: 84, + 0xE0135: 84, + 0xE0136: 84, + 0xE0137: 84, + 0xE0138: 84, + 0xE0139: 84, + 0xE013A: 84, + 0xE013B: 84, + 0xE013C: 84, + 0xE013D: 84, + 0xE013E: 84, + 0xE013F: 84, + 0xE0140: 84, + 0xE0141: 84, + 0xE0142: 84, + 0xE0143: 84, + 0xE0144: 84, + 0xE0145: 84, + 0xE0146: 84, + 0xE0147: 84, + 0xE0148: 84, + 0xE0149: 84, + 0xE014A: 84, + 0xE014B: 84, + 0xE014C: 84, + 0xE014D: 84, + 0xE014E: 84, + 0xE014F: 84, + 0xE0150: 84, + 0xE0151: 84, + 0xE0152: 84, + 0xE0153: 84, + 0xE0154: 84, + 0xE0155: 84, + 0xE0156: 84, + 0xE0157: 84, + 0xE0158: 84, + 0xE0159: 84, + 0xE015A: 84, + 0xE015B: 84, + 0xE015C: 84, + 0xE015D: 84, + 0xE015E: 84, + 0xE015F: 84, + 0xE0160: 84, + 0xE0161: 84, + 0xE0162: 84, + 0xE0163: 84, + 0xE0164: 84, + 0xE0165: 84, + 0xE0166: 84, + 0xE0167: 84, + 0xE0168: 84, + 0xE0169: 84, + 0xE016A: 84, + 0xE016B: 84, + 0xE016C: 84, + 0xE016D: 84, + 0xE016E: 84, + 0xE016F: 84, + 0xE0170: 84, + 0xE0171: 84, + 0xE0172: 84, + 0xE0173: 84, + 0xE0174: 84, + 0xE0175: 84, + 0xE0176: 84, + 0xE0177: 84, + 0xE0178: 84, + 0xE0179: 84, + 0xE017A: 84, + 0xE017B: 84, + 0xE017C: 84, + 0xE017D: 84, + 0xE017E: 84, + 0xE017F: 84, + 0xE0180: 84, + 0xE0181: 84, + 0xE0182: 84, + 0xE0183: 84, + 0xE0184: 84, + 0xE0185: 84, + 0xE0186: 84, + 0xE0187: 84, + 0xE0188: 84, + 0xE0189: 84, + 0xE018A: 84, + 0xE018B: 84, + 0xE018C: 84, + 0xE018D: 84, + 0xE018E: 84, + 0xE018F: 84, + 0xE0190: 84, + 0xE0191: 84, + 0xE0192: 84, + 0xE0193: 84, + 0xE0194: 84, + 0xE0195: 84, + 0xE0196: 84, + 0xE0197: 84, + 0xE0198: 84, + 0xE0199: 84, + 0xE019A: 84, + 0xE019B: 84, + 0xE019C: 84, + 0xE019D: 84, + 0xE019E: 84, + 0xE019F: 84, + 0xE01A0: 84, + 0xE01A1: 84, + 0xE01A2: 84, + 0xE01A3: 84, + 0xE01A4: 84, + 0xE01A5: 84, + 0xE01A6: 84, + 0xE01A7: 84, + 0xE01A8: 84, + 0xE01A9: 84, + 0xE01AA: 84, + 0xE01AB: 84, + 0xE01AC: 84, + 0xE01AD: 84, + 0xE01AE: 84, + 0xE01AF: 84, + 0xE01B0: 84, + 0xE01B1: 84, + 0xE01B2: 84, + 0xE01B3: 84, + 0xE01B4: 84, + 0xE01B5: 84, + 0xE01B6: 84, + 0xE01B7: 84, + 0xE01B8: 84, + 0xE01B9: 84, + 0xE01BA: 84, + 0xE01BB: 84, + 0xE01BC: 84, + 0xE01BD: 84, + 0xE01BE: 84, + 0xE01BF: 84, + 0xE01C0: 84, + 0xE01C1: 84, + 0xE01C2: 84, + 0xE01C3: 84, + 0xE01C4: 84, + 0xE01C5: 84, + 0xE01C6: 84, + 0xE01C7: 84, + 0xE01C8: 84, + 0xE01C9: 84, + 0xE01CA: 84, + 0xE01CB: 84, + 0xE01CC: 84, + 0xE01CD: 84, + 0xE01CE: 84, + 0xE01CF: 84, + 0xE01D0: 84, + 0xE01D1: 84, + 0xE01D2: 84, + 0xE01D3: 84, + 0xE01D4: 84, + 0xE01D5: 84, + 0xE01D6: 84, + 0xE01D7: 84, + 0xE01D8: 84, + 0xE01D9: 84, + 0xE01DA: 84, + 0xE01DB: 84, + 0xE01DC: 84, + 0xE01DD: 84, + 0xE01DE: 84, + 0xE01DF: 84, + 0xE01E0: 84, + 0xE01E1: 84, + 0xE01E2: 84, + 0xE01E3: 84, + 0xE01E4: 84, + 0xE01E5: 84, + 0xE01E6: 84, + 0xE01E7: 84, + 0xE01E8: 84, + 0xE01E9: 84, + 0xE01EA: 84, + 0xE01EB: 84, + 0xE01EC: 84, + 0xE01ED: 84, + 0xE01EE: 84, + 0xE01EF: 84, +} +codepoint_classes = { + "PVALID": ( + 0x2D0000002E, + 0x300000003A, + 0x610000007B, + 0xDF000000F7, + 0xF800000100, + 0x10100000102, + 0x10300000104, + 0x10500000106, + 0x10700000108, + 0x1090000010A, + 0x10B0000010C, + 0x10D0000010E, + 0x10F00000110, + 0x11100000112, + 0x11300000114, + 0x11500000116, + 0x11700000118, + 0x1190000011A, + 0x11B0000011C, + 0x11D0000011E, + 0x11F00000120, + 0x12100000122, + 0x12300000124, + 0x12500000126, + 0x12700000128, + 0x1290000012A, + 0x12B0000012C, + 0x12D0000012E, + 0x12F00000130, + 0x13100000132, + 0x13500000136, + 0x13700000139, + 0x13A0000013B, + 0x13C0000013D, + 0x13E0000013F, + 0x14200000143, + 0x14400000145, + 0x14600000147, + 0x14800000149, + 0x14B0000014C, + 0x14D0000014E, + 0x14F00000150, + 0x15100000152, + 0x15300000154, + 0x15500000156, + 0x15700000158, + 0x1590000015A, + 0x15B0000015C, + 0x15D0000015E, + 0x15F00000160, + 0x16100000162, + 0x16300000164, + 0x16500000166, + 0x16700000168, + 0x1690000016A, + 0x16B0000016C, + 0x16D0000016E, + 0x16F00000170, + 0x17100000172, + 0x17300000174, + 0x17500000176, + 0x17700000178, + 0x17A0000017B, + 0x17C0000017D, + 0x17E0000017F, + 0x18000000181, + 0x18300000184, + 0x18500000186, + 0x18800000189, + 0x18C0000018E, + 0x19200000193, + 0x19500000196, + 0x1990000019C, + 0x19E0000019F, + 0x1A1000001A2, + 0x1A3000001A4, + 0x1A5000001A6, + 0x1A8000001A9, + 0x1AA000001AC, + 0x1AD000001AE, + 0x1B0000001B1, + 0x1B4000001B5, + 0x1B6000001B7, + 0x1B9000001BC, + 0x1BD000001C4, + 0x1CE000001CF, + 0x1D0000001D1, + 0x1D2000001D3, + 0x1D4000001D5, + 0x1D6000001D7, + 0x1D8000001D9, + 0x1DA000001DB, + 0x1DC000001DE, + 0x1DF000001E0, + 0x1E1000001E2, + 0x1E3000001E4, + 0x1E5000001E6, + 0x1E7000001E8, + 0x1E9000001EA, + 0x1EB000001EC, + 0x1ED000001EE, + 0x1EF000001F1, + 0x1F5000001F6, + 0x1F9000001FA, + 0x1FB000001FC, + 0x1FD000001FE, + 0x1FF00000200, + 0x20100000202, + 0x20300000204, + 0x20500000206, + 0x20700000208, + 0x2090000020A, + 0x20B0000020C, + 0x20D0000020E, + 0x20F00000210, + 0x21100000212, + 0x21300000214, + 0x21500000216, + 0x21700000218, + 0x2190000021A, + 0x21B0000021C, + 0x21D0000021E, + 0x21F00000220, + 0x22100000222, + 0x22300000224, + 0x22500000226, + 0x22700000228, + 0x2290000022A, + 0x22B0000022C, + 0x22D0000022E, + 0x22F00000230, + 0x23100000232, + 0x2330000023A, + 0x23C0000023D, + 0x23F00000241, + 0x24200000243, + 0x24700000248, + 0x2490000024A, + 0x24B0000024C, + 0x24D0000024E, + 0x24F000002B0, + 0x2B9000002C2, + 0x2C6000002D2, + 0x2EC000002ED, + 0x2EE000002EF, + 0x30000000340, + 0x34200000343, + 0x3460000034F, + 0x35000000370, + 0x37100000372, + 0x37300000374, + 0x37700000378, + 0x37B0000037E, + 0x39000000391, + 0x3AC000003CF, + 0x3D7000003D8, + 0x3D9000003DA, + 0x3DB000003DC, + 0x3DD000003DE, + 0x3DF000003E0, + 0x3E1000003E2, + 0x3E3000003E4, + 0x3E5000003E6, + 0x3E7000003E8, + 0x3E9000003EA, + 0x3EB000003EC, + 0x3ED000003EE, + 0x3EF000003F0, + 0x3F3000003F4, + 0x3F8000003F9, + 0x3FB000003FD, + 0x43000000460, + 0x46100000462, + 0x46300000464, + 0x46500000466, + 0x46700000468, + 0x4690000046A, + 0x46B0000046C, + 0x46D0000046E, + 0x46F00000470, + 0x47100000472, + 0x47300000474, + 0x47500000476, + 0x47700000478, + 0x4790000047A, + 0x47B0000047C, + 0x47D0000047E, + 0x47F00000480, + 0x48100000482, + 0x48300000488, + 0x48B0000048C, + 0x48D0000048E, + 0x48F00000490, + 0x49100000492, + 0x49300000494, + 0x49500000496, + 0x49700000498, + 0x4990000049A, + 0x49B0000049C, + 0x49D0000049E, + 0x49F000004A0, + 0x4A1000004A2, + 0x4A3000004A4, + 0x4A5000004A6, + 0x4A7000004A8, + 0x4A9000004AA, + 0x4AB000004AC, + 0x4AD000004AE, + 0x4AF000004B0, + 0x4B1000004B2, + 0x4B3000004B4, + 0x4B5000004B6, + 0x4B7000004B8, + 0x4B9000004BA, + 0x4BB000004BC, + 0x4BD000004BE, + 0x4BF000004C0, + 0x4C2000004C3, + 0x4C4000004C5, + 0x4C6000004C7, + 0x4C8000004C9, + 0x4CA000004CB, + 0x4CC000004CD, + 0x4CE000004D0, + 0x4D1000004D2, + 0x4D3000004D4, + 0x4D5000004D6, + 0x4D7000004D8, + 0x4D9000004DA, + 0x4DB000004DC, + 0x4DD000004DE, + 0x4DF000004E0, + 0x4E1000004E2, + 0x4E3000004E4, + 0x4E5000004E6, + 0x4E7000004E8, + 0x4E9000004EA, + 0x4EB000004EC, + 0x4ED000004EE, + 0x4EF000004F0, + 0x4F1000004F2, + 0x4F3000004F4, + 0x4F5000004F6, + 0x4F7000004F8, + 0x4F9000004FA, + 0x4FB000004FC, + 0x4FD000004FE, + 0x4FF00000500, + 0x50100000502, + 0x50300000504, + 0x50500000506, + 0x50700000508, + 0x5090000050A, + 0x50B0000050C, + 0x50D0000050E, + 0x50F00000510, + 0x51100000512, + 0x51300000514, + 0x51500000516, + 0x51700000518, + 0x5190000051A, + 0x51B0000051C, + 0x51D0000051E, + 0x51F00000520, + 0x52100000522, + 0x52300000524, + 0x52500000526, + 0x52700000528, + 0x5290000052A, + 0x52B0000052C, + 0x52D0000052E, + 0x52F00000530, + 0x5590000055A, + 0x56000000587, + 0x58800000589, + 0x591000005BE, + 0x5BF000005C0, + 0x5C1000005C3, + 0x5C4000005C6, + 0x5C7000005C8, + 0x5D0000005EB, + 0x5EF000005F3, + 0x6100000061B, + 0x62000000640, + 0x64100000660, + 0x66E00000675, + 0x679000006D4, + 0x6D5000006DD, + 0x6DF000006E9, + 0x6EA000006F0, + 0x6FA00000700, + 0x7100000074B, + 0x74D000007B2, + 0x7C0000007F6, + 0x7FD000007FE, + 0x8000000082E, + 0x8400000085C, + 0x8600000086B, + 0x87000000888, + 0x8890000088F, + 0x898000008E2, + 0x8E300000958, + 0x96000000964, + 0x96600000970, + 0x97100000984, + 0x9850000098D, + 0x98F00000991, + 0x993000009A9, + 0x9AA000009B1, + 0x9B2000009B3, + 0x9B6000009BA, + 0x9BC000009C5, + 0x9C7000009C9, + 0x9CB000009CF, + 0x9D7000009D8, + 0x9E0000009E4, + 0x9E6000009F2, + 0x9FC000009FD, + 0x9FE000009FF, + 0xA0100000A04, + 0xA0500000A0B, + 0xA0F00000A11, + 0xA1300000A29, + 0xA2A00000A31, + 0xA3200000A33, + 0xA3500000A36, + 0xA3800000A3A, + 0xA3C00000A3D, + 0xA3E00000A43, + 0xA4700000A49, + 0xA4B00000A4E, + 0xA5100000A52, + 0xA5C00000A5D, + 0xA6600000A76, + 0xA8100000A84, + 0xA8500000A8E, + 0xA8F00000A92, + 0xA9300000AA9, + 0xAAA00000AB1, + 0xAB200000AB4, + 0xAB500000ABA, + 0xABC00000AC6, + 0xAC700000ACA, + 0xACB00000ACE, + 0xAD000000AD1, + 0xAE000000AE4, + 0xAE600000AF0, + 0xAF900000B00, + 0xB0100000B04, + 0xB0500000B0D, + 0xB0F00000B11, + 0xB1300000B29, + 0xB2A00000B31, + 0xB3200000B34, + 0xB3500000B3A, + 0xB3C00000B45, + 0xB4700000B49, + 0xB4B00000B4E, + 0xB5500000B58, + 0xB5F00000B64, + 0xB6600000B70, + 0xB7100000B72, + 0xB8200000B84, + 0xB8500000B8B, + 0xB8E00000B91, + 0xB9200000B96, + 0xB9900000B9B, + 0xB9C00000B9D, + 0xB9E00000BA0, + 0xBA300000BA5, + 0xBA800000BAB, + 0xBAE00000BBA, + 0xBBE00000BC3, + 0xBC600000BC9, + 0xBCA00000BCE, + 0xBD000000BD1, + 0xBD700000BD8, + 0xBE600000BF0, + 0xC0000000C0D, + 0xC0E00000C11, + 0xC1200000C29, + 0xC2A00000C3A, + 0xC3C00000C45, + 0xC4600000C49, + 0xC4A00000C4E, + 0xC5500000C57, + 0xC5800000C5B, + 0xC5D00000C5E, + 0xC6000000C64, + 0xC6600000C70, + 0xC8000000C84, + 0xC8500000C8D, + 0xC8E00000C91, + 0xC9200000CA9, + 0xCAA00000CB4, + 0xCB500000CBA, + 0xCBC00000CC5, + 0xCC600000CC9, + 0xCCA00000CCE, + 0xCD500000CD7, + 0xCDD00000CDF, + 0xCE000000CE4, + 0xCE600000CF0, + 0xCF100000CF4, + 0xD0000000D0D, + 0xD0E00000D11, + 0xD1200000D45, + 0xD4600000D49, + 0xD4A00000D4F, + 0xD5400000D58, + 0xD5F00000D64, + 0xD6600000D70, + 0xD7A00000D80, + 0xD8100000D84, + 0xD8500000D97, + 0xD9A00000DB2, + 0xDB300000DBC, + 0xDBD00000DBE, + 0xDC000000DC7, + 0xDCA00000DCB, + 0xDCF00000DD5, + 0xDD600000DD7, + 0xDD800000DE0, + 0xDE600000DF0, + 0xDF200000DF4, + 0xE0100000E33, + 0xE3400000E3B, + 0xE4000000E4F, + 0xE5000000E5A, + 0xE8100000E83, + 0xE8400000E85, + 0xE8600000E8B, + 0xE8C00000EA4, + 0xEA500000EA6, + 0xEA700000EB3, + 0xEB400000EBE, + 0xEC000000EC5, + 0xEC600000EC7, + 0xEC800000ECF, + 0xED000000EDA, + 0xEDE00000EE0, + 0xF0000000F01, + 0xF0B00000F0C, + 0xF1800000F1A, + 0xF2000000F2A, + 0xF3500000F36, + 0xF3700000F38, + 0xF3900000F3A, + 0xF3E00000F43, + 0xF4400000F48, + 0xF4900000F4D, + 0xF4E00000F52, + 0xF5300000F57, + 0xF5800000F5C, + 0xF5D00000F69, + 0xF6A00000F6D, + 0xF7100000F73, + 0xF7400000F75, + 0xF7A00000F81, + 0xF8200000F85, + 0xF8600000F93, + 0xF9400000F98, + 0xF9900000F9D, + 0xF9E00000FA2, + 0xFA300000FA7, + 0xFA800000FAC, + 0xFAD00000FB9, + 0xFBA00000FBD, + 0xFC600000FC7, + 0x10000000104A, + 0x10500000109E, + 0x10D0000010FB, + 0x10FD00001100, + 0x120000001249, + 0x124A0000124E, + 0x125000001257, + 0x125800001259, + 0x125A0000125E, + 0x126000001289, + 0x128A0000128E, + 0x1290000012B1, + 0x12B2000012B6, + 0x12B8000012BF, + 0x12C0000012C1, + 0x12C2000012C6, + 0x12C8000012D7, + 0x12D800001311, + 0x131200001316, + 0x13180000135B, + 0x135D00001360, + 0x138000001390, + 0x13A0000013F6, + 0x14010000166D, + 0x166F00001680, + 0x16810000169B, + 0x16A0000016EB, + 0x16F1000016F9, + 0x170000001716, + 0x171F00001735, + 0x174000001754, + 0x17600000176D, + 0x176E00001771, + 0x177200001774, + 0x1780000017B4, + 0x17B6000017D4, + 0x17D7000017D8, + 0x17DC000017DE, + 0x17E0000017EA, + 0x18100000181A, + 0x182000001879, + 0x1880000018AB, + 0x18B0000018F6, + 0x19000000191F, + 0x19200000192C, + 0x19300000193C, + 0x19460000196E, + 0x197000001975, + 0x1980000019AC, + 0x19B0000019CA, + 0x19D0000019DA, + 0x1A0000001A1C, + 0x1A2000001A5F, + 0x1A6000001A7D, + 0x1A7F00001A8A, + 0x1A9000001A9A, + 0x1AA700001AA8, + 0x1AB000001ABE, + 0x1ABF00001ACF, + 0x1B0000001B4D, + 0x1B5000001B5A, + 0x1B6B00001B74, + 0x1B8000001BF4, + 0x1C0000001C38, + 0x1C4000001C4A, + 0x1C4D00001C7E, + 0x1CD000001CD3, + 0x1CD400001CFB, + 0x1D0000001D2C, + 0x1D2F00001D30, + 0x1D3B00001D3C, + 0x1D4E00001D4F, + 0x1D6B00001D78, + 0x1D7900001D9B, + 0x1DC000001E00, + 0x1E0100001E02, + 0x1E0300001E04, + 0x1E0500001E06, + 0x1E0700001E08, + 0x1E0900001E0A, + 0x1E0B00001E0C, + 0x1E0D00001E0E, + 0x1E0F00001E10, + 0x1E1100001E12, + 0x1E1300001E14, + 0x1E1500001E16, + 0x1E1700001E18, + 0x1E1900001E1A, + 0x1E1B00001E1C, + 0x1E1D00001E1E, + 0x1E1F00001E20, + 0x1E2100001E22, + 0x1E2300001E24, + 0x1E2500001E26, + 0x1E2700001E28, + 0x1E2900001E2A, + 0x1E2B00001E2C, + 0x1E2D00001E2E, + 0x1E2F00001E30, + 0x1E3100001E32, + 0x1E3300001E34, + 0x1E3500001E36, + 0x1E3700001E38, + 0x1E3900001E3A, + 0x1E3B00001E3C, + 0x1E3D00001E3E, + 0x1E3F00001E40, + 0x1E4100001E42, + 0x1E4300001E44, + 0x1E4500001E46, + 0x1E4700001E48, + 0x1E4900001E4A, + 0x1E4B00001E4C, + 0x1E4D00001E4E, + 0x1E4F00001E50, + 0x1E5100001E52, + 0x1E5300001E54, + 0x1E5500001E56, + 0x1E5700001E58, + 0x1E5900001E5A, + 0x1E5B00001E5C, + 0x1E5D00001E5E, + 0x1E5F00001E60, + 0x1E6100001E62, + 0x1E6300001E64, + 0x1E6500001E66, + 0x1E6700001E68, + 0x1E6900001E6A, + 0x1E6B00001E6C, + 0x1E6D00001E6E, + 0x1E6F00001E70, + 0x1E7100001E72, + 0x1E7300001E74, + 0x1E7500001E76, + 0x1E7700001E78, + 0x1E7900001E7A, + 0x1E7B00001E7C, + 0x1E7D00001E7E, + 0x1E7F00001E80, + 0x1E8100001E82, + 0x1E8300001E84, + 0x1E8500001E86, + 0x1E8700001E88, + 0x1E8900001E8A, + 0x1E8B00001E8C, + 0x1E8D00001E8E, + 0x1E8F00001E90, + 0x1E9100001E92, + 0x1E9300001E94, + 0x1E9500001E9A, + 0x1E9C00001E9E, + 0x1E9F00001EA0, + 0x1EA100001EA2, + 0x1EA300001EA4, + 0x1EA500001EA6, + 0x1EA700001EA8, + 0x1EA900001EAA, + 0x1EAB00001EAC, + 0x1EAD00001EAE, + 0x1EAF00001EB0, + 0x1EB100001EB2, + 0x1EB300001EB4, + 0x1EB500001EB6, + 0x1EB700001EB8, + 0x1EB900001EBA, + 0x1EBB00001EBC, + 0x1EBD00001EBE, + 0x1EBF00001EC0, + 0x1EC100001EC2, + 0x1EC300001EC4, + 0x1EC500001EC6, + 0x1EC700001EC8, + 0x1EC900001ECA, + 0x1ECB00001ECC, + 0x1ECD00001ECE, + 0x1ECF00001ED0, + 0x1ED100001ED2, + 0x1ED300001ED4, + 0x1ED500001ED6, + 0x1ED700001ED8, + 0x1ED900001EDA, + 0x1EDB00001EDC, + 0x1EDD00001EDE, + 0x1EDF00001EE0, + 0x1EE100001EE2, + 0x1EE300001EE4, + 0x1EE500001EE6, + 0x1EE700001EE8, + 0x1EE900001EEA, + 0x1EEB00001EEC, + 0x1EED00001EEE, + 0x1EEF00001EF0, + 0x1EF100001EF2, + 0x1EF300001EF4, + 0x1EF500001EF6, + 0x1EF700001EF8, + 0x1EF900001EFA, + 0x1EFB00001EFC, + 0x1EFD00001EFE, + 0x1EFF00001F08, + 0x1F1000001F16, + 0x1F2000001F28, + 0x1F3000001F38, + 0x1F4000001F46, + 0x1F5000001F58, + 0x1F6000001F68, + 0x1F7000001F71, + 0x1F7200001F73, + 0x1F7400001F75, + 0x1F7600001F77, + 0x1F7800001F79, + 0x1F7A00001F7B, + 0x1F7C00001F7D, + 0x1FB000001FB2, + 0x1FB600001FB7, + 0x1FC600001FC7, + 0x1FD000001FD3, + 0x1FD600001FD8, + 0x1FE000001FE3, + 0x1FE400001FE8, + 0x1FF600001FF7, + 0x214E0000214F, + 0x218400002185, + 0x2C3000002C60, + 0x2C6100002C62, + 0x2C6500002C67, + 0x2C6800002C69, + 0x2C6A00002C6B, + 0x2C6C00002C6D, + 0x2C7100002C72, + 0x2C7300002C75, + 0x2C7600002C7C, + 0x2C8100002C82, + 0x2C8300002C84, + 0x2C8500002C86, + 0x2C8700002C88, + 0x2C8900002C8A, + 0x2C8B00002C8C, + 0x2C8D00002C8E, + 0x2C8F00002C90, + 0x2C9100002C92, + 0x2C9300002C94, + 0x2C9500002C96, + 0x2C9700002C98, + 0x2C9900002C9A, + 0x2C9B00002C9C, + 0x2C9D00002C9E, + 0x2C9F00002CA0, + 0x2CA100002CA2, + 0x2CA300002CA4, + 0x2CA500002CA6, + 0x2CA700002CA8, + 0x2CA900002CAA, + 0x2CAB00002CAC, + 0x2CAD00002CAE, + 0x2CAF00002CB0, + 0x2CB100002CB2, + 0x2CB300002CB4, + 0x2CB500002CB6, + 0x2CB700002CB8, + 0x2CB900002CBA, + 0x2CBB00002CBC, + 0x2CBD00002CBE, + 0x2CBF00002CC0, + 0x2CC100002CC2, + 0x2CC300002CC4, + 0x2CC500002CC6, + 0x2CC700002CC8, + 0x2CC900002CCA, + 0x2CCB00002CCC, + 0x2CCD00002CCE, + 0x2CCF00002CD0, + 0x2CD100002CD2, + 0x2CD300002CD4, + 0x2CD500002CD6, + 0x2CD700002CD8, + 0x2CD900002CDA, + 0x2CDB00002CDC, + 0x2CDD00002CDE, + 0x2CDF00002CE0, + 0x2CE100002CE2, + 0x2CE300002CE5, + 0x2CEC00002CED, + 0x2CEE00002CF2, + 0x2CF300002CF4, + 0x2D0000002D26, + 0x2D2700002D28, + 0x2D2D00002D2E, + 0x2D3000002D68, + 0x2D7F00002D97, + 0x2DA000002DA7, + 0x2DA800002DAF, + 0x2DB000002DB7, + 0x2DB800002DBF, + 0x2DC000002DC7, + 0x2DC800002DCF, + 0x2DD000002DD7, + 0x2DD800002DDF, + 0x2DE000002E00, + 0x2E2F00002E30, + 0x300500003008, + 0x302A0000302E, + 0x303C0000303D, + 0x304100003097, + 0x30990000309B, + 0x309D0000309F, + 0x30A1000030FB, + 0x30FC000030FF, + 0x310500003130, + 0x31A0000031C0, + 0x31F000003200, + 0x340000004DC0, + 0x4E000000A48D, + 0xA4D00000A4FE, + 0xA5000000A60D, + 0xA6100000A62C, + 0xA6410000A642, + 0xA6430000A644, + 0xA6450000A646, + 0xA6470000A648, + 0xA6490000A64A, + 0xA64B0000A64C, + 0xA64D0000A64E, + 0xA64F0000A650, + 0xA6510000A652, + 0xA6530000A654, + 0xA6550000A656, + 0xA6570000A658, + 0xA6590000A65A, + 0xA65B0000A65C, + 0xA65D0000A65E, + 0xA65F0000A660, + 0xA6610000A662, + 0xA6630000A664, + 0xA6650000A666, + 0xA6670000A668, + 0xA6690000A66A, + 0xA66B0000A66C, + 0xA66D0000A670, + 0xA6740000A67E, + 0xA67F0000A680, + 0xA6810000A682, + 0xA6830000A684, + 0xA6850000A686, + 0xA6870000A688, + 0xA6890000A68A, + 0xA68B0000A68C, + 0xA68D0000A68E, + 0xA68F0000A690, + 0xA6910000A692, + 0xA6930000A694, + 0xA6950000A696, + 0xA6970000A698, + 0xA6990000A69A, + 0xA69B0000A69C, + 0xA69E0000A6E6, + 0xA6F00000A6F2, + 0xA7170000A720, + 0xA7230000A724, + 0xA7250000A726, + 0xA7270000A728, + 0xA7290000A72A, + 0xA72B0000A72C, + 0xA72D0000A72E, + 0xA72F0000A732, + 0xA7330000A734, + 0xA7350000A736, + 0xA7370000A738, + 0xA7390000A73A, + 0xA73B0000A73C, + 0xA73D0000A73E, + 0xA73F0000A740, + 0xA7410000A742, + 0xA7430000A744, + 0xA7450000A746, + 0xA7470000A748, + 0xA7490000A74A, + 0xA74B0000A74C, + 0xA74D0000A74E, + 0xA74F0000A750, + 0xA7510000A752, + 0xA7530000A754, + 0xA7550000A756, + 0xA7570000A758, + 0xA7590000A75A, + 0xA75B0000A75C, + 0xA75D0000A75E, + 0xA75F0000A760, + 0xA7610000A762, + 0xA7630000A764, + 0xA7650000A766, + 0xA7670000A768, + 0xA7690000A76A, + 0xA76B0000A76C, + 0xA76D0000A76E, + 0xA76F0000A770, + 0xA7710000A779, + 0xA77A0000A77B, + 0xA77C0000A77D, + 0xA77F0000A780, + 0xA7810000A782, + 0xA7830000A784, + 0xA7850000A786, + 0xA7870000A789, + 0xA78C0000A78D, + 0xA78E0000A790, + 0xA7910000A792, + 0xA7930000A796, + 0xA7970000A798, + 0xA7990000A79A, + 0xA79B0000A79C, + 0xA79D0000A79E, + 0xA79F0000A7A0, + 0xA7A10000A7A2, + 0xA7A30000A7A4, + 0xA7A50000A7A6, + 0xA7A70000A7A8, + 0xA7A90000A7AA, + 0xA7AF0000A7B0, + 0xA7B50000A7B6, + 0xA7B70000A7B8, + 0xA7B90000A7BA, + 0xA7BB0000A7BC, + 0xA7BD0000A7BE, + 0xA7BF0000A7C0, + 0xA7C10000A7C2, + 0xA7C30000A7C4, + 0xA7C80000A7C9, + 0xA7CA0000A7CB, + 0xA7D10000A7D2, + 0xA7D30000A7D4, + 0xA7D50000A7D6, + 0xA7D70000A7D8, + 0xA7D90000A7DA, + 0xA7F60000A7F8, + 0xA7FA0000A828, + 0xA82C0000A82D, + 0xA8400000A874, + 0xA8800000A8C6, + 0xA8D00000A8DA, + 0xA8E00000A8F8, + 0xA8FB0000A8FC, + 0xA8FD0000A92E, + 0xA9300000A954, + 0xA9800000A9C1, + 0xA9CF0000A9DA, + 0xA9E00000A9FF, + 0xAA000000AA37, + 0xAA400000AA4E, + 0xAA500000AA5A, + 0xAA600000AA77, + 0xAA7A0000AAC3, + 0xAADB0000AADE, + 0xAAE00000AAF0, + 0xAAF20000AAF7, + 0xAB010000AB07, + 0xAB090000AB0F, + 0xAB110000AB17, + 0xAB200000AB27, + 0xAB280000AB2F, + 0xAB300000AB5B, + 0xAB600000AB69, + 0xABC00000ABEB, + 0xABEC0000ABEE, + 0xABF00000ABFA, + 0xAC000000D7A4, + 0xFA0E0000FA10, + 0xFA110000FA12, + 0xFA130000FA15, + 0xFA1F0000FA20, + 0xFA210000FA22, + 0xFA230000FA25, + 0xFA270000FA2A, + 0xFB1E0000FB1F, + 0xFE200000FE30, + 0xFE730000FE74, + 0x100000001000C, + 0x1000D00010027, + 0x100280001003B, + 0x1003C0001003E, + 0x1003F0001004E, + 0x100500001005E, + 0x10080000100FB, + 0x101FD000101FE, + 0x102800001029D, + 0x102A0000102D1, + 0x102E0000102E1, + 0x1030000010320, + 0x1032D00010341, + 0x103420001034A, + 0x103500001037B, + 0x103800001039E, + 0x103A0000103C4, + 0x103C8000103D0, + 0x104280001049E, + 0x104A0000104AA, + 0x104D8000104FC, + 0x1050000010528, + 0x1053000010564, + 0x10597000105A2, + 0x105A3000105B2, + 0x105B3000105BA, + 0x105BB000105BD, + 0x1060000010737, + 0x1074000010756, + 0x1076000010768, + 0x1078000010781, + 0x1080000010806, + 0x1080800010809, + 0x1080A00010836, + 0x1083700010839, + 0x1083C0001083D, + 0x1083F00010856, + 0x1086000010877, + 0x108800001089F, + 0x108E0000108F3, + 0x108F4000108F6, + 0x1090000010916, + 0x109200001093A, + 0x10980000109B8, + 0x109BE000109C0, + 0x10A0000010A04, + 0x10A0500010A07, + 0x10A0C00010A14, + 0x10A1500010A18, + 0x10A1900010A36, + 0x10A3800010A3B, + 0x10A3F00010A40, + 0x10A6000010A7D, + 0x10A8000010A9D, + 0x10AC000010AC8, + 0x10AC900010AE7, + 0x10B0000010B36, + 0x10B4000010B56, + 0x10B6000010B73, + 0x10B8000010B92, + 0x10C0000010C49, + 0x10CC000010CF3, + 0x10D0000010D28, + 0x10D3000010D3A, + 0x10E8000010EAA, + 0x10EAB00010EAD, + 0x10EB000010EB2, + 0x10EFD00010F1D, + 0x10F2700010F28, + 0x10F3000010F51, + 0x10F7000010F86, + 0x10FB000010FC5, + 0x10FE000010FF7, + 0x1100000011047, + 0x1106600011076, + 0x1107F000110BB, + 0x110C2000110C3, + 0x110D0000110E9, + 0x110F0000110FA, + 0x1110000011135, + 0x1113600011140, + 0x1114400011148, + 0x1115000011174, + 0x1117600011177, + 0x11180000111C5, + 0x111C9000111CD, + 0x111CE000111DB, + 0x111DC000111DD, + 0x1120000011212, + 0x1121300011238, + 0x1123E00011242, + 0x1128000011287, + 0x1128800011289, + 0x1128A0001128E, + 0x1128F0001129E, + 0x1129F000112A9, + 0x112B0000112EB, + 0x112F0000112FA, + 0x1130000011304, + 0x113050001130D, + 0x1130F00011311, + 0x1131300011329, + 0x1132A00011331, + 0x1133200011334, + 0x113350001133A, + 0x1133B00011345, + 0x1134700011349, + 0x1134B0001134E, + 0x1135000011351, + 0x1135700011358, + 0x1135D00011364, + 0x113660001136D, + 0x1137000011375, + 0x114000001144B, + 0x114500001145A, + 0x1145E00011462, + 0x11480000114C6, + 0x114C7000114C8, + 0x114D0000114DA, + 0x11580000115B6, + 0x115B8000115C1, + 0x115D8000115DE, + 0x1160000011641, + 0x1164400011645, + 0x116500001165A, + 0x11680000116B9, + 0x116C0000116CA, + 0x117000001171B, + 0x1171D0001172C, + 0x117300001173A, + 0x1174000011747, + 0x118000001183B, + 0x118C0000118EA, + 0x118FF00011907, + 0x119090001190A, + 0x1190C00011914, + 0x1191500011917, + 0x1191800011936, + 0x1193700011939, + 0x1193B00011944, + 0x119500001195A, + 0x119A0000119A8, + 0x119AA000119D8, + 0x119DA000119E2, + 0x119E3000119E5, + 0x11A0000011A3F, + 0x11A4700011A48, + 0x11A5000011A9A, + 0x11A9D00011A9E, + 0x11AB000011AF9, + 0x11C0000011C09, + 0x11C0A00011C37, + 0x11C3800011C41, + 0x11C5000011C5A, + 0x11C7200011C90, + 0x11C9200011CA8, + 0x11CA900011CB7, + 0x11D0000011D07, + 0x11D0800011D0A, + 0x11D0B00011D37, + 0x11D3A00011D3B, + 0x11D3C00011D3E, + 0x11D3F00011D48, + 0x11D5000011D5A, + 0x11D6000011D66, + 0x11D6700011D69, + 0x11D6A00011D8F, + 0x11D9000011D92, + 0x11D9300011D99, + 0x11DA000011DAA, + 0x11EE000011EF7, + 0x11F0000011F11, + 0x11F1200011F3B, + 0x11F3E00011F43, + 0x11F5000011F5A, + 0x11FB000011FB1, + 0x120000001239A, + 0x1248000012544, + 0x12F9000012FF1, + 0x1300000013430, + 0x1344000013456, + 0x1440000014647, + 0x1680000016A39, + 0x16A4000016A5F, + 0x16A6000016A6A, + 0x16A7000016ABF, + 0x16AC000016ACA, + 0x16AD000016AEE, + 0x16AF000016AF5, + 0x16B0000016B37, + 0x16B4000016B44, + 0x16B5000016B5A, + 0x16B6300016B78, + 0x16B7D00016B90, + 0x16E6000016E80, + 0x16F0000016F4B, + 0x16F4F00016F88, + 0x16F8F00016FA0, + 0x16FE000016FE2, + 0x16FE300016FE5, + 0x16FF000016FF2, + 0x17000000187F8, + 0x1880000018CD6, + 0x18D0000018D09, + 0x1AFF00001AFF4, + 0x1AFF50001AFFC, + 0x1AFFD0001AFFF, + 0x1B0000001B123, + 0x1B1320001B133, + 0x1B1500001B153, + 0x1B1550001B156, + 0x1B1640001B168, + 0x1B1700001B2FC, + 0x1BC000001BC6B, + 0x1BC700001BC7D, + 0x1BC800001BC89, + 0x1BC900001BC9A, + 0x1BC9D0001BC9F, + 0x1CF000001CF2E, + 0x1CF300001CF47, + 0x1DA000001DA37, + 0x1DA3B0001DA6D, + 0x1DA750001DA76, + 0x1DA840001DA85, + 0x1DA9B0001DAA0, + 0x1DAA10001DAB0, + 0x1DF000001DF1F, + 0x1DF250001DF2B, + 0x1E0000001E007, + 0x1E0080001E019, + 0x1E01B0001E022, + 0x1E0230001E025, + 0x1E0260001E02B, + 0x1E08F0001E090, + 0x1E1000001E12D, + 0x1E1300001E13E, + 0x1E1400001E14A, + 0x1E14E0001E14F, + 0x1E2900001E2AF, + 0x1E2C00001E2FA, + 0x1E4D00001E4FA, + 0x1E7E00001E7E7, + 0x1E7E80001E7EC, + 0x1E7ED0001E7EF, + 0x1E7F00001E7FF, + 0x1E8000001E8C5, + 0x1E8D00001E8D7, + 0x1E9220001E94C, + 0x1E9500001E95A, + 0x200000002A6E0, + 0x2A7000002B73A, + 0x2B7400002B81E, + 0x2B8200002CEA2, + 0x2CEB00002EBE1, + 0x2EBF00002EE5E, + 0x300000003134B, + 0x31350000323B0, + ), + "CONTEXTJ": (0x200C0000200E,), + "CONTEXTO": ( + 0xB7000000B8, + 0x37500000376, + 0x5F3000005F5, + 0x6600000066A, + 0x6F0000006FA, + 0x30FB000030FC, + ), +} diff --git a/backend/venv/Lib/site-packages/idna/intranges.py b/backend/venv/Lib/site-packages/idna/intranges.py new file mode 100644 index 0000000..7bfaa8d --- /dev/null +++ b/backend/venv/Lib/site-packages/idna/intranges.py @@ -0,0 +1,57 @@ +""" +Given a list of integers, made up of (hopefully) a small number of long runs +of consecutive integers, compute a representation of the form +((start1, end1), (start2, end2) ...). Then answer the question "was x present +in the original list?" in time O(log(# runs)). +""" + +import bisect +from typing import List, Tuple + + +def intranges_from_list(list_: List[int]) -> Tuple[int, ...]: + """Represent a list of integers as a sequence of ranges: + ((start_0, end_0), (start_1, end_1), ...), such that the original + integers are exactly those x such that start_i <= x < end_i for some i. + + Ranges are encoded as single integers (start << 32 | end), not as tuples. + """ + + sorted_list = sorted(list_) + ranges = [] + last_write = -1 + for i in range(len(sorted_list)): + if i + 1 < len(sorted_list): + if sorted_list[i] == sorted_list[i + 1] - 1: + continue + current_range = sorted_list[last_write + 1 : i + 1] + ranges.append(_encode_range(current_range[0], current_range[-1] + 1)) + last_write = i + + return tuple(ranges) + + +def _encode_range(start: int, end: int) -> int: + return (start << 32) | end + + +def _decode_range(r: int) -> Tuple[int, int]: + return (r >> 32), (r & ((1 << 32) - 1)) + + +def intranges_contain(int_: int, ranges: Tuple[int, ...]) -> bool: + """Determine if `int_` falls into one of the ranges in `ranges`.""" + tuple_ = _encode_range(int_, 0) + pos = bisect.bisect_left(ranges, tuple_) + # we could be immediately ahead of a tuple (start, end) + # with start < int_ <= end + if pos > 0: + left, right = _decode_range(ranges[pos - 1]) + if left <= int_ < right: + return True + # or we could be immediately behind a tuple (int_, end) + if pos < len(ranges): + left, _ = _decode_range(ranges[pos]) + if left == int_: + return True + return False diff --git a/backend/venv/Lib/site-packages/idna/package_data.py b/backend/venv/Lib/site-packages/idna/package_data.py new file mode 100644 index 0000000..514ff7e --- /dev/null +++ b/backend/venv/Lib/site-packages/idna/package_data.py @@ -0,0 +1 @@ +__version__ = "3.10" diff --git a/backend/venv/Lib/site-packages/idna/py.typed b/backend/venv/Lib/site-packages/idna/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/backend/venv/Lib/site-packages/idna/uts46data.py b/backend/venv/Lib/site-packages/idna/uts46data.py new file mode 100644 index 0000000..eb89432 --- /dev/null +++ b/backend/venv/Lib/site-packages/idna/uts46data.py @@ -0,0 +1,8681 @@ +# This file is automatically generated by tools/idna-data +# vim: set fileencoding=utf-8 : + +from typing import List, Tuple, Union + +"""IDNA Mapping Table from UTS46.""" + + +__version__ = "15.1.0" + + +def _seg_0() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x0, "3"), + (0x1, "3"), + (0x2, "3"), + (0x3, "3"), + (0x4, "3"), + (0x5, "3"), + (0x6, "3"), + (0x7, "3"), + (0x8, "3"), + (0x9, "3"), + (0xA, "3"), + (0xB, "3"), + (0xC, "3"), + (0xD, "3"), + (0xE, "3"), + (0xF, "3"), + (0x10, "3"), + (0x11, "3"), + (0x12, "3"), + (0x13, "3"), + (0x14, "3"), + (0x15, "3"), + (0x16, "3"), + (0x17, "3"), + (0x18, "3"), + (0x19, "3"), + (0x1A, "3"), + (0x1B, "3"), + (0x1C, "3"), + (0x1D, "3"), + (0x1E, "3"), + (0x1F, "3"), + (0x20, "3"), + (0x21, "3"), + (0x22, "3"), + (0x23, "3"), + (0x24, "3"), + (0x25, "3"), + (0x26, "3"), + (0x27, "3"), + (0x28, "3"), + (0x29, "3"), + (0x2A, "3"), + (0x2B, "3"), + (0x2C, "3"), + (0x2D, "V"), + (0x2E, "V"), + (0x2F, "3"), + (0x30, "V"), + (0x31, "V"), + (0x32, "V"), + (0x33, "V"), + (0x34, "V"), + (0x35, "V"), + (0x36, "V"), + (0x37, "V"), + (0x38, "V"), + (0x39, "V"), + (0x3A, "3"), + (0x3B, "3"), + (0x3C, "3"), + (0x3D, "3"), + (0x3E, "3"), + (0x3F, "3"), + (0x40, "3"), + (0x41, "M", "a"), + (0x42, "M", "b"), + (0x43, "M", "c"), + (0x44, "M", "d"), + (0x45, "M", "e"), + (0x46, "M", "f"), + (0x47, "M", "g"), + (0x48, "M", "h"), + (0x49, "M", "i"), + (0x4A, "M", "j"), + (0x4B, "M", "k"), + (0x4C, "M", "l"), + (0x4D, "M", "m"), + (0x4E, "M", "n"), + (0x4F, "M", "o"), + (0x50, "M", "p"), + (0x51, "M", "q"), + (0x52, "M", "r"), + (0x53, "M", "s"), + (0x54, "M", "t"), + (0x55, "M", "u"), + (0x56, "M", "v"), + (0x57, "M", "w"), + (0x58, "M", "x"), + (0x59, "M", "y"), + (0x5A, "M", "z"), + (0x5B, "3"), + (0x5C, "3"), + (0x5D, "3"), + (0x5E, "3"), + (0x5F, "3"), + (0x60, "3"), + (0x61, "V"), + (0x62, "V"), + (0x63, "V"), + ] + + +def _seg_1() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x64, "V"), + (0x65, "V"), + (0x66, "V"), + (0x67, "V"), + (0x68, "V"), + (0x69, "V"), + (0x6A, "V"), + (0x6B, "V"), + (0x6C, "V"), + (0x6D, "V"), + (0x6E, "V"), + (0x6F, "V"), + (0x70, "V"), + (0x71, "V"), + (0x72, "V"), + (0x73, "V"), + (0x74, "V"), + (0x75, "V"), + (0x76, "V"), + (0x77, "V"), + (0x78, "V"), + (0x79, "V"), + (0x7A, "V"), + (0x7B, "3"), + (0x7C, "3"), + (0x7D, "3"), + (0x7E, "3"), + (0x7F, "3"), + (0x80, "X"), + (0x81, "X"), + (0x82, "X"), + (0x83, "X"), + (0x84, "X"), + (0x85, "X"), + (0x86, "X"), + (0x87, "X"), + (0x88, "X"), + (0x89, "X"), + (0x8A, "X"), + (0x8B, "X"), + (0x8C, "X"), + (0x8D, "X"), + (0x8E, "X"), + (0x8F, "X"), + (0x90, "X"), + (0x91, "X"), + (0x92, "X"), + (0x93, "X"), + (0x94, "X"), + (0x95, "X"), + (0x96, "X"), + (0x97, "X"), + (0x98, "X"), + (0x99, "X"), + (0x9A, "X"), + (0x9B, "X"), + (0x9C, "X"), + (0x9D, "X"), + (0x9E, "X"), + (0x9F, "X"), + (0xA0, "3", " "), + (0xA1, "V"), + (0xA2, "V"), + (0xA3, "V"), + (0xA4, "V"), + (0xA5, "V"), + (0xA6, "V"), + (0xA7, "V"), + (0xA8, "3", " ̈"), + (0xA9, "V"), + (0xAA, "M", "a"), + (0xAB, "V"), + (0xAC, "V"), + (0xAD, "I"), + (0xAE, "V"), + (0xAF, "3", " ̄"), + (0xB0, "V"), + (0xB1, "V"), + (0xB2, "M", "2"), + (0xB3, "M", "3"), + (0xB4, "3", " ́"), + (0xB5, "M", "μ"), + (0xB6, "V"), + (0xB7, "V"), + (0xB8, "3", " ̧"), + (0xB9, "M", "1"), + (0xBA, "M", "o"), + (0xBB, "V"), + (0xBC, "M", "1⁄4"), + (0xBD, "M", "1⁄2"), + (0xBE, "M", "3⁄4"), + (0xBF, "V"), + (0xC0, "M", "à"), + (0xC1, "M", "á"), + (0xC2, "M", "â"), + (0xC3, "M", "ã"), + (0xC4, "M", "ä"), + (0xC5, "M", "å"), + (0xC6, "M", "æ"), + (0xC7, "M", "ç"), + ] + + +def _seg_2() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xC8, "M", "è"), + (0xC9, "M", "é"), + (0xCA, "M", "ê"), + (0xCB, "M", "ë"), + (0xCC, "M", "ì"), + (0xCD, "M", "í"), + (0xCE, "M", "î"), + (0xCF, "M", "ï"), + (0xD0, "M", "ð"), + (0xD1, "M", "ñ"), + (0xD2, "M", "ò"), + (0xD3, "M", "ó"), + (0xD4, "M", "ô"), + (0xD5, "M", "õ"), + (0xD6, "M", "ö"), + (0xD7, "V"), + (0xD8, "M", "ø"), + (0xD9, "M", "ù"), + (0xDA, "M", "ú"), + (0xDB, "M", "û"), + (0xDC, "M", "ü"), + (0xDD, "M", "ý"), + (0xDE, "M", "þ"), + (0xDF, "D", "ss"), + (0xE0, "V"), + (0xE1, "V"), + (0xE2, "V"), + (0xE3, "V"), + (0xE4, "V"), + (0xE5, "V"), + (0xE6, "V"), + (0xE7, "V"), + (0xE8, "V"), + (0xE9, "V"), + (0xEA, "V"), + (0xEB, "V"), + (0xEC, "V"), + (0xED, "V"), + (0xEE, "V"), + (0xEF, "V"), + (0xF0, "V"), + (0xF1, "V"), + (0xF2, "V"), + (0xF3, "V"), + (0xF4, "V"), + (0xF5, "V"), + (0xF6, "V"), + (0xF7, "V"), + (0xF8, "V"), + (0xF9, "V"), + (0xFA, "V"), + (0xFB, "V"), + (0xFC, "V"), + (0xFD, "V"), + (0xFE, "V"), + (0xFF, "V"), + (0x100, "M", "ā"), + (0x101, "V"), + (0x102, "M", "ă"), + (0x103, "V"), + (0x104, "M", "ą"), + (0x105, "V"), + (0x106, "M", "ć"), + (0x107, "V"), + (0x108, "M", "ĉ"), + (0x109, "V"), + (0x10A, "M", "ċ"), + (0x10B, "V"), + (0x10C, "M", "č"), + (0x10D, "V"), + (0x10E, "M", "ď"), + (0x10F, "V"), + (0x110, "M", "đ"), + (0x111, "V"), + (0x112, "M", "ē"), + (0x113, "V"), + (0x114, "M", "ĕ"), + (0x115, "V"), + (0x116, "M", "ė"), + (0x117, "V"), + (0x118, "M", "ę"), + (0x119, "V"), + (0x11A, "M", "ě"), + (0x11B, "V"), + (0x11C, "M", "ĝ"), + (0x11D, "V"), + (0x11E, "M", "ğ"), + (0x11F, "V"), + (0x120, "M", "ġ"), + (0x121, "V"), + (0x122, "M", "ģ"), + (0x123, "V"), + (0x124, "M", "ĥ"), + (0x125, "V"), + (0x126, "M", "ħ"), + (0x127, "V"), + (0x128, "M", "ĩ"), + (0x129, "V"), + (0x12A, "M", "ī"), + (0x12B, "V"), + ] + + +def _seg_3() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x12C, "M", "ĭ"), + (0x12D, "V"), + (0x12E, "M", "į"), + (0x12F, "V"), + (0x130, "M", "i̇"), + (0x131, "V"), + (0x132, "M", "ij"), + (0x134, "M", "ĵ"), + (0x135, "V"), + (0x136, "M", "ķ"), + (0x137, "V"), + (0x139, "M", "ĺ"), + (0x13A, "V"), + (0x13B, "M", "ļ"), + (0x13C, "V"), + (0x13D, "M", "ľ"), + (0x13E, "V"), + (0x13F, "M", "l·"), + (0x141, "M", "ł"), + (0x142, "V"), + (0x143, "M", "ń"), + (0x144, "V"), + (0x145, "M", "ņ"), + (0x146, "V"), + (0x147, "M", "ň"), + (0x148, "V"), + (0x149, "M", "ʼn"), + (0x14A, "M", "ŋ"), + (0x14B, "V"), + (0x14C, "M", "ō"), + (0x14D, "V"), + (0x14E, "M", "ŏ"), + (0x14F, "V"), + (0x150, "M", "ő"), + (0x151, "V"), + (0x152, "M", "œ"), + (0x153, "V"), + (0x154, "M", "ŕ"), + (0x155, "V"), + (0x156, "M", "ŗ"), + (0x157, "V"), + (0x158, "M", "ř"), + (0x159, "V"), + (0x15A, "M", "ś"), + (0x15B, "V"), + (0x15C, "M", "ŝ"), + (0x15D, "V"), + (0x15E, "M", "ş"), + (0x15F, "V"), + (0x160, "M", "š"), + (0x161, "V"), + (0x162, "M", "ţ"), + (0x163, "V"), + (0x164, "M", "ť"), + (0x165, "V"), + (0x166, "M", "ŧ"), + (0x167, "V"), + (0x168, "M", "ũ"), + (0x169, "V"), + (0x16A, "M", "ū"), + (0x16B, "V"), + (0x16C, "M", "ŭ"), + (0x16D, "V"), + (0x16E, "M", "ů"), + (0x16F, "V"), + (0x170, "M", "ű"), + (0x171, "V"), + (0x172, "M", "ų"), + (0x173, "V"), + (0x174, "M", "ŵ"), + (0x175, "V"), + (0x176, "M", "ŷ"), + (0x177, "V"), + (0x178, "M", "ÿ"), + (0x179, "M", "ź"), + (0x17A, "V"), + (0x17B, "M", "ż"), + (0x17C, "V"), + (0x17D, "M", "ž"), + (0x17E, "V"), + (0x17F, "M", "s"), + (0x180, "V"), + (0x181, "M", "ɓ"), + (0x182, "M", "ƃ"), + (0x183, "V"), + (0x184, "M", "ƅ"), + (0x185, "V"), + (0x186, "M", "ɔ"), + (0x187, "M", "ƈ"), + (0x188, "V"), + (0x189, "M", "ɖ"), + (0x18A, "M", "ɗ"), + (0x18B, "M", "ƌ"), + (0x18C, "V"), + (0x18E, "M", "ǝ"), + (0x18F, "M", "ə"), + (0x190, "M", "ɛ"), + (0x191, "M", "ƒ"), + (0x192, "V"), + (0x193, "M", "ɠ"), + ] + + +def _seg_4() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x194, "M", "ɣ"), + (0x195, "V"), + (0x196, "M", "ɩ"), + (0x197, "M", "ɨ"), + (0x198, "M", "ƙ"), + (0x199, "V"), + (0x19C, "M", "ɯ"), + (0x19D, "M", "ɲ"), + (0x19E, "V"), + (0x19F, "M", "ɵ"), + (0x1A0, "M", "ơ"), + (0x1A1, "V"), + (0x1A2, "M", "ƣ"), + (0x1A3, "V"), + (0x1A4, "M", "ƥ"), + (0x1A5, "V"), + (0x1A6, "M", "ʀ"), + (0x1A7, "M", "ƨ"), + (0x1A8, "V"), + (0x1A9, "M", "ʃ"), + (0x1AA, "V"), + (0x1AC, "M", "ƭ"), + (0x1AD, "V"), + (0x1AE, "M", "ʈ"), + (0x1AF, "M", "ư"), + (0x1B0, "V"), + (0x1B1, "M", "ʊ"), + (0x1B2, "M", "ʋ"), + (0x1B3, "M", "ƴ"), + (0x1B4, "V"), + (0x1B5, "M", "ƶ"), + (0x1B6, "V"), + (0x1B7, "M", "ʒ"), + (0x1B8, "M", "ƹ"), + (0x1B9, "V"), + (0x1BC, "M", "ƽ"), + (0x1BD, "V"), + (0x1C4, "M", "dž"), + (0x1C7, "M", "lj"), + (0x1CA, "M", "nj"), + (0x1CD, "M", "ǎ"), + (0x1CE, "V"), + (0x1CF, "M", "ǐ"), + (0x1D0, "V"), + (0x1D1, "M", "ǒ"), + (0x1D2, "V"), + (0x1D3, "M", "ǔ"), + (0x1D4, "V"), + (0x1D5, "M", "ǖ"), + (0x1D6, "V"), + (0x1D7, "M", "ǘ"), + (0x1D8, "V"), + (0x1D9, "M", "ǚ"), + (0x1DA, "V"), + (0x1DB, "M", "ǜ"), + (0x1DC, "V"), + (0x1DE, "M", "ǟ"), + (0x1DF, "V"), + (0x1E0, "M", "ǡ"), + (0x1E1, "V"), + (0x1E2, "M", "ǣ"), + (0x1E3, "V"), + (0x1E4, "M", "ǥ"), + (0x1E5, "V"), + (0x1E6, "M", "ǧ"), + (0x1E7, "V"), + (0x1E8, "M", "ǩ"), + (0x1E9, "V"), + (0x1EA, "M", "ǫ"), + (0x1EB, "V"), + (0x1EC, "M", "ǭ"), + (0x1ED, "V"), + (0x1EE, "M", "ǯ"), + (0x1EF, "V"), + (0x1F1, "M", "dz"), + (0x1F4, "M", "ǵ"), + (0x1F5, "V"), + (0x1F6, "M", "ƕ"), + (0x1F7, "M", "ƿ"), + (0x1F8, "M", "ǹ"), + (0x1F9, "V"), + (0x1FA, "M", "ǻ"), + (0x1FB, "V"), + (0x1FC, "M", "ǽ"), + (0x1FD, "V"), + (0x1FE, "M", "ǿ"), + (0x1FF, "V"), + (0x200, "M", "ȁ"), + (0x201, "V"), + (0x202, "M", "ȃ"), + (0x203, "V"), + (0x204, "M", "ȅ"), + (0x205, "V"), + (0x206, "M", "ȇ"), + (0x207, "V"), + (0x208, "M", "ȉ"), + (0x209, "V"), + (0x20A, "M", "ȋ"), + (0x20B, "V"), + (0x20C, "M", "ȍ"), + ] + + +def _seg_5() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x20D, "V"), + (0x20E, "M", "ȏ"), + (0x20F, "V"), + (0x210, "M", "ȑ"), + (0x211, "V"), + (0x212, "M", "ȓ"), + (0x213, "V"), + (0x214, "M", "ȕ"), + (0x215, "V"), + (0x216, "M", "ȗ"), + (0x217, "V"), + (0x218, "M", "ș"), + (0x219, "V"), + (0x21A, "M", "ț"), + (0x21B, "V"), + (0x21C, "M", "ȝ"), + (0x21D, "V"), + (0x21E, "M", "ȟ"), + (0x21F, "V"), + (0x220, "M", "ƞ"), + (0x221, "V"), + (0x222, "M", "ȣ"), + (0x223, "V"), + (0x224, "M", "ȥ"), + (0x225, "V"), + (0x226, "M", "ȧ"), + (0x227, "V"), + (0x228, "M", "ȩ"), + (0x229, "V"), + (0x22A, "M", "ȫ"), + (0x22B, "V"), + (0x22C, "M", "ȭ"), + (0x22D, "V"), + (0x22E, "M", "ȯ"), + (0x22F, "V"), + (0x230, "M", "ȱ"), + (0x231, "V"), + (0x232, "M", "ȳ"), + (0x233, "V"), + (0x23A, "M", "ⱥ"), + (0x23B, "M", "ȼ"), + (0x23C, "V"), + (0x23D, "M", "ƚ"), + (0x23E, "M", "ⱦ"), + (0x23F, "V"), + (0x241, "M", "ɂ"), + (0x242, "V"), + (0x243, "M", "ƀ"), + (0x244, "M", "ʉ"), + (0x245, "M", "ʌ"), + (0x246, "M", "ɇ"), + (0x247, "V"), + (0x248, "M", "ɉ"), + (0x249, "V"), + (0x24A, "M", "ɋ"), + (0x24B, "V"), + (0x24C, "M", "ɍ"), + (0x24D, "V"), + (0x24E, "M", "ɏ"), + (0x24F, "V"), + (0x2B0, "M", "h"), + (0x2B1, "M", "ɦ"), + (0x2B2, "M", "j"), + (0x2B3, "M", "r"), + (0x2B4, "M", "ɹ"), + (0x2B5, "M", "ɻ"), + (0x2B6, "M", "ʁ"), + (0x2B7, "M", "w"), + (0x2B8, "M", "y"), + (0x2B9, "V"), + (0x2D8, "3", " ̆"), + (0x2D9, "3", " ̇"), + (0x2DA, "3", " ̊"), + (0x2DB, "3", " ̨"), + (0x2DC, "3", " ̃"), + (0x2DD, "3", " ̋"), + (0x2DE, "V"), + (0x2E0, "M", "ɣ"), + (0x2E1, "M", "l"), + (0x2E2, "M", "s"), + (0x2E3, "M", "x"), + (0x2E4, "M", "ʕ"), + (0x2E5, "V"), + (0x340, "M", "̀"), + (0x341, "M", "́"), + (0x342, "V"), + (0x343, "M", "̓"), + (0x344, "M", "̈́"), + (0x345, "M", "ι"), + (0x346, "V"), + (0x34F, "I"), + (0x350, "V"), + (0x370, "M", "ͱ"), + (0x371, "V"), + (0x372, "M", "ͳ"), + (0x373, "V"), + (0x374, "M", "ʹ"), + (0x375, "V"), + (0x376, "M", "ͷ"), + (0x377, "V"), + ] + + +def _seg_6() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x378, "X"), + (0x37A, "3", " ι"), + (0x37B, "V"), + (0x37E, "3", ";"), + (0x37F, "M", "ϳ"), + (0x380, "X"), + (0x384, "3", " ́"), + (0x385, "3", " ̈́"), + (0x386, "M", "ά"), + (0x387, "M", "·"), + (0x388, "M", "έ"), + (0x389, "M", "ή"), + (0x38A, "M", "ί"), + (0x38B, "X"), + (0x38C, "M", "ό"), + (0x38D, "X"), + (0x38E, "M", "ύ"), + (0x38F, "M", "ώ"), + (0x390, "V"), + (0x391, "M", "α"), + (0x392, "M", "β"), + (0x393, "M", "γ"), + (0x394, "M", "δ"), + (0x395, "M", "ε"), + (0x396, "M", "ζ"), + (0x397, "M", "η"), + (0x398, "M", "θ"), + (0x399, "M", "ι"), + (0x39A, "M", "κ"), + (0x39B, "M", "λ"), + (0x39C, "M", "μ"), + (0x39D, "M", "ν"), + (0x39E, "M", "ξ"), + (0x39F, "M", "ο"), + (0x3A0, "M", "π"), + (0x3A1, "M", "ρ"), + (0x3A2, "X"), + (0x3A3, "M", "σ"), + (0x3A4, "M", "τ"), + (0x3A5, "M", "υ"), + (0x3A6, "M", "φ"), + (0x3A7, "M", "χ"), + (0x3A8, "M", "ψ"), + (0x3A9, "M", "ω"), + (0x3AA, "M", "ϊ"), + (0x3AB, "M", "ϋ"), + (0x3AC, "V"), + (0x3C2, "D", "σ"), + (0x3C3, "V"), + (0x3CF, "M", "ϗ"), + (0x3D0, "M", "β"), + (0x3D1, "M", "θ"), + (0x3D2, "M", "υ"), + (0x3D3, "M", "ύ"), + (0x3D4, "M", "ϋ"), + (0x3D5, "M", "φ"), + (0x3D6, "M", "π"), + (0x3D7, "V"), + (0x3D8, "M", "ϙ"), + (0x3D9, "V"), + (0x3DA, "M", "ϛ"), + (0x3DB, "V"), + (0x3DC, "M", "ϝ"), + (0x3DD, "V"), + (0x3DE, "M", "ϟ"), + (0x3DF, "V"), + (0x3E0, "M", "ϡ"), + (0x3E1, "V"), + (0x3E2, "M", "ϣ"), + (0x3E3, "V"), + (0x3E4, "M", "ϥ"), + (0x3E5, "V"), + (0x3E6, "M", "ϧ"), + (0x3E7, "V"), + (0x3E8, "M", "ϩ"), + (0x3E9, "V"), + (0x3EA, "M", "ϫ"), + (0x3EB, "V"), + (0x3EC, "M", "ϭ"), + (0x3ED, "V"), + (0x3EE, "M", "ϯ"), + (0x3EF, "V"), + (0x3F0, "M", "κ"), + (0x3F1, "M", "ρ"), + (0x3F2, "M", "σ"), + (0x3F3, "V"), + (0x3F4, "M", "θ"), + (0x3F5, "M", "ε"), + (0x3F6, "V"), + (0x3F7, "M", "ϸ"), + (0x3F8, "V"), + (0x3F9, "M", "σ"), + (0x3FA, "M", "ϻ"), + (0x3FB, "V"), + (0x3FD, "M", "ͻ"), + (0x3FE, "M", "ͼ"), + (0x3FF, "M", "ͽ"), + (0x400, "M", "ѐ"), + (0x401, "M", "ё"), + (0x402, "M", "ђ"), + ] + + +def _seg_7() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x403, "M", "ѓ"), + (0x404, "M", "є"), + (0x405, "M", "ѕ"), + (0x406, "M", "і"), + (0x407, "M", "ї"), + (0x408, "M", "ј"), + (0x409, "M", "љ"), + (0x40A, "M", "њ"), + (0x40B, "M", "ћ"), + (0x40C, "M", "ќ"), + (0x40D, "M", "ѝ"), + (0x40E, "M", "ў"), + (0x40F, "M", "џ"), + (0x410, "M", "а"), + (0x411, "M", "б"), + (0x412, "M", "в"), + (0x413, "M", "г"), + (0x414, "M", "д"), + (0x415, "M", "е"), + (0x416, "M", "ж"), + (0x417, "M", "з"), + (0x418, "M", "и"), + (0x419, "M", "й"), + (0x41A, "M", "к"), + (0x41B, "M", "л"), + (0x41C, "M", "м"), + (0x41D, "M", "н"), + (0x41E, "M", "о"), + (0x41F, "M", "п"), + (0x420, "M", "р"), + (0x421, "M", "с"), + (0x422, "M", "т"), + (0x423, "M", "у"), + (0x424, "M", "ф"), + (0x425, "M", "х"), + (0x426, "M", "ц"), + (0x427, "M", "ч"), + (0x428, "M", "ш"), + (0x429, "M", "щ"), + (0x42A, "M", "ъ"), + (0x42B, "M", "ы"), + (0x42C, "M", "ь"), + (0x42D, "M", "э"), + (0x42E, "M", "ю"), + (0x42F, "M", "я"), + (0x430, "V"), + (0x460, "M", "ѡ"), + (0x461, "V"), + (0x462, "M", "ѣ"), + (0x463, "V"), + (0x464, "M", "ѥ"), + (0x465, "V"), + (0x466, "M", "ѧ"), + (0x467, "V"), + (0x468, "M", "ѩ"), + (0x469, "V"), + (0x46A, "M", "ѫ"), + (0x46B, "V"), + (0x46C, "M", "ѭ"), + (0x46D, "V"), + (0x46E, "M", "ѯ"), + (0x46F, "V"), + (0x470, "M", "ѱ"), + (0x471, "V"), + (0x472, "M", "ѳ"), + (0x473, "V"), + (0x474, "M", "ѵ"), + (0x475, "V"), + (0x476, "M", "ѷ"), + (0x477, "V"), + (0x478, "M", "ѹ"), + (0x479, "V"), + (0x47A, "M", "ѻ"), + (0x47B, "V"), + (0x47C, "M", "ѽ"), + (0x47D, "V"), + (0x47E, "M", "ѿ"), + (0x47F, "V"), + (0x480, "M", "ҁ"), + (0x481, "V"), + (0x48A, "M", "ҋ"), + (0x48B, "V"), + (0x48C, "M", "ҍ"), + (0x48D, "V"), + (0x48E, "M", "ҏ"), + (0x48F, "V"), + (0x490, "M", "ґ"), + (0x491, "V"), + (0x492, "M", "ғ"), + (0x493, "V"), + (0x494, "M", "ҕ"), + (0x495, "V"), + (0x496, "M", "җ"), + (0x497, "V"), + (0x498, "M", "ҙ"), + (0x499, "V"), + (0x49A, "M", "қ"), + (0x49B, "V"), + (0x49C, "M", "ҝ"), + (0x49D, "V"), + ] + + +def _seg_8() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x49E, "M", "ҟ"), + (0x49F, "V"), + (0x4A0, "M", "ҡ"), + (0x4A1, "V"), + (0x4A2, "M", "ң"), + (0x4A3, "V"), + (0x4A4, "M", "ҥ"), + (0x4A5, "V"), + (0x4A6, "M", "ҧ"), + (0x4A7, "V"), + (0x4A8, "M", "ҩ"), + (0x4A9, "V"), + (0x4AA, "M", "ҫ"), + (0x4AB, "V"), + (0x4AC, "M", "ҭ"), + (0x4AD, "V"), + (0x4AE, "M", "ү"), + (0x4AF, "V"), + (0x4B0, "M", "ұ"), + (0x4B1, "V"), + (0x4B2, "M", "ҳ"), + (0x4B3, "V"), + (0x4B4, "M", "ҵ"), + (0x4B5, "V"), + (0x4B6, "M", "ҷ"), + (0x4B7, "V"), + (0x4B8, "M", "ҹ"), + (0x4B9, "V"), + (0x4BA, "M", "һ"), + (0x4BB, "V"), + (0x4BC, "M", "ҽ"), + (0x4BD, "V"), + (0x4BE, "M", "ҿ"), + (0x4BF, "V"), + (0x4C0, "X"), + (0x4C1, "M", "ӂ"), + (0x4C2, "V"), + (0x4C3, "M", "ӄ"), + (0x4C4, "V"), + (0x4C5, "M", "ӆ"), + (0x4C6, "V"), + (0x4C7, "M", "ӈ"), + (0x4C8, "V"), + (0x4C9, "M", "ӊ"), + (0x4CA, "V"), + (0x4CB, "M", "ӌ"), + (0x4CC, "V"), + (0x4CD, "M", "ӎ"), + (0x4CE, "V"), + (0x4D0, "M", "ӑ"), + (0x4D1, "V"), + (0x4D2, "M", "ӓ"), + (0x4D3, "V"), + (0x4D4, "M", "ӕ"), + (0x4D5, "V"), + (0x4D6, "M", "ӗ"), + (0x4D7, "V"), + (0x4D8, "M", "ә"), + (0x4D9, "V"), + (0x4DA, "M", "ӛ"), + (0x4DB, "V"), + (0x4DC, "M", "ӝ"), + (0x4DD, "V"), + (0x4DE, "M", "ӟ"), + (0x4DF, "V"), + (0x4E0, "M", "ӡ"), + (0x4E1, "V"), + (0x4E2, "M", "ӣ"), + (0x4E3, "V"), + (0x4E4, "M", "ӥ"), + (0x4E5, "V"), + (0x4E6, "M", "ӧ"), + (0x4E7, "V"), + (0x4E8, "M", "ө"), + (0x4E9, "V"), + (0x4EA, "M", "ӫ"), + (0x4EB, "V"), + (0x4EC, "M", "ӭ"), + (0x4ED, "V"), + (0x4EE, "M", "ӯ"), + (0x4EF, "V"), + (0x4F0, "M", "ӱ"), + (0x4F1, "V"), + (0x4F2, "M", "ӳ"), + (0x4F3, "V"), + (0x4F4, "M", "ӵ"), + (0x4F5, "V"), + (0x4F6, "M", "ӷ"), + (0x4F7, "V"), + (0x4F8, "M", "ӹ"), + (0x4F9, "V"), + (0x4FA, "M", "ӻ"), + (0x4FB, "V"), + (0x4FC, "M", "ӽ"), + (0x4FD, "V"), + (0x4FE, "M", "ӿ"), + (0x4FF, "V"), + (0x500, "M", "ԁ"), + (0x501, "V"), + (0x502, "M", "ԃ"), + ] + + +def _seg_9() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x503, "V"), + (0x504, "M", "ԅ"), + (0x505, "V"), + (0x506, "M", "ԇ"), + (0x507, "V"), + (0x508, "M", "ԉ"), + (0x509, "V"), + (0x50A, "M", "ԋ"), + (0x50B, "V"), + (0x50C, "M", "ԍ"), + (0x50D, "V"), + (0x50E, "M", "ԏ"), + (0x50F, "V"), + (0x510, "M", "ԑ"), + (0x511, "V"), + (0x512, "M", "ԓ"), + (0x513, "V"), + (0x514, "M", "ԕ"), + (0x515, "V"), + (0x516, "M", "ԗ"), + (0x517, "V"), + (0x518, "M", "ԙ"), + (0x519, "V"), + (0x51A, "M", "ԛ"), + (0x51B, "V"), + (0x51C, "M", "ԝ"), + (0x51D, "V"), + (0x51E, "M", "ԟ"), + (0x51F, "V"), + (0x520, "M", "ԡ"), + (0x521, "V"), + (0x522, "M", "ԣ"), + (0x523, "V"), + (0x524, "M", "ԥ"), + (0x525, "V"), + (0x526, "M", "ԧ"), + (0x527, "V"), + (0x528, "M", "ԩ"), + (0x529, "V"), + (0x52A, "M", "ԫ"), + (0x52B, "V"), + (0x52C, "M", "ԭ"), + (0x52D, "V"), + (0x52E, "M", "ԯ"), + (0x52F, "V"), + (0x530, "X"), + (0x531, "M", "ա"), + (0x532, "M", "բ"), + (0x533, "M", "գ"), + (0x534, "M", "դ"), + (0x535, "M", "ե"), + (0x536, "M", "զ"), + (0x537, "M", "է"), + (0x538, "M", "ը"), + (0x539, "M", "թ"), + (0x53A, "M", "ժ"), + (0x53B, "M", "ի"), + (0x53C, "M", "լ"), + (0x53D, "M", "խ"), + (0x53E, "M", "ծ"), + (0x53F, "M", "կ"), + (0x540, "M", "հ"), + (0x541, "M", "ձ"), + (0x542, "M", "ղ"), + (0x543, "M", "ճ"), + (0x544, "M", "մ"), + (0x545, "M", "յ"), + (0x546, "M", "ն"), + (0x547, "M", "շ"), + (0x548, "M", "ո"), + (0x549, "M", "չ"), + (0x54A, "M", "պ"), + (0x54B, "M", "ջ"), + (0x54C, "M", "ռ"), + (0x54D, "M", "ս"), + (0x54E, "M", "վ"), + (0x54F, "M", "տ"), + (0x550, "M", "ր"), + (0x551, "M", "ց"), + (0x552, "M", "ւ"), + (0x553, "M", "փ"), + (0x554, "M", "ք"), + (0x555, "M", "օ"), + (0x556, "M", "ֆ"), + (0x557, "X"), + (0x559, "V"), + (0x587, "M", "եւ"), + (0x588, "V"), + (0x58B, "X"), + (0x58D, "V"), + (0x590, "X"), + (0x591, "V"), + (0x5C8, "X"), + (0x5D0, "V"), + (0x5EB, "X"), + (0x5EF, "V"), + (0x5F5, "X"), + (0x606, "V"), + (0x61C, "X"), + (0x61D, "V"), + ] + + +def _seg_10() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x675, "M", "اٴ"), + (0x676, "M", "وٴ"), + (0x677, "M", "ۇٴ"), + (0x678, "M", "يٴ"), + (0x679, "V"), + (0x6DD, "X"), + (0x6DE, "V"), + (0x70E, "X"), + (0x710, "V"), + (0x74B, "X"), + (0x74D, "V"), + (0x7B2, "X"), + (0x7C0, "V"), + (0x7FB, "X"), + (0x7FD, "V"), + (0x82E, "X"), + (0x830, "V"), + (0x83F, "X"), + (0x840, "V"), + (0x85C, "X"), + (0x85E, "V"), + (0x85F, "X"), + (0x860, "V"), + (0x86B, "X"), + (0x870, "V"), + (0x88F, "X"), + (0x898, "V"), + (0x8E2, "X"), + (0x8E3, "V"), + (0x958, "M", "क़"), + (0x959, "M", "ख़"), + (0x95A, "M", "ग़"), + (0x95B, "M", "ज़"), + (0x95C, "M", "ड़"), + (0x95D, "M", "ढ़"), + (0x95E, "M", "फ़"), + (0x95F, "M", "य़"), + (0x960, "V"), + (0x984, "X"), + (0x985, "V"), + (0x98D, "X"), + (0x98F, "V"), + (0x991, "X"), + (0x993, "V"), + (0x9A9, "X"), + (0x9AA, "V"), + (0x9B1, "X"), + (0x9B2, "V"), + (0x9B3, "X"), + (0x9B6, "V"), + (0x9BA, "X"), + (0x9BC, "V"), + (0x9C5, "X"), + (0x9C7, "V"), + (0x9C9, "X"), + (0x9CB, "V"), + (0x9CF, "X"), + (0x9D7, "V"), + (0x9D8, "X"), + (0x9DC, "M", "ড়"), + (0x9DD, "M", "ঢ়"), + (0x9DE, "X"), + (0x9DF, "M", "য়"), + (0x9E0, "V"), + (0x9E4, "X"), + (0x9E6, "V"), + (0x9FF, "X"), + (0xA01, "V"), + (0xA04, "X"), + (0xA05, "V"), + (0xA0B, "X"), + (0xA0F, "V"), + (0xA11, "X"), + (0xA13, "V"), + (0xA29, "X"), + (0xA2A, "V"), + (0xA31, "X"), + (0xA32, "V"), + (0xA33, "M", "ਲ਼"), + (0xA34, "X"), + (0xA35, "V"), + (0xA36, "M", "ਸ਼"), + (0xA37, "X"), + (0xA38, "V"), + (0xA3A, "X"), + (0xA3C, "V"), + (0xA3D, "X"), + (0xA3E, "V"), + (0xA43, "X"), + (0xA47, "V"), + (0xA49, "X"), + (0xA4B, "V"), + (0xA4E, "X"), + (0xA51, "V"), + (0xA52, "X"), + (0xA59, "M", "ਖ਼"), + (0xA5A, "M", "ਗ਼"), + (0xA5B, "M", "ਜ਼"), + (0xA5C, "V"), + (0xA5D, "X"), + ] + + +def _seg_11() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xA5E, "M", "ਫ਼"), + (0xA5F, "X"), + (0xA66, "V"), + (0xA77, "X"), + (0xA81, "V"), + (0xA84, "X"), + (0xA85, "V"), + (0xA8E, "X"), + (0xA8F, "V"), + (0xA92, "X"), + (0xA93, "V"), + (0xAA9, "X"), + (0xAAA, "V"), + (0xAB1, "X"), + (0xAB2, "V"), + (0xAB4, "X"), + (0xAB5, "V"), + (0xABA, "X"), + (0xABC, "V"), + (0xAC6, "X"), + (0xAC7, "V"), + (0xACA, "X"), + (0xACB, "V"), + (0xACE, "X"), + (0xAD0, "V"), + (0xAD1, "X"), + (0xAE0, "V"), + (0xAE4, "X"), + (0xAE6, "V"), + (0xAF2, "X"), + (0xAF9, "V"), + (0xB00, "X"), + (0xB01, "V"), + (0xB04, "X"), + (0xB05, "V"), + (0xB0D, "X"), + (0xB0F, "V"), + (0xB11, "X"), + (0xB13, "V"), + (0xB29, "X"), + (0xB2A, "V"), + (0xB31, "X"), + (0xB32, "V"), + (0xB34, "X"), + (0xB35, "V"), + (0xB3A, "X"), + (0xB3C, "V"), + (0xB45, "X"), + (0xB47, "V"), + (0xB49, "X"), + (0xB4B, "V"), + (0xB4E, "X"), + (0xB55, "V"), + (0xB58, "X"), + (0xB5C, "M", "ଡ଼"), + (0xB5D, "M", "ଢ଼"), + (0xB5E, "X"), + (0xB5F, "V"), + (0xB64, "X"), + (0xB66, "V"), + (0xB78, "X"), + (0xB82, "V"), + (0xB84, "X"), + (0xB85, "V"), + (0xB8B, "X"), + (0xB8E, "V"), + (0xB91, "X"), + (0xB92, "V"), + (0xB96, "X"), + (0xB99, "V"), + (0xB9B, "X"), + (0xB9C, "V"), + (0xB9D, "X"), + (0xB9E, "V"), + (0xBA0, "X"), + (0xBA3, "V"), + (0xBA5, "X"), + (0xBA8, "V"), + (0xBAB, "X"), + (0xBAE, "V"), + (0xBBA, "X"), + (0xBBE, "V"), + (0xBC3, "X"), + (0xBC6, "V"), + (0xBC9, "X"), + (0xBCA, "V"), + (0xBCE, "X"), + (0xBD0, "V"), + (0xBD1, "X"), + (0xBD7, "V"), + (0xBD8, "X"), + (0xBE6, "V"), + (0xBFB, "X"), + (0xC00, "V"), + (0xC0D, "X"), + (0xC0E, "V"), + (0xC11, "X"), + (0xC12, "V"), + (0xC29, "X"), + (0xC2A, "V"), + ] + + +def _seg_12() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xC3A, "X"), + (0xC3C, "V"), + (0xC45, "X"), + (0xC46, "V"), + (0xC49, "X"), + (0xC4A, "V"), + (0xC4E, "X"), + (0xC55, "V"), + (0xC57, "X"), + (0xC58, "V"), + (0xC5B, "X"), + (0xC5D, "V"), + (0xC5E, "X"), + (0xC60, "V"), + (0xC64, "X"), + (0xC66, "V"), + (0xC70, "X"), + (0xC77, "V"), + (0xC8D, "X"), + (0xC8E, "V"), + (0xC91, "X"), + (0xC92, "V"), + (0xCA9, "X"), + (0xCAA, "V"), + (0xCB4, "X"), + (0xCB5, "V"), + (0xCBA, "X"), + (0xCBC, "V"), + (0xCC5, "X"), + (0xCC6, "V"), + (0xCC9, "X"), + (0xCCA, "V"), + (0xCCE, "X"), + (0xCD5, "V"), + (0xCD7, "X"), + (0xCDD, "V"), + (0xCDF, "X"), + (0xCE0, "V"), + (0xCE4, "X"), + (0xCE6, "V"), + (0xCF0, "X"), + (0xCF1, "V"), + (0xCF4, "X"), + (0xD00, "V"), + (0xD0D, "X"), + (0xD0E, "V"), + (0xD11, "X"), + (0xD12, "V"), + (0xD45, "X"), + (0xD46, "V"), + (0xD49, "X"), + (0xD4A, "V"), + (0xD50, "X"), + (0xD54, "V"), + (0xD64, "X"), + (0xD66, "V"), + (0xD80, "X"), + (0xD81, "V"), + (0xD84, "X"), + (0xD85, "V"), + (0xD97, "X"), + (0xD9A, "V"), + (0xDB2, "X"), + (0xDB3, "V"), + (0xDBC, "X"), + (0xDBD, "V"), + (0xDBE, "X"), + (0xDC0, "V"), + (0xDC7, "X"), + (0xDCA, "V"), + (0xDCB, "X"), + (0xDCF, "V"), + (0xDD5, "X"), + (0xDD6, "V"), + (0xDD7, "X"), + (0xDD8, "V"), + (0xDE0, "X"), + (0xDE6, "V"), + (0xDF0, "X"), + (0xDF2, "V"), + (0xDF5, "X"), + (0xE01, "V"), + (0xE33, "M", "ํา"), + (0xE34, "V"), + (0xE3B, "X"), + (0xE3F, "V"), + (0xE5C, "X"), + (0xE81, "V"), + (0xE83, "X"), + (0xE84, "V"), + (0xE85, "X"), + (0xE86, "V"), + (0xE8B, "X"), + (0xE8C, "V"), + (0xEA4, "X"), + (0xEA5, "V"), + (0xEA6, "X"), + (0xEA7, "V"), + (0xEB3, "M", "ໍາ"), + (0xEB4, "V"), + ] + + +def _seg_13() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xEBE, "X"), + (0xEC0, "V"), + (0xEC5, "X"), + (0xEC6, "V"), + (0xEC7, "X"), + (0xEC8, "V"), + (0xECF, "X"), + (0xED0, "V"), + (0xEDA, "X"), + (0xEDC, "M", "ຫນ"), + (0xEDD, "M", "ຫມ"), + (0xEDE, "V"), + (0xEE0, "X"), + (0xF00, "V"), + (0xF0C, "M", "་"), + (0xF0D, "V"), + (0xF43, "M", "གྷ"), + (0xF44, "V"), + (0xF48, "X"), + (0xF49, "V"), + (0xF4D, "M", "ཌྷ"), + (0xF4E, "V"), + (0xF52, "M", "དྷ"), + (0xF53, "V"), + (0xF57, "M", "བྷ"), + (0xF58, "V"), + (0xF5C, "M", "ཛྷ"), + (0xF5D, "V"), + (0xF69, "M", "ཀྵ"), + (0xF6A, "V"), + (0xF6D, "X"), + (0xF71, "V"), + (0xF73, "M", "ཱི"), + (0xF74, "V"), + (0xF75, "M", "ཱུ"), + (0xF76, "M", "ྲྀ"), + (0xF77, "M", "ྲཱྀ"), + (0xF78, "M", "ླྀ"), + (0xF79, "M", "ླཱྀ"), + (0xF7A, "V"), + (0xF81, "M", "ཱྀ"), + (0xF82, "V"), + (0xF93, "M", "ྒྷ"), + (0xF94, "V"), + (0xF98, "X"), + (0xF99, "V"), + (0xF9D, "M", "ྜྷ"), + (0xF9E, "V"), + (0xFA2, "M", "ྡྷ"), + (0xFA3, "V"), + (0xFA7, "M", "ྦྷ"), + (0xFA8, "V"), + (0xFAC, "M", "ྫྷ"), + (0xFAD, "V"), + (0xFB9, "M", "ྐྵ"), + (0xFBA, "V"), + (0xFBD, "X"), + (0xFBE, "V"), + (0xFCD, "X"), + (0xFCE, "V"), + (0xFDB, "X"), + (0x1000, "V"), + (0x10A0, "X"), + (0x10C7, "M", "ⴧ"), + (0x10C8, "X"), + (0x10CD, "M", "ⴭ"), + (0x10CE, "X"), + (0x10D0, "V"), + (0x10FC, "M", "ნ"), + (0x10FD, "V"), + (0x115F, "X"), + (0x1161, "V"), + (0x1249, "X"), + (0x124A, "V"), + (0x124E, "X"), + (0x1250, "V"), + (0x1257, "X"), + (0x1258, "V"), + (0x1259, "X"), + (0x125A, "V"), + (0x125E, "X"), + (0x1260, "V"), + (0x1289, "X"), + (0x128A, "V"), + (0x128E, "X"), + (0x1290, "V"), + (0x12B1, "X"), + (0x12B2, "V"), + (0x12B6, "X"), + (0x12B8, "V"), + (0x12BF, "X"), + (0x12C0, "V"), + (0x12C1, "X"), + (0x12C2, "V"), + (0x12C6, "X"), + (0x12C8, "V"), + (0x12D7, "X"), + (0x12D8, "V"), + (0x1311, "X"), + (0x1312, "V"), + ] + + +def _seg_14() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1316, "X"), + (0x1318, "V"), + (0x135B, "X"), + (0x135D, "V"), + (0x137D, "X"), + (0x1380, "V"), + (0x139A, "X"), + (0x13A0, "V"), + (0x13F6, "X"), + (0x13F8, "M", "Ᏸ"), + (0x13F9, "M", "Ᏹ"), + (0x13FA, "M", "Ᏺ"), + (0x13FB, "M", "Ᏻ"), + (0x13FC, "M", "Ᏼ"), + (0x13FD, "M", "Ᏽ"), + (0x13FE, "X"), + (0x1400, "V"), + (0x1680, "X"), + (0x1681, "V"), + (0x169D, "X"), + (0x16A0, "V"), + (0x16F9, "X"), + (0x1700, "V"), + (0x1716, "X"), + (0x171F, "V"), + (0x1737, "X"), + (0x1740, "V"), + (0x1754, "X"), + (0x1760, "V"), + (0x176D, "X"), + (0x176E, "V"), + (0x1771, "X"), + (0x1772, "V"), + (0x1774, "X"), + (0x1780, "V"), + (0x17B4, "X"), + (0x17B6, "V"), + (0x17DE, "X"), + (0x17E0, "V"), + (0x17EA, "X"), + (0x17F0, "V"), + (0x17FA, "X"), + (0x1800, "V"), + (0x1806, "X"), + (0x1807, "V"), + (0x180B, "I"), + (0x180E, "X"), + (0x180F, "I"), + (0x1810, "V"), + (0x181A, "X"), + (0x1820, "V"), + (0x1879, "X"), + (0x1880, "V"), + (0x18AB, "X"), + (0x18B0, "V"), + (0x18F6, "X"), + (0x1900, "V"), + (0x191F, "X"), + (0x1920, "V"), + (0x192C, "X"), + (0x1930, "V"), + (0x193C, "X"), + (0x1940, "V"), + (0x1941, "X"), + (0x1944, "V"), + (0x196E, "X"), + (0x1970, "V"), + (0x1975, "X"), + (0x1980, "V"), + (0x19AC, "X"), + (0x19B0, "V"), + (0x19CA, "X"), + (0x19D0, "V"), + (0x19DB, "X"), + (0x19DE, "V"), + (0x1A1C, "X"), + (0x1A1E, "V"), + (0x1A5F, "X"), + (0x1A60, "V"), + (0x1A7D, "X"), + (0x1A7F, "V"), + (0x1A8A, "X"), + (0x1A90, "V"), + (0x1A9A, "X"), + (0x1AA0, "V"), + (0x1AAE, "X"), + (0x1AB0, "V"), + (0x1ACF, "X"), + (0x1B00, "V"), + (0x1B4D, "X"), + (0x1B50, "V"), + (0x1B7F, "X"), + (0x1B80, "V"), + (0x1BF4, "X"), + (0x1BFC, "V"), + (0x1C38, "X"), + (0x1C3B, "V"), + (0x1C4A, "X"), + (0x1C4D, "V"), + (0x1C80, "M", "в"), + ] + + +def _seg_15() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1C81, "M", "д"), + (0x1C82, "M", "о"), + (0x1C83, "M", "с"), + (0x1C84, "M", "т"), + (0x1C86, "M", "ъ"), + (0x1C87, "M", "ѣ"), + (0x1C88, "M", "ꙋ"), + (0x1C89, "X"), + (0x1C90, "M", "ა"), + (0x1C91, "M", "ბ"), + (0x1C92, "M", "გ"), + (0x1C93, "M", "დ"), + (0x1C94, "M", "ე"), + (0x1C95, "M", "ვ"), + (0x1C96, "M", "ზ"), + (0x1C97, "M", "თ"), + (0x1C98, "M", "ი"), + (0x1C99, "M", "კ"), + (0x1C9A, "M", "ლ"), + (0x1C9B, "M", "მ"), + (0x1C9C, "M", "ნ"), + (0x1C9D, "M", "ო"), + (0x1C9E, "M", "პ"), + (0x1C9F, "M", "ჟ"), + (0x1CA0, "M", "რ"), + (0x1CA1, "M", "ს"), + (0x1CA2, "M", "ტ"), + (0x1CA3, "M", "უ"), + (0x1CA4, "M", "ფ"), + (0x1CA5, "M", "ქ"), + (0x1CA6, "M", "ღ"), + (0x1CA7, "M", "ყ"), + (0x1CA8, "M", "შ"), + (0x1CA9, "M", "ჩ"), + (0x1CAA, "M", "ც"), + (0x1CAB, "M", "ძ"), + (0x1CAC, "M", "წ"), + (0x1CAD, "M", "ჭ"), + (0x1CAE, "M", "ხ"), + (0x1CAF, "M", "ჯ"), + (0x1CB0, "M", "ჰ"), + (0x1CB1, "M", "ჱ"), + (0x1CB2, "M", "ჲ"), + (0x1CB3, "M", "ჳ"), + (0x1CB4, "M", "ჴ"), + (0x1CB5, "M", "ჵ"), + (0x1CB6, "M", "ჶ"), + (0x1CB7, "M", "ჷ"), + (0x1CB8, "M", "ჸ"), + (0x1CB9, "M", "ჹ"), + (0x1CBA, "M", "ჺ"), + (0x1CBB, "X"), + (0x1CBD, "M", "ჽ"), + (0x1CBE, "M", "ჾ"), + (0x1CBF, "M", "ჿ"), + (0x1CC0, "V"), + (0x1CC8, "X"), + (0x1CD0, "V"), + (0x1CFB, "X"), + (0x1D00, "V"), + (0x1D2C, "M", "a"), + (0x1D2D, "M", "æ"), + (0x1D2E, "M", "b"), + (0x1D2F, "V"), + (0x1D30, "M", "d"), + (0x1D31, "M", "e"), + (0x1D32, "M", "ǝ"), + (0x1D33, "M", "g"), + (0x1D34, "M", "h"), + (0x1D35, "M", "i"), + (0x1D36, "M", "j"), + (0x1D37, "M", "k"), + (0x1D38, "M", "l"), + (0x1D39, "M", "m"), + (0x1D3A, "M", "n"), + (0x1D3B, "V"), + (0x1D3C, "M", "o"), + (0x1D3D, "M", "ȣ"), + (0x1D3E, "M", "p"), + (0x1D3F, "M", "r"), + (0x1D40, "M", "t"), + (0x1D41, "M", "u"), + (0x1D42, "M", "w"), + (0x1D43, "M", "a"), + (0x1D44, "M", "ɐ"), + (0x1D45, "M", "ɑ"), + (0x1D46, "M", "ᴂ"), + (0x1D47, "M", "b"), + (0x1D48, "M", "d"), + (0x1D49, "M", "e"), + (0x1D4A, "M", "ə"), + (0x1D4B, "M", "ɛ"), + (0x1D4C, "M", "ɜ"), + (0x1D4D, "M", "g"), + (0x1D4E, "V"), + (0x1D4F, "M", "k"), + (0x1D50, "M", "m"), + (0x1D51, "M", "ŋ"), + (0x1D52, "M", "o"), + (0x1D53, "M", "ɔ"), + ] + + +def _seg_16() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1D54, "M", "ᴖ"), + (0x1D55, "M", "ᴗ"), + (0x1D56, "M", "p"), + (0x1D57, "M", "t"), + (0x1D58, "M", "u"), + (0x1D59, "M", "ᴝ"), + (0x1D5A, "M", "ɯ"), + (0x1D5B, "M", "v"), + (0x1D5C, "M", "ᴥ"), + (0x1D5D, "M", "β"), + (0x1D5E, "M", "γ"), + (0x1D5F, "M", "δ"), + (0x1D60, "M", "φ"), + (0x1D61, "M", "χ"), + (0x1D62, "M", "i"), + (0x1D63, "M", "r"), + (0x1D64, "M", "u"), + (0x1D65, "M", "v"), + (0x1D66, "M", "β"), + (0x1D67, "M", "γ"), + (0x1D68, "M", "ρ"), + (0x1D69, "M", "φ"), + (0x1D6A, "M", "χ"), + (0x1D6B, "V"), + (0x1D78, "M", "н"), + (0x1D79, "V"), + (0x1D9B, "M", "ɒ"), + (0x1D9C, "M", "c"), + (0x1D9D, "M", "ɕ"), + (0x1D9E, "M", "ð"), + (0x1D9F, "M", "ɜ"), + (0x1DA0, "M", "f"), + (0x1DA1, "M", "ɟ"), + (0x1DA2, "M", "ɡ"), + (0x1DA3, "M", "ɥ"), + (0x1DA4, "M", "ɨ"), + (0x1DA5, "M", "ɩ"), + (0x1DA6, "M", "ɪ"), + (0x1DA7, "M", "ᵻ"), + (0x1DA8, "M", "ʝ"), + (0x1DA9, "M", "ɭ"), + (0x1DAA, "M", "ᶅ"), + (0x1DAB, "M", "ʟ"), + (0x1DAC, "M", "ɱ"), + (0x1DAD, "M", "ɰ"), + (0x1DAE, "M", "ɲ"), + (0x1DAF, "M", "ɳ"), + (0x1DB0, "M", "ɴ"), + (0x1DB1, "M", "ɵ"), + (0x1DB2, "M", "ɸ"), + (0x1DB3, "M", "ʂ"), + (0x1DB4, "M", "ʃ"), + (0x1DB5, "M", "ƫ"), + (0x1DB6, "M", "ʉ"), + (0x1DB7, "M", "ʊ"), + (0x1DB8, "M", "ᴜ"), + (0x1DB9, "M", "ʋ"), + (0x1DBA, "M", "ʌ"), + (0x1DBB, "M", "z"), + (0x1DBC, "M", "ʐ"), + (0x1DBD, "M", "ʑ"), + (0x1DBE, "M", "ʒ"), + (0x1DBF, "M", "θ"), + (0x1DC0, "V"), + (0x1E00, "M", "ḁ"), + (0x1E01, "V"), + (0x1E02, "M", "ḃ"), + (0x1E03, "V"), + (0x1E04, "M", "ḅ"), + (0x1E05, "V"), + (0x1E06, "M", "ḇ"), + (0x1E07, "V"), + (0x1E08, "M", "ḉ"), + (0x1E09, "V"), + (0x1E0A, "M", "ḋ"), + (0x1E0B, "V"), + (0x1E0C, "M", "ḍ"), + (0x1E0D, "V"), + (0x1E0E, "M", "ḏ"), + (0x1E0F, "V"), + (0x1E10, "M", "ḑ"), + (0x1E11, "V"), + (0x1E12, "M", "ḓ"), + (0x1E13, "V"), + (0x1E14, "M", "ḕ"), + (0x1E15, "V"), + (0x1E16, "M", "ḗ"), + (0x1E17, "V"), + (0x1E18, "M", "ḙ"), + (0x1E19, "V"), + (0x1E1A, "M", "ḛ"), + (0x1E1B, "V"), + (0x1E1C, "M", "ḝ"), + (0x1E1D, "V"), + (0x1E1E, "M", "ḟ"), + (0x1E1F, "V"), + (0x1E20, "M", "ḡ"), + (0x1E21, "V"), + (0x1E22, "M", "ḣ"), + (0x1E23, "V"), + ] + + +def _seg_17() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1E24, "M", "ḥ"), + (0x1E25, "V"), + (0x1E26, "M", "ḧ"), + (0x1E27, "V"), + (0x1E28, "M", "ḩ"), + (0x1E29, "V"), + (0x1E2A, "M", "ḫ"), + (0x1E2B, "V"), + (0x1E2C, "M", "ḭ"), + (0x1E2D, "V"), + (0x1E2E, "M", "ḯ"), + (0x1E2F, "V"), + (0x1E30, "M", "ḱ"), + (0x1E31, "V"), + (0x1E32, "M", "ḳ"), + (0x1E33, "V"), + (0x1E34, "M", "ḵ"), + (0x1E35, "V"), + (0x1E36, "M", "ḷ"), + (0x1E37, "V"), + (0x1E38, "M", "ḹ"), + (0x1E39, "V"), + (0x1E3A, "M", "ḻ"), + (0x1E3B, "V"), + (0x1E3C, "M", "ḽ"), + (0x1E3D, "V"), + (0x1E3E, "M", "ḿ"), + (0x1E3F, "V"), + (0x1E40, "M", "ṁ"), + (0x1E41, "V"), + (0x1E42, "M", "ṃ"), + (0x1E43, "V"), + (0x1E44, "M", "ṅ"), + (0x1E45, "V"), + (0x1E46, "M", "ṇ"), + (0x1E47, "V"), + (0x1E48, "M", "ṉ"), + (0x1E49, "V"), + (0x1E4A, "M", "ṋ"), + (0x1E4B, "V"), + (0x1E4C, "M", "ṍ"), + (0x1E4D, "V"), + (0x1E4E, "M", "ṏ"), + (0x1E4F, "V"), + (0x1E50, "M", "ṑ"), + (0x1E51, "V"), + (0x1E52, "M", "ṓ"), + (0x1E53, "V"), + (0x1E54, "M", "ṕ"), + (0x1E55, "V"), + (0x1E56, "M", "ṗ"), + (0x1E57, "V"), + (0x1E58, "M", "ṙ"), + (0x1E59, "V"), + (0x1E5A, "M", "ṛ"), + (0x1E5B, "V"), + (0x1E5C, "M", "ṝ"), + (0x1E5D, "V"), + (0x1E5E, "M", "ṟ"), + (0x1E5F, "V"), + (0x1E60, "M", "ṡ"), + (0x1E61, "V"), + (0x1E62, "M", "ṣ"), + (0x1E63, "V"), + (0x1E64, "M", "ṥ"), + (0x1E65, "V"), + (0x1E66, "M", "ṧ"), + (0x1E67, "V"), + (0x1E68, "M", "ṩ"), + (0x1E69, "V"), + (0x1E6A, "M", "ṫ"), + (0x1E6B, "V"), + (0x1E6C, "M", "ṭ"), + (0x1E6D, "V"), + (0x1E6E, "M", "ṯ"), + (0x1E6F, "V"), + (0x1E70, "M", "ṱ"), + (0x1E71, "V"), + (0x1E72, "M", "ṳ"), + (0x1E73, "V"), + (0x1E74, "M", "ṵ"), + (0x1E75, "V"), + (0x1E76, "M", "ṷ"), + (0x1E77, "V"), + (0x1E78, "M", "ṹ"), + (0x1E79, "V"), + (0x1E7A, "M", "ṻ"), + (0x1E7B, "V"), + (0x1E7C, "M", "ṽ"), + (0x1E7D, "V"), + (0x1E7E, "M", "ṿ"), + (0x1E7F, "V"), + (0x1E80, "M", "ẁ"), + (0x1E81, "V"), + (0x1E82, "M", "ẃ"), + (0x1E83, "V"), + (0x1E84, "M", "ẅ"), + (0x1E85, "V"), + (0x1E86, "M", "ẇ"), + (0x1E87, "V"), + ] + + +def _seg_18() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1E88, "M", "ẉ"), + (0x1E89, "V"), + (0x1E8A, "M", "ẋ"), + (0x1E8B, "V"), + (0x1E8C, "M", "ẍ"), + (0x1E8D, "V"), + (0x1E8E, "M", "ẏ"), + (0x1E8F, "V"), + (0x1E90, "M", "ẑ"), + (0x1E91, "V"), + (0x1E92, "M", "ẓ"), + (0x1E93, "V"), + (0x1E94, "M", "ẕ"), + (0x1E95, "V"), + (0x1E9A, "M", "aʾ"), + (0x1E9B, "M", "ṡ"), + (0x1E9C, "V"), + (0x1E9E, "M", "ß"), + (0x1E9F, "V"), + (0x1EA0, "M", "ạ"), + (0x1EA1, "V"), + (0x1EA2, "M", "ả"), + (0x1EA3, "V"), + (0x1EA4, "M", "ấ"), + (0x1EA5, "V"), + (0x1EA6, "M", "ầ"), + (0x1EA7, "V"), + (0x1EA8, "M", "ẩ"), + (0x1EA9, "V"), + (0x1EAA, "M", "ẫ"), + (0x1EAB, "V"), + (0x1EAC, "M", "ậ"), + (0x1EAD, "V"), + (0x1EAE, "M", "ắ"), + (0x1EAF, "V"), + (0x1EB0, "M", "ằ"), + (0x1EB1, "V"), + (0x1EB2, "M", "ẳ"), + (0x1EB3, "V"), + (0x1EB4, "M", "ẵ"), + (0x1EB5, "V"), + (0x1EB6, "M", "ặ"), + (0x1EB7, "V"), + (0x1EB8, "M", "ẹ"), + (0x1EB9, "V"), + (0x1EBA, "M", "ẻ"), + (0x1EBB, "V"), + (0x1EBC, "M", "ẽ"), + (0x1EBD, "V"), + (0x1EBE, "M", "ế"), + (0x1EBF, "V"), + (0x1EC0, "M", "ề"), + (0x1EC1, "V"), + (0x1EC2, "M", "ể"), + (0x1EC3, "V"), + (0x1EC4, "M", "ễ"), + (0x1EC5, "V"), + (0x1EC6, "M", "ệ"), + (0x1EC7, "V"), + (0x1EC8, "M", "ỉ"), + (0x1EC9, "V"), + (0x1ECA, "M", "ị"), + (0x1ECB, "V"), + (0x1ECC, "M", "ọ"), + (0x1ECD, "V"), + (0x1ECE, "M", "ỏ"), + (0x1ECF, "V"), + (0x1ED0, "M", "ố"), + (0x1ED1, "V"), + (0x1ED2, "M", "ồ"), + (0x1ED3, "V"), + (0x1ED4, "M", "ổ"), + (0x1ED5, "V"), + (0x1ED6, "M", "ỗ"), + (0x1ED7, "V"), + (0x1ED8, "M", "ộ"), + (0x1ED9, "V"), + (0x1EDA, "M", "ớ"), + (0x1EDB, "V"), + (0x1EDC, "M", "ờ"), + (0x1EDD, "V"), + (0x1EDE, "M", "ở"), + (0x1EDF, "V"), + (0x1EE0, "M", "ỡ"), + (0x1EE1, "V"), + (0x1EE2, "M", "ợ"), + (0x1EE3, "V"), + (0x1EE4, "M", "ụ"), + (0x1EE5, "V"), + (0x1EE6, "M", "ủ"), + (0x1EE7, "V"), + (0x1EE8, "M", "ứ"), + (0x1EE9, "V"), + (0x1EEA, "M", "ừ"), + (0x1EEB, "V"), + (0x1EEC, "M", "ử"), + (0x1EED, "V"), + (0x1EEE, "M", "ữ"), + (0x1EEF, "V"), + (0x1EF0, "M", "ự"), + ] + + +def _seg_19() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1EF1, "V"), + (0x1EF2, "M", "ỳ"), + (0x1EF3, "V"), + (0x1EF4, "M", "ỵ"), + (0x1EF5, "V"), + (0x1EF6, "M", "ỷ"), + (0x1EF7, "V"), + (0x1EF8, "M", "ỹ"), + (0x1EF9, "V"), + (0x1EFA, "M", "ỻ"), + (0x1EFB, "V"), + (0x1EFC, "M", "ỽ"), + (0x1EFD, "V"), + (0x1EFE, "M", "ỿ"), + (0x1EFF, "V"), + (0x1F08, "M", "ἀ"), + (0x1F09, "M", "ἁ"), + (0x1F0A, "M", "ἂ"), + (0x1F0B, "M", "ἃ"), + (0x1F0C, "M", "ἄ"), + (0x1F0D, "M", "ἅ"), + (0x1F0E, "M", "ἆ"), + (0x1F0F, "M", "ἇ"), + (0x1F10, "V"), + (0x1F16, "X"), + (0x1F18, "M", "ἐ"), + (0x1F19, "M", "ἑ"), + (0x1F1A, "M", "ἒ"), + (0x1F1B, "M", "ἓ"), + (0x1F1C, "M", "ἔ"), + (0x1F1D, "M", "ἕ"), + (0x1F1E, "X"), + (0x1F20, "V"), + (0x1F28, "M", "ἠ"), + (0x1F29, "M", "ἡ"), + (0x1F2A, "M", "ἢ"), + (0x1F2B, "M", "ἣ"), + (0x1F2C, "M", "ἤ"), + (0x1F2D, "M", "ἥ"), + (0x1F2E, "M", "ἦ"), + (0x1F2F, "M", "ἧ"), + (0x1F30, "V"), + (0x1F38, "M", "ἰ"), + (0x1F39, "M", "ἱ"), + (0x1F3A, "M", "ἲ"), + (0x1F3B, "M", "ἳ"), + (0x1F3C, "M", "ἴ"), + (0x1F3D, "M", "ἵ"), + (0x1F3E, "M", "ἶ"), + (0x1F3F, "M", "ἷ"), + (0x1F40, "V"), + (0x1F46, "X"), + (0x1F48, "M", "ὀ"), + (0x1F49, "M", "ὁ"), + (0x1F4A, "M", "ὂ"), + (0x1F4B, "M", "ὃ"), + (0x1F4C, "M", "ὄ"), + (0x1F4D, "M", "ὅ"), + (0x1F4E, "X"), + (0x1F50, "V"), + (0x1F58, "X"), + (0x1F59, "M", "ὑ"), + (0x1F5A, "X"), + (0x1F5B, "M", "ὓ"), + (0x1F5C, "X"), + (0x1F5D, "M", "ὕ"), + (0x1F5E, "X"), + (0x1F5F, "M", "ὗ"), + (0x1F60, "V"), + (0x1F68, "M", "ὠ"), + (0x1F69, "M", "ὡ"), + (0x1F6A, "M", "ὢ"), + (0x1F6B, "M", "ὣ"), + (0x1F6C, "M", "ὤ"), + (0x1F6D, "M", "ὥ"), + (0x1F6E, "M", "ὦ"), + (0x1F6F, "M", "ὧ"), + (0x1F70, "V"), + (0x1F71, "M", "ά"), + (0x1F72, "V"), + (0x1F73, "M", "έ"), + (0x1F74, "V"), + (0x1F75, "M", "ή"), + (0x1F76, "V"), + (0x1F77, "M", "ί"), + (0x1F78, "V"), + (0x1F79, "M", "ό"), + (0x1F7A, "V"), + (0x1F7B, "M", "ύ"), + (0x1F7C, "V"), + (0x1F7D, "M", "ώ"), + (0x1F7E, "X"), + (0x1F80, "M", "ἀι"), + (0x1F81, "M", "ἁι"), + (0x1F82, "M", "ἂι"), + (0x1F83, "M", "ἃι"), + (0x1F84, "M", "ἄι"), + (0x1F85, "M", "ἅι"), + (0x1F86, "M", "ἆι"), + (0x1F87, "M", "ἇι"), + ] + + +def _seg_20() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1F88, "M", "ἀι"), + (0x1F89, "M", "ἁι"), + (0x1F8A, "M", "ἂι"), + (0x1F8B, "M", "ἃι"), + (0x1F8C, "M", "ἄι"), + (0x1F8D, "M", "ἅι"), + (0x1F8E, "M", "ἆι"), + (0x1F8F, "M", "ἇι"), + (0x1F90, "M", "ἠι"), + (0x1F91, "M", "ἡι"), + (0x1F92, "M", "ἢι"), + (0x1F93, "M", "ἣι"), + (0x1F94, "M", "ἤι"), + (0x1F95, "M", "ἥι"), + (0x1F96, "M", "ἦι"), + (0x1F97, "M", "ἧι"), + (0x1F98, "M", "ἠι"), + (0x1F99, "M", "ἡι"), + (0x1F9A, "M", "ἢι"), + (0x1F9B, "M", "ἣι"), + (0x1F9C, "M", "ἤι"), + (0x1F9D, "M", "ἥι"), + (0x1F9E, "M", "ἦι"), + (0x1F9F, "M", "ἧι"), + (0x1FA0, "M", "ὠι"), + (0x1FA1, "M", "ὡι"), + (0x1FA2, "M", "ὢι"), + (0x1FA3, "M", "ὣι"), + (0x1FA4, "M", "ὤι"), + (0x1FA5, "M", "ὥι"), + (0x1FA6, "M", "ὦι"), + (0x1FA7, "M", "ὧι"), + (0x1FA8, "M", "ὠι"), + (0x1FA9, "M", "ὡι"), + (0x1FAA, "M", "ὢι"), + (0x1FAB, "M", "ὣι"), + (0x1FAC, "M", "ὤι"), + (0x1FAD, "M", "ὥι"), + (0x1FAE, "M", "ὦι"), + (0x1FAF, "M", "ὧι"), + (0x1FB0, "V"), + (0x1FB2, "M", "ὰι"), + (0x1FB3, "M", "αι"), + (0x1FB4, "M", "άι"), + (0x1FB5, "X"), + (0x1FB6, "V"), + (0x1FB7, "M", "ᾶι"), + (0x1FB8, "M", "ᾰ"), + (0x1FB9, "M", "ᾱ"), + (0x1FBA, "M", "ὰ"), + (0x1FBB, "M", "ά"), + (0x1FBC, "M", "αι"), + (0x1FBD, "3", " ̓"), + (0x1FBE, "M", "ι"), + (0x1FBF, "3", " ̓"), + (0x1FC0, "3", " ͂"), + (0x1FC1, "3", " ̈͂"), + (0x1FC2, "M", "ὴι"), + (0x1FC3, "M", "ηι"), + (0x1FC4, "M", "ήι"), + (0x1FC5, "X"), + (0x1FC6, "V"), + (0x1FC7, "M", "ῆι"), + (0x1FC8, "M", "ὲ"), + (0x1FC9, "M", "έ"), + (0x1FCA, "M", "ὴ"), + (0x1FCB, "M", "ή"), + (0x1FCC, "M", "ηι"), + (0x1FCD, "3", " ̓̀"), + (0x1FCE, "3", " ̓́"), + (0x1FCF, "3", " ̓͂"), + (0x1FD0, "V"), + (0x1FD3, "M", "ΐ"), + (0x1FD4, "X"), + (0x1FD6, "V"), + (0x1FD8, "M", "ῐ"), + (0x1FD9, "M", "ῑ"), + (0x1FDA, "M", "ὶ"), + (0x1FDB, "M", "ί"), + (0x1FDC, "X"), + (0x1FDD, "3", " ̔̀"), + (0x1FDE, "3", " ̔́"), + (0x1FDF, "3", " ̔͂"), + (0x1FE0, "V"), + (0x1FE3, "M", "ΰ"), + (0x1FE4, "V"), + (0x1FE8, "M", "ῠ"), + (0x1FE9, "M", "ῡ"), + (0x1FEA, "M", "ὺ"), + (0x1FEB, "M", "ύ"), + (0x1FEC, "M", "ῥ"), + (0x1FED, "3", " ̈̀"), + (0x1FEE, "3", " ̈́"), + (0x1FEF, "3", "`"), + (0x1FF0, "X"), + (0x1FF2, "M", "ὼι"), + (0x1FF3, "M", "ωι"), + (0x1FF4, "M", "ώι"), + (0x1FF5, "X"), + (0x1FF6, "V"), + ] + + +def _seg_21() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1FF7, "M", "ῶι"), + (0x1FF8, "M", "ὸ"), + (0x1FF9, "M", "ό"), + (0x1FFA, "M", "ὼ"), + (0x1FFB, "M", "ώ"), + (0x1FFC, "M", "ωι"), + (0x1FFD, "3", " ́"), + (0x1FFE, "3", " ̔"), + (0x1FFF, "X"), + (0x2000, "3", " "), + (0x200B, "I"), + (0x200C, "D", ""), + (0x200E, "X"), + (0x2010, "V"), + (0x2011, "M", "‐"), + (0x2012, "V"), + (0x2017, "3", " ̳"), + (0x2018, "V"), + (0x2024, "X"), + (0x2027, "V"), + (0x2028, "X"), + (0x202F, "3", " "), + (0x2030, "V"), + (0x2033, "M", "′′"), + (0x2034, "M", "′′′"), + (0x2035, "V"), + (0x2036, "M", "‵‵"), + (0x2037, "M", "‵‵‵"), + (0x2038, "V"), + (0x203C, "3", "!!"), + (0x203D, "V"), + (0x203E, "3", " ̅"), + (0x203F, "V"), + (0x2047, "3", "??"), + (0x2048, "3", "?!"), + (0x2049, "3", "!?"), + (0x204A, "V"), + (0x2057, "M", "′′′′"), + (0x2058, "V"), + (0x205F, "3", " "), + (0x2060, "I"), + (0x2061, "X"), + (0x2064, "I"), + (0x2065, "X"), + (0x2070, "M", "0"), + (0x2071, "M", "i"), + (0x2072, "X"), + (0x2074, "M", "4"), + (0x2075, "M", "5"), + (0x2076, "M", "6"), + (0x2077, "M", "7"), + (0x2078, "M", "8"), + (0x2079, "M", "9"), + (0x207A, "3", "+"), + (0x207B, "M", "−"), + (0x207C, "3", "="), + (0x207D, "3", "("), + (0x207E, "3", ")"), + (0x207F, "M", "n"), + (0x2080, "M", "0"), + (0x2081, "M", "1"), + (0x2082, "M", "2"), + (0x2083, "M", "3"), + (0x2084, "M", "4"), + (0x2085, "M", "5"), + (0x2086, "M", "6"), + (0x2087, "M", "7"), + (0x2088, "M", "8"), + (0x2089, "M", "9"), + (0x208A, "3", "+"), + (0x208B, "M", "−"), + (0x208C, "3", "="), + (0x208D, "3", "("), + (0x208E, "3", ")"), + (0x208F, "X"), + (0x2090, "M", "a"), + (0x2091, "M", "e"), + (0x2092, "M", "o"), + (0x2093, "M", "x"), + (0x2094, "M", "ə"), + (0x2095, "M", "h"), + (0x2096, "M", "k"), + (0x2097, "M", "l"), + (0x2098, "M", "m"), + (0x2099, "M", "n"), + (0x209A, "M", "p"), + (0x209B, "M", "s"), + (0x209C, "M", "t"), + (0x209D, "X"), + (0x20A0, "V"), + (0x20A8, "M", "rs"), + (0x20A9, "V"), + (0x20C1, "X"), + (0x20D0, "V"), + (0x20F1, "X"), + (0x2100, "3", "a/c"), + (0x2101, "3", "a/s"), + (0x2102, "M", "c"), + (0x2103, "M", "°c"), + (0x2104, "V"), + ] + + +def _seg_22() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x2105, "3", "c/o"), + (0x2106, "3", "c/u"), + (0x2107, "M", "ɛ"), + (0x2108, "V"), + (0x2109, "M", "°f"), + (0x210A, "M", "g"), + (0x210B, "M", "h"), + (0x210F, "M", "ħ"), + (0x2110, "M", "i"), + (0x2112, "M", "l"), + (0x2114, "V"), + (0x2115, "M", "n"), + (0x2116, "M", "no"), + (0x2117, "V"), + (0x2119, "M", "p"), + (0x211A, "M", "q"), + (0x211B, "M", "r"), + (0x211E, "V"), + (0x2120, "M", "sm"), + (0x2121, "M", "tel"), + (0x2122, "M", "tm"), + (0x2123, "V"), + (0x2124, "M", "z"), + (0x2125, "V"), + (0x2126, "M", "ω"), + (0x2127, "V"), + (0x2128, "M", "z"), + (0x2129, "V"), + (0x212A, "M", "k"), + (0x212B, "M", "å"), + (0x212C, "M", "b"), + (0x212D, "M", "c"), + (0x212E, "V"), + (0x212F, "M", "e"), + (0x2131, "M", "f"), + (0x2132, "X"), + (0x2133, "M", "m"), + (0x2134, "M", "o"), + (0x2135, "M", "א"), + (0x2136, "M", "ב"), + (0x2137, "M", "ג"), + (0x2138, "M", "ד"), + (0x2139, "M", "i"), + (0x213A, "V"), + (0x213B, "M", "fax"), + (0x213C, "M", "π"), + (0x213D, "M", "γ"), + (0x213F, "M", "π"), + (0x2140, "M", "∑"), + (0x2141, "V"), + (0x2145, "M", "d"), + (0x2147, "M", "e"), + (0x2148, "M", "i"), + (0x2149, "M", "j"), + (0x214A, "V"), + (0x2150, "M", "1⁄7"), + (0x2151, "M", "1⁄9"), + (0x2152, "M", "1⁄10"), + (0x2153, "M", "1⁄3"), + (0x2154, "M", "2⁄3"), + (0x2155, "M", "1⁄5"), + (0x2156, "M", "2⁄5"), + (0x2157, "M", "3⁄5"), + (0x2158, "M", "4⁄5"), + (0x2159, "M", "1⁄6"), + (0x215A, "M", "5⁄6"), + (0x215B, "M", "1⁄8"), + (0x215C, "M", "3⁄8"), + (0x215D, "M", "5⁄8"), + (0x215E, "M", "7⁄8"), + (0x215F, "M", "1⁄"), + (0x2160, "M", "i"), + (0x2161, "M", "ii"), + (0x2162, "M", "iii"), + (0x2163, "M", "iv"), + (0x2164, "M", "v"), + (0x2165, "M", "vi"), + (0x2166, "M", "vii"), + (0x2167, "M", "viii"), + (0x2168, "M", "ix"), + (0x2169, "M", "x"), + (0x216A, "M", "xi"), + (0x216B, "M", "xii"), + (0x216C, "M", "l"), + (0x216D, "M", "c"), + (0x216E, "M", "d"), + (0x216F, "M", "m"), + (0x2170, "M", "i"), + (0x2171, "M", "ii"), + (0x2172, "M", "iii"), + (0x2173, "M", "iv"), + (0x2174, "M", "v"), + (0x2175, "M", "vi"), + (0x2176, "M", "vii"), + (0x2177, "M", "viii"), + (0x2178, "M", "ix"), + (0x2179, "M", "x"), + (0x217A, "M", "xi"), + (0x217B, "M", "xii"), + (0x217C, "M", "l"), + ] + + +def _seg_23() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x217D, "M", "c"), + (0x217E, "M", "d"), + (0x217F, "M", "m"), + (0x2180, "V"), + (0x2183, "X"), + (0x2184, "V"), + (0x2189, "M", "0⁄3"), + (0x218A, "V"), + (0x218C, "X"), + (0x2190, "V"), + (0x222C, "M", "∫∫"), + (0x222D, "M", "∫∫∫"), + (0x222E, "V"), + (0x222F, "M", "∮∮"), + (0x2230, "M", "∮∮∮"), + (0x2231, "V"), + (0x2329, "M", "〈"), + (0x232A, "M", "〉"), + (0x232B, "V"), + (0x2427, "X"), + (0x2440, "V"), + (0x244B, "X"), + (0x2460, "M", "1"), + (0x2461, "M", "2"), + (0x2462, "M", "3"), + (0x2463, "M", "4"), + (0x2464, "M", "5"), + (0x2465, "M", "6"), + (0x2466, "M", "7"), + (0x2467, "M", "8"), + (0x2468, "M", "9"), + (0x2469, "M", "10"), + (0x246A, "M", "11"), + (0x246B, "M", "12"), + (0x246C, "M", "13"), + (0x246D, "M", "14"), + (0x246E, "M", "15"), + (0x246F, "M", "16"), + (0x2470, "M", "17"), + (0x2471, "M", "18"), + (0x2472, "M", "19"), + (0x2473, "M", "20"), + (0x2474, "3", "(1)"), + (0x2475, "3", "(2)"), + (0x2476, "3", "(3)"), + (0x2477, "3", "(4)"), + (0x2478, "3", "(5)"), + (0x2479, "3", "(6)"), + (0x247A, "3", "(7)"), + (0x247B, "3", "(8)"), + (0x247C, "3", "(9)"), + (0x247D, "3", "(10)"), + (0x247E, "3", "(11)"), + (0x247F, "3", "(12)"), + (0x2480, "3", "(13)"), + (0x2481, "3", "(14)"), + (0x2482, "3", "(15)"), + (0x2483, "3", "(16)"), + (0x2484, "3", "(17)"), + (0x2485, "3", "(18)"), + (0x2486, "3", "(19)"), + (0x2487, "3", "(20)"), + (0x2488, "X"), + (0x249C, "3", "(a)"), + (0x249D, "3", "(b)"), + (0x249E, "3", "(c)"), + (0x249F, "3", "(d)"), + (0x24A0, "3", "(e)"), + (0x24A1, "3", "(f)"), + (0x24A2, "3", "(g)"), + (0x24A3, "3", "(h)"), + (0x24A4, "3", "(i)"), + (0x24A5, "3", "(j)"), + (0x24A6, "3", "(k)"), + (0x24A7, "3", "(l)"), + (0x24A8, "3", "(m)"), + (0x24A9, "3", "(n)"), + (0x24AA, "3", "(o)"), + (0x24AB, "3", "(p)"), + (0x24AC, "3", "(q)"), + (0x24AD, "3", "(r)"), + (0x24AE, "3", "(s)"), + (0x24AF, "3", "(t)"), + (0x24B0, "3", "(u)"), + (0x24B1, "3", "(v)"), + (0x24B2, "3", "(w)"), + (0x24B3, "3", "(x)"), + (0x24B4, "3", "(y)"), + (0x24B5, "3", "(z)"), + (0x24B6, "M", "a"), + (0x24B7, "M", "b"), + (0x24B8, "M", "c"), + (0x24B9, "M", "d"), + (0x24BA, "M", "e"), + (0x24BB, "M", "f"), + (0x24BC, "M", "g"), + (0x24BD, "M", "h"), + (0x24BE, "M", "i"), + (0x24BF, "M", "j"), + (0x24C0, "M", "k"), + ] + + +def _seg_24() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x24C1, "M", "l"), + (0x24C2, "M", "m"), + (0x24C3, "M", "n"), + (0x24C4, "M", "o"), + (0x24C5, "M", "p"), + (0x24C6, "M", "q"), + (0x24C7, "M", "r"), + (0x24C8, "M", "s"), + (0x24C9, "M", "t"), + (0x24CA, "M", "u"), + (0x24CB, "M", "v"), + (0x24CC, "M", "w"), + (0x24CD, "M", "x"), + (0x24CE, "M", "y"), + (0x24CF, "M", "z"), + (0x24D0, "M", "a"), + (0x24D1, "M", "b"), + (0x24D2, "M", "c"), + (0x24D3, "M", "d"), + (0x24D4, "M", "e"), + (0x24D5, "M", "f"), + (0x24D6, "M", "g"), + (0x24D7, "M", "h"), + (0x24D8, "M", "i"), + (0x24D9, "M", "j"), + (0x24DA, "M", "k"), + (0x24DB, "M", "l"), + (0x24DC, "M", "m"), + (0x24DD, "M", "n"), + (0x24DE, "M", "o"), + (0x24DF, "M", "p"), + (0x24E0, "M", "q"), + (0x24E1, "M", "r"), + (0x24E2, "M", "s"), + (0x24E3, "M", "t"), + (0x24E4, "M", "u"), + (0x24E5, "M", "v"), + (0x24E6, "M", "w"), + (0x24E7, "M", "x"), + (0x24E8, "M", "y"), + (0x24E9, "M", "z"), + (0x24EA, "M", "0"), + (0x24EB, "V"), + (0x2A0C, "M", "∫∫∫∫"), + (0x2A0D, "V"), + (0x2A74, "3", "::="), + (0x2A75, "3", "=="), + (0x2A76, "3", "==="), + (0x2A77, "V"), + (0x2ADC, "M", "⫝̸"), + (0x2ADD, "V"), + (0x2B74, "X"), + (0x2B76, "V"), + (0x2B96, "X"), + (0x2B97, "V"), + (0x2C00, "M", "ⰰ"), + (0x2C01, "M", "ⰱ"), + (0x2C02, "M", "ⰲ"), + (0x2C03, "M", "ⰳ"), + (0x2C04, "M", "ⰴ"), + (0x2C05, "M", "ⰵ"), + (0x2C06, "M", "ⰶ"), + (0x2C07, "M", "ⰷ"), + (0x2C08, "M", "ⰸ"), + (0x2C09, "M", "ⰹ"), + (0x2C0A, "M", "ⰺ"), + (0x2C0B, "M", "ⰻ"), + (0x2C0C, "M", "ⰼ"), + (0x2C0D, "M", "ⰽ"), + (0x2C0E, "M", "ⰾ"), + (0x2C0F, "M", "ⰿ"), + (0x2C10, "M", "ⱀ"), + (0x2C11, "M", "ⱁ"), + (0x2C12, "M", "ⱂ"), + (0x2C13, "M", "ⱃ"), + (0x2C14, "M", "ⱄ"), + (0x2C15, "M", "ⱅ"), + (0x2C16, "M", "ⱆ"), + (0x2C17, "M", "ⱇ"), + (0x2C18, "M", "ⱈ"), + (0x2C19, "M", "ⱉ"), + (0x2C1A, "M", "ⱊ"), + (0x2C1B, "M", "ⱋ"), + (0x2C1C, "M", "ⱌ"), + (0x2C1D, "M", "ⱍ"), + (0x2C1E, "M", "ⱎ"), + (0x2C1F, "M", "ⱏ"), + (0x2C20, "M", "ⱐ"), + (0x2C21, "M", "ⱑ"), + (0x2C22, "M", "ⱒ"), + (0x2C23, "M", "ⱓ"), + (0x2C24, "M", "ⱔ"), + (0x2C25, "M", "ⱕ"), + (0x2C26, "M", "ⱖ"), + (0x2C27, "M", "ⱗ"), + (0x2C28, "M", "ⱘ"), + (0x2C29, "M", "ⱙ"), + (0x2C2A, "M", "ⱚ"), + (0x2C2B, "M", "ⱛ"), + (0x2C2C, "M", "ⱜ"), + ] + + +def _seg_25() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x2C2D, "M", "ⱝ"), + (0x2C2E, "M", "ⱞ"), + (0x2C2F, "M", "ⱟ"), + (0x2C30, "V"), + (0x2C60, "M", "ⱡ"), + (0x2C61, "V"), + (0x2C62, "M", "ɫ"), + (0x2C63, "M", "ᵽ"), + (0x2C64, "M", "ɽ"), + (0x2C65, "V"), + (0x2C67, "M", "ⱨ"), + (0x2C68, "V"), + (0x2C69, "M", "ⱪ"), + (0x2C6A, "V"), + (0x2C6B, "M", "ⱬ"), + (0x2C6C, "V"), + (0x2C6D, "M", "ɑ"), + (0x2C6E, "M", "ɱ"), + (0x2C6F, "M", "ɐ"), + (0x2C70, "M", "ɒ"), + (0x2C71, "V"), + (0x2C72, "M", "ⱳ"), + (0x2C73, "V"), + (0x2C75, "M", "ⱶ"), + (0x2C76, "V"), + (0x2C7C, "M", "j"), + (0x2C7D, "M", "v"), + (0x2C7E, "M", "ȿ"), + (0x2C7F, "M", "ɀ"), + (0x2C80, "M", "ⲁ"), + (0x2C81, "V"), + (0x2C82, "M", "ⲃ"), + (0x2C83, "V"), + (0x2C84, "M", "ⲅ"), + (0x2C85, "V"), + (0x2C86, "M", "ⲇ"), + (0x2C87, "V"), + (0x2C88, "M", "ⲉ"), + (0x2C89, "V"), + (0x2C8A, "M", "ⲋ"), + (0x2C8B, "V"), + (0x2C8C, "M", "ⲍ"), + (0x2C8D, "V"), + (0x2C8E, "M", "ⲏ"), + (0x2C8F, "V"), + (0x2C90, "M", "ⲑ"), + (0x2C91, "V"), + (0x2C92, "M", "ⲓ"), + (0x2C93, "V"), + (0x2C94, "M", "ⲕ"), + (0x2C95, "V"), + (0x2C96, "M", "ⲗ"), + (0x2C97, "V"), + (0x2C98, "M", "ⲙ"), + (0x2C99, "V"), + (0x2C9A, "M", "ⲛ"), + (0x2C9B, "V"), + (0x2C9C, "M", "ⲝ"), + (0x2C9D, "V"), + (0x2C9E, "M", "ⲟ"), + (0x2C9F, "V"), + (0x2CA0, "M", "ⲡ"), + (0x2CA1, "V"), + (0x2CA2, "M", "ⲣ"), + (0x2CA3, "V"), + (0x2CA4, "M", "ⲥ"), + (0x2CA5, "V"), + (0x2CA6, "M", "ⲧ"), + (0x2CA7, "V"), + (0x2CA8, "M", "ⲩ"), + (0x2CA9, "V"), + (0x2CAA, "M", "ⲫ"), + (0x2CAB, "V"), + (0x2CAC, "M", "ⲭ"), + (0x2CAD, "V"), + (0x2CAE, "M", "ⲯ"), + (0x2CAF, "V"), + (0x2CB0, "M", "ⲱ"), + (0x2CB1, "V"), + (0x2CB2, "M", "ⲳ"), + (0x2CB3, "V"), + (0x2CB4, "M", "ⲵ"), + (0x2CB5, "V"), + (0x2CB6, "M", "ⲷ"), + (0x2CB7, "V"), + (0x2CB8, "M", "ⲹ"), + (0x2CB9, "V"), + (0x2CBA, "M", "ⲻ"), + (0x2CBB, "V"), + (0x2CBC, "M", "ⲽ"), + (0x2CBD, "V"), + (0x2CBE, "M", "ⲿ"), + (0x2CBF, "V"), + (0x2CC0, "M", "ⳁ"), + (0x2CC1, "V"), + (0x2CC2, "M", "ⳃ"), + (0x2CC3, "V"), + (0x2CC4, "M", "ⳅ"), + (0x2CC5, "V"), + (0x2CC6, "M", "ⳇ"), + ] + + +def _seg_26() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x2CC7, "V"), + (0x2CC8, "M", "ⳉ"), + (0x2CC9, "V"), + (0x2CCA, "M", "ⳋ"), + (0x2CCB, "V"), + (0x2CCC, "M", "ⳍ"), + (0x2CCD, "V"), + (0x2CCE, "M", "ⳏ"), + (0x2CCF, "V"), + (0x2CD0, "M", "ⳑ"), + (0x2CD1, "V"), + (0x2CD2, "M", "ⳓ"), + (0x2CD3, "V"), + (0x2CD4, "M", "ⳕ"), + (0x2CD5, "V"), + (0x2CD6, "M", "ⳗ"), + (0x2CD7, "V"), + (0x2CD8, "M", "ⳙ"), + (0x2CD9, "V"), + (0x2CDA, "M", "ⳛ"), + (0x2CDB, "V"), + (0x2CDC, "M", "ⳝ"), + (0x2CDD, "V"), + (0x2CDE, "M", "ⳟ"), + (0x2CDF, "V"), + (0x2CE0, "M", "ⳡ"), + (0x2CE1, "V"), + (0x2CE2, "M", "ⳣ"), + (0x2CE3, "V"), + (0x2CEB, "M", "ⳬ"), + (0x2CEC, "V"), + (0x2CED, "M", "ⳮ"), + (0x2CEE, "V"), + (0x2CF2, "M", "ⳳ"), + (0x2CF3, "V"), + (0x2CF4, "X"), + (0x2CF9, "V"), + (0x2D26, "X"), + (0x2D27, "V"), + (0x2D28, "X"), + (0x2D2D, "V"), + (0x2D2E, "X"), + (0x2D30, "V"), + (0x2D68, "X"), + (0x2D6F, "M", "ⵡ"), + (0x2D70, "V"), + (0x2D71, "X"), + (0x2D7F, "V"), + (0x2D97, "X"), + (0x2DA0, "V"), + (0x2DA7, "X"), + (0x2DA8, "V"), + (0x2DAF, "X"), + (0x2DB0, "V"), + (0x2DB7, "X"), + (0x2DB8, "V"), + (0x2DBF, "X"), + (0x2DC0, "V"), + (0x2DC7, "X"), + (0x2DC8, "V"), + (0x2DCF, "X"), + (0x2DD0, "V"), + (0x2DD7, "X"), + (0x2DD8, "V"), + (0x2DDF, "X"), + (0x2DE0, "V"), + (0x2E5E, "X"), + (0x2E80, "V"), + (0x2E9A, "X"), + (0x2E9B, "V"), + (0x2E9F, "M", "母"), + (0x2EA0, "V"), + (0x2EF3, "M", "龟"), + (0x2EF4, "X"), + (0x2F00, "M", "一"), + (0x2F01, "M", "丨"), + (0x2F02, "M", "丶"), + (0x2F03, "M", "丿"), + (0x2F04, "M", "乙"), + (0x2F05, "M", "亅"), + (0x2F06, "M", "二"), + (0x2F07, "M", "亠"), + (0x2F08, "M", "人"), + (0x2F09, "M", "儿"), + (0x2F0A, "M", "入"), + (0x2F0B, "M", "八"), + (0x2F0C, "M", "冂"), + (0x2F0D, "M", "冖"), + (0x2F0E, "M", "冫"), + (0x2F0F, "M", "几"), + (0x2F10, "M", "凵"), + (0x2F11, "M", "刀"), + (0x2F12, "M", "力"), + (0x2F13, "M", "勹"), + (0x2F14, "M", "匕"), + (0x2F15, "M", "匚"), + (0x2F16, "M", "匸"), + (0x2F17, "M", "十"), + (0x2F18, "M", "卜"), + (0x2F19, "M", "卩"), + ] + + +def _seg_27() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x2F1A, "M", "厂"), + (0x2F1B, "M", "厶"), + (0x2F1C, "M", "又"), + (0x2F1D, "M", "口"), + (0x2F1E, "M", "囗"), + (0x2F1F, "M", "土"), + (0x2F20, "M", "士"), + (0x2F21, "M", "夂"), + (0x2F22, "M", "夊"), + (0x2F23, "M", "夕"), + (0x2F24, "M", "大"), + (0x2F25, "M", "女"), + (0x2F26, "M", "子"), + (0x2F27, "M", "宀"), + (0x2F28, "M", "寸"), + (0x2F29, "M", "小"), + (0x2F2A, "M", "尢"), + (0x2F2B, "M", "尸"), + (0x2F2C, "M", "屮"), + (0x2F2D, "M", "山"), + (0x2F2E, "M", "巛"), + (0x2F2F, "M", "工"), + (0x2F30, "M", "己"), + (0x2F31, "M", "巾"), + (0x2F32, "M", "干"), + (0x2F33, "M", "幺"), + (0x2F34, "M", "广"), + (0x2F35, "M", "廴"), + (0x2F36, "M", "廾"), + (0x2F37, "M", "弋"), + (0x2F38, "M", "弓"), + (0x2F39, "M", "彐"), + (0x2F3A, "M", "彡"), + (0x2F3B, "M", "彳"), + (0x2F3C, "M", "心"), + (0x2F3D, "M", "戈"), + (0x2F3E, "M", "戶"), + (0x2F3F, "M", "手"), + (0x2F40, "M", "支"), + (0x2F41, "M", "攴"), + (0x2F42, "M", "文"), + (0x2F43, "M", "斗"), + (0x2F44, "M", "斤"), + (0x2F45, "M", "方"), + (0x2F46, "M", "无"), + (0x2F47, "M", "日"), + (0x2F48, "M", "曰"), + (0x2F49, "M", "月"), + (0x2F4A, "M", "木"), + (0x2F4B, "M", "欠"), + (0x2F4C, "M", "止"), + (0x2F4D, "M", "歹"), + (0x2F4E, "M", "殳"), + (0x2F4F, "M", "毋"), + (0x2F50, "M", "比"), + (0x2F51, "M", "毛"), + (0x2F52, "M", "氏"), + (0x2F53, "M", "气"), + (0x2F54, "M", "水"), + (0x2F55, "M", "火"), + (0x2F56, "M", "爪"), + (0x2F57, "M", "父"), + (0x2F58, "M", "爻"), + (0x2F59, "M", "爿"), + (0x2F5A, "M", "片"), + (0x2F5B, "M", "牙"), + (0x2F5C, "M", "牛"), + (0x2F5D, "M", "犬"), + (0x2F5E, "M", "玄"), + (0x2F5F, "M", "玉"), + (0x2F60, "M", "瓜"), + (0x2F61, "M", "瓦"), + (0x2F62, "M", "甘"), + (0x2F63, "M", "生"), + (0x2F64, "M", "用"), + (0x2F65, "M", "田"), + (0x2F66, "M", "疋"), + (0x2F67, "M", "疒"), + (0x2F68, "M", "癶"), + (0x2F69, "M", "白"), + (0x2F6A, "M", "皮"), + (0x2F6B, "M", "皿"), + (0x2F6C, "M", "目"), + (0x2F6D, "M", "矛"), + (0x2F6E, "M", "矢"), + (0x2F6F, "M", "石"), + (0x2F70, "M", "示"), + (0x2F71, "M", "禸"), + (0x2F72, "M", "禾"), + (0x2F73, "M", "穴"), + (0x2F74, "M", "立"), + (0x2F75, "M", "竹"), + (0x2F76, "M", "米"), + (0x2F77, "M", "糸"), + (0x2F78, "M", "缶"), + (0x2F79, "M", "网"), + (0x2F7A, "M", "羊"), + (0x2F7B, "M", "羽"), + (0x2F7C, "M", "老"), + (0x2F7D, "M", "而"), + ] + + +def _seg_28() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x2F7E, "M", "耒"), + (0x2F7F, "M", "耳"), + (0x2F80, "M", "聿"), + (0x2F81, "M", "肉"), + (0x2F82, "M", "臣"), + (0x2F83, "M", "自"), + (0x2F84, "M", "至"), + (0x2F85, "M", "臼"), + (0x2F86, "M", "舌"), + (0x2F87, "M", "舛"), + (0x2F88, "M", "舟"), + (0x2F89, "M", "艮"), + (0x2F8A, "M", "色"), + (0x2F8B, "M", "艸"), + (0x2F8C, "M", "虍"), + (0x2F8D, "M", "虫"), + (0x2F8E, "M", "血"), + (0x2F8F, "M", "行"), + (0x2F90, "M", "衣"), + (0x2F91, "M", "襾"), + (0x2F92, "M", "見"), + (0x2F93, "M", "角"), + (0x2F94, "M", "言"), + (0x2F95, "M", "谷"), + (0x2F96, "M", "豆"), + (0x2F97, "M", "豕"), + (0x2F98, "M", "豸"), + (0x2F99, "M", "貝"), + (0x2F9A, "M", "赤"), + (0x2F9B, "M", "走"), + (0x2F9C, "M", "足"), + (0x2F9D, "M", "身"), + (0x2F9E, "M", "車"), + (0x2F9F, "M", "辛"), + (0x2FA0, "M", "辰"), + (0x2FA1, "M", "辵"), + (0x2FA2, "M", "邑"), + (0x2FA3, "M", "酉"), + (0x2FA4, "M", "釆"), + (0x2FA5, "M", "里"), + (0x2FA6, "M", "金"), + (0x2FA7, "M", "長"), + (0x2FA8, "M", "門"), + (0x2FA9, "M", "阜"), + (0x2FAA, "M", "隶"), + (0x2FAB, "M", "隹"), + (0x2FAC, "M", "雨"), + (0x2FAD, "M", "靑"), + (0x2FAE, "M", "非"), + (0x2FAF, "M", "面"), + (0x2FB0, "M", "革"), + (0x2FB1, "M", "韋"), + (0x2FB2, "M", "韭"), + (0x2FB3, "M", "音"), + (0x2FB4, "M", "頁"), + (0x2FB5, "M", "風"), + (0x2FB6, "M", "飛"), + (0x2FB7, "M", "食"), + (0x2FB8, "M", "首"), + (0x2FB9, "M", "香"), + (0x2FBA, "M", "馬"), + (0x2FBB, "M", "骨"), + (0x2FBC, "M", "高"), + (0x2FBD, "M", "髟"), + (0x2FBE, "M", "鬥"), + (0x2FBF, "M", "鬯"), + (0x2FC0, "M", "鬲"), + (0x2FC1, "M", "鬼"), + (0x2FC2, "M", "魚"), + (0x2FC3, "M", "鳥"), + (0x2FC4, "M", "鹵"), + (0x2FC5, "M", "鹿"), + (0x2FC6, "M", "麥"), + (0x2FC7, "M", "麻"), + (0x2FC8, "M", "黃"), + (0x2FC9, "M", "黍"), + (0x2FCA, "M", "黑"), + (0x2FCB, "M", "黹"), + (0x2FCC, "M", "黽"), + (0x2FCD, "M", "鼎"), + (0x2FCE, "M", "鼓"), + (0x2FCF, "M", "鼠"), + (0x2FD0, "M", "鼻"), + (0x2FD1, "M", "齊"), + (0x2FD2, "M", "齒"), + (0x2FD3, "M", "龍"), + (0x2FD4, "M", "龜"), + (0x2FD5, "M", "龠"), + (0x2FD6, "X"), + (0x3000, "3", " "), + (0x3001, "V"), + (0x3002, "M", "."), + (0x3003, "V"), + (0x3036, "M", "〒"), + (0x3037, "V"), + (0x3038, "M", "十"), + (0x3039, "M", "卄"), + (0x303A, "M", "卅"), + (0x303B, "V"), + (0x3040, "X"), + ] + + +def _seg_29() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x3041, "V"), + (0x3097, "X"), + (0x3099, "V"), + (0x309B, "3", " ゙"), + (0x309C, "3", " ゚"), + (0x309D, "V"), + (0x309F, "M", "より"), + (0x30A0, "V"), + (0x30FF, "M", "コト"), + (0x3100, "X"), + (0x3105, "V"), + (0x3130, "X"), + (0x3131, "M", "ᄀ"), + (0x3132, "M", "ᄁ"), + (0x3133, "M", "ᆪ"), + (0x3134, "M", "ᄂ"), + (0x3135, "M", "ᆬ"), + (0x3136, "M", "ᆭ"), + (0x3137, "M", "ᄃ"), + (0x3138, "M", "ᄄ"), + (0x3139, "M", "ᄅ"), + (0x313A, "M", "ᆰ"), + (0x313B, "M", "ᆱ"), + (0x313C, "M", "ᆲ"), + (0x313D, "M", "ᆳ"), + (0x313E, "M", "ᆴ"), + (0x313F, "M", "ᆵ"), + (0x3140, "M", "ᄚ"), + (0x3141, "M", "ᄆ"), + (0x3142, "M", "ᄇ"), + (0x3143, "M", "ᄈ"), + (0x3144, "M", "ᄡ"), + (0x3145, "M", "ᄉ"), + (0x3146, "M", "ᄊ"), + (0x3147, "M", "ᄋ"), + (0x3148, "M", "ᄌ"), + (0x3149, "M", "ᄍ"), + (0x314A, "M", "ᄎ"), + (0x314B, "M", "ᄏ"), + (0x314C, "M", "ᄐ"), + (0x314D, "M", "ᄑ"), + (0x314E, "M", "ᄒ"), + (0x314F, "M", "ᅡ"), + (0x3150, "M", "ᅢ"), + (0x3151, "M", "ᅣ"), + (0x3152, "M", "ᅤ"), + (0x3153, "M", "ᅥ"), + (0x3154, "M", "ᅦ"), + (0x3155, "M", "ᅧ"), + (0x3156, "M", "ᅨ"), + (0x3157, "M", "ᅩ"), + (0x3158, "M", "ᅪ"), + (0x3159, "M", "ᅫ"), + (0x315A, "M", "ᅬ"), + (0x315B, "M", "ᅭ"), + (0x315C, "M", "ᅮ"), + (0x315D, "M", "ᅯ"), + (0x315E, "M", "ᅰ"), + (0x315F, "M", "ᅱ"), + (0x3160, "M", "ᅲ"), + (0x3161, "M", "ᅳ"), + (0x3162, "M", "ᅴ"), + (0x3163, "M", "ᅵ"), + (0x3164, "X"), + (0x3165, "M", "ᄔ"), + (0x3166, "M", "ᄕ"), + (0x3167, "M", "ᇇ"), + (0x3168, "M", "ᇈ"), + (0x3169, "M", "ᇌ"), + (0x316A, "M", "ᇎ"), + (0x316B, "M", "ᇓ"), + (0x316C, "M", "ᇗ"), + (0x316D, "M", "ᇙ"), + (0x316E, "M", "ᄜ"), + (0x316F, "M", "ᇝ"), + (0x3170, "M", "ᇟ"), + (0x3171, "M", "ᄝ"), + (0x3172, "M", "ᄞ"), + (0x3173, "M", "ᄠ"), + (0x3174, "M", "ᄢ"), + (0x3175, "M", "ᄣ"), + (0x3176, "M", "ᄧ"), + (0x3177, "M", "ᄩ"), + (0x3178, "M", "ᄫ"), + (0x3179, "M", "ᄬ"), + (0x317A, "M", "ᄭ"), + (0x317B, "M", "ᄮ"), + (0x317C, "M", "ᄯ"), + (0x317D, "M", "ᄲ"), + (0x317E, "M", "ᄶ"), + (0x317F, "M", "ᅀ"), + (0x3180, "M", "ᅇ"), + (0x3181, "M", "ᅌ"), + (0x3182, "M", "ᇱ"), + (0x3183, "M", "ᇲ"), + (0x3184, "M", "ᅗ"), + (0x3185, "M", "ᅘ"), + (0x3186, "M", "ᅙ"), + (0x3187, "M", "ᆄ"), + (0x3188, "M", "ᆅ"), + ] + + +def _seg_30() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x3189, "M", "ᆈ"), + (0x318A, "M", "ᆑ"), + (0x318B, "M", "ᆒ"), + (0x318C, "M", "ᆔ"), + (0x318D, "M", "ᆞ"), + (0x318E, "M", "ᆡ"), + (0x318F, "X"), + (0x3190, "V"), + (0x3192, "M", "一"), + (0x3193, "M", "二"), + (0x3194, "M", "三"), + (0x3195, "M", "四"), + (0x3196, "M", "上"), + (0x3197, "M", "中"), + (0x3198, "M", "下"), + (0x3199, "M", "甲"), + (0x319A, "M", "乙"), + (0x319B, "M", "丙"), + (0x319C, "M", "丁"), + (0x319D, "M", "天"), + (0x319E, "M", "地"), + (0x319F, "M", "人"), + (0x31A0, "V"), + (0x31E4, "X"), + (0x31F0, "V"), + (0x3200, "3", "(ᄀ)"), + (0x3201, "3", "(ᄂ)"), + (0x3202, "3", "(ᄃ)"), + (0x3203, "3", "(ᄅ)"), + (0x3204, "3", "(ᄆ)"), + (0x3205, "3", "(ᄇ)"), + (0x3206, "3", "(ᄉ)"), + (0x3207, "3", "(ᄋ)"), + (0x3208, "3", "(ᄌ)"), + (0x3209, "3", "(ᄎ)"), + (0x320A, "3", "(ᄏ)"), + (0x320B, "3", "(ᄐ)"), + (0x320C, "3", "(ᄑ)"), + (0x320D, "3", "(ᄒ)"), + (0x320E, "3", "(가)"), + (0x320F, "3", "(나)"), + (0x3210, "3", "(다)"), + (0x3211, "3", "(라)"), + (0x3212, "3", "(마)"), + (0x3213, "3", "(바)"), + (0x3214, "3", "(사)"), + (0x3215, "3", "(아)"), + (0x3216, "3", "(자)"), + (0x3217, "3", "(차)"), + (0x3218, "3", "(카)"), + (0x3219, "3", "(타)"), + (0x321A, "3", "(파)"), + (0x321B, "3", "(하)"), + (0x321C, "3", "(주)"), + (0x321D, "3", "(오전)"), + (0x321E, "3", "(오후)"), + (0x321F, "X"), + (0x3220, "3", "(一)"), + (0x3221, "3", "(二)"), + (0x3222, "3", "(三)"), + (0x3223, "3", "(四)"), + (0x3224, "3", "(五)"), + (0x3225, "3", "(六)"), + (0x3226, "3", "(七)"), + (0x3227, "3", "(八)"), + (0x3228, "3", "(九)"), + (0x3229, "3", "(十)"), + (0x322A, "3", "(月)"), + (0x322B, "3", "(火)"), + (0x322C, "3", "(水)"), + (0x322D, "3", "(木)"), + (0x322E, "3", "(金)"), + (0x322F, "3", "(土)"), + (0x3230, "3", "(日)"), + (0x3231, "3", "(株)"), + (0x3232, "3", "(有)"), + (0x3233, "3", "(社)"), + (0x3234, "3", "(名)"), + (0x3235, "3", "(特)"), + (0x3236, "3", "(財)"), + (0x3237, "3", "(祝)"), + (0x3238, "3", "(労)"), + (0x3239, "3", "(代)"), + (0x323A, "3", "(呼)"), + (0x323B, "3", "(学)"), + (0x323C, "3", "(監)"), + (0x323D, "3", "(企)"), + (0x323E, "3", "(資)"), + (0x323F, "3", "(協)"), + (0x3240, "3", "(祭)"), + (0x3241, "3", "(休)"), + (0x3242, "3", "(自)"), + (0x3243, "3", "(至)"), + (0x3244, "M", "問"), + (0x3245, "M", "幼"), + (0x3246, "M", "文"), + (0x3247, "M", "箏"), + (0x3248, "V"), + (0x3250, "M", "pte"), + (0x3251, "M", "21"), + ] + + +def _seg_31() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x3252, "M", "22"), + (0x3253, "M", "23"), + (0x3254, "M", "24"), + (0x3255, "M", "25"), + (0x3256, "M", "26"), + (0x3257, "M", "27"), + (0x3258, "M", "28"), + (0x3259, "M", "29"), + (0x325A, "M", "30"), + (0x325B, "M", "31"), + (0x325C, "M", "32"), + (0x325D, "M", "33"), + (0x325E, "M", "34"), + (0x325F, "M", "35"), + (0x3260, "M", "ᄀ"), + (0x3261, "M", "ᄂ"), + (0x3262, "M", "ᄃ"), + (0x3263, "M", "ᄅ"), + (0x3264, "M", "ᄆ"), + (0x3265, "M", "ᄇ"), + (0x3266, "M", "ᄉ"), + (0x3267, "M", "ᄋ"), + (0x3268, "M", "ᄌ"), + (0x3269, "M", "ᄎ"), + (0x326A, "M", "ᄏ"), + (0x326B, "M", "ᄐ"), + (0x326C, "M", "ᄑ"), + (0x326D, "M", "ᄒ"), + (0x326E, "M", "가"), + (0x326F, "M", "나"), + (0x3270, "M", "다"), + (0x3271, "M", "라"), + (0x3272, "M", "마"), + (0x3273, "M", "바"), + (0x3274, "M", "사"), + (0x3275, "M", "아"), + (0x3276, "M", "자"), + (0x3277, "M", "차"), + (0x3278, "M", "카"), + (0x3279, "M", "타"), + (0x327A, "M", "파"), + (0x327B, "M", "하"), + (0x327C, "M", "참고"), + (0x327D, "M", "주의"), + (0x327E, "M", "우"), + (0x327F, "V"), + (0x3280, "M", "一"), + (0x3281, "M", "二"), + (0x3282, "M", "三"), + (0x3283, "M", "四"), + (0x3284, "M", "五"), + (0x3285, "M", "六"), + (0x3286, "M", "七"), + (0x3287, "M", "八"), + (0x3288, "M", "九"), + (0x3289, "M", "十"), + (0x328A, "M", "月"), + (0x328B, "M", "火"), + (0x328C, "M", "水"), + (0x328D, "M", "木"), + (0x328E, "M", "金"), + (0x328F, "M", "土"), + (0x3290, "M", "日"), + (0x3291, "M", "株"), + (0x3292, "M", "有"), + (0x3293, "M", "社"), + (0x3294, "M", "名"), + (0x3295, "M", "特"), + (0x3296, "M", "財"), + (0x3297, "M", "祝"), + (0x3298, "M", "労"), + (0x3299, "M", "秘"), + (0x329A, "M", "男"), + (0x329B, "M", "女"), + (0x329C, "M", "適"), + (0x329D, "M", "優"), + (0x329E, "M", "印"), + (0x329F, "M", "注"), + (0x32A0, "M", "項"), + (0x32A1, "M", "休"), + (0x32A2, "M", "写"), + (0x32A3, "M", "正"), + (0x32A4, "M", "上"), + (0x32A5, "M", "中"), + (0x32A6, "M", "下"), + (0x32A7, "M", "左"), + (0x32A8, "M", "右"), + (0x32A9, "M", "医"), + (0x32AA, "M", "宗"), + (0x32AB, "M", "学"), + (0x32AC, "M", "監"), + (0x32AD, "M", "企"), + (0x32AE, "M", "資"), + (0x32AF, "M", "協"), + (0x32B0, "M", "夜"), + (0x32B1, "M", "36"), + (0x32B2, "M", "37"), + (0x32B3, "M", "38"), + (0x32B4, "M", "39"), + (0x32B5, "M", "40"), + ] + + +def _seg_32() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x32B6, "M", "41"), + (0x32B7, "M", "42"), + (0x32B8, "M", "43"), + (0x32B9, "M", "44"), + (0x32BA, "M", "45"), + (0x32BB, "M", "46"), + (0x32BC, "M", "47"), + (0x32BD, "M", "48"), + (0x32BE, "M", "49"), + (0x32BF, "M", "50"), + (0x32C0, "M", "1月"), + (0x32C1, "M", "2月"), + (0x32C2, "M", "3月"), + (0x32C3, "M", "4月"), + (0x32C4, "M", "5月"), + (0x32C5, "M", "6月"), + (0x32C6, "M", "7月"), + (0x32C7, "M", "8月"), + (0x32C8, "M", "9月"), + (0x32C9, "M", "10月"), + (0x32CA, "M", "11月"), + (0x32CB, "M", "12月"), + (0x32CC, "M", "hg"), + (0x32CD, "M", "erg"), + (0x32CE, "M", "ev"), + (0x32CF, "M", "ltd"), + (0x32D0, "M", "ア"), + (0x32D1, "M", "イ"), + (0x32D2, "M", "ウ"), + (0x32D3, "M", "エ"), + (0x32D4, "M", "オ"), + (0x32D5, "M", "カ"), + (0x32D6, "M", "キ"), + (0x32D7, "M", "ク"), + (0x32D8, "M", "ケ"), + (0x32D9, "M", "コ"), + (0x32DA, "M", "サ"), + (0x32DB, "M", "シ"), + (0x32DC, "M", "ス"), + (0x32DD, "M", "セ"), + (0x32DE, "M", "ソ"), + (0x32DF, "M", "タ"), + (0x32E0, "M", "チ"), + (0x32E1, "M", "ツ"), + (0x32E2, "M", "テ"), + (0x32E3, "M", "ト"), + (0x32E4, "M", "ナ"), + (0x32E5, "M", "ニ"), + (0x32E6, "M", "ヌ"), + (0x32E7, "M", "ネ"), + (0x32E8, "M", "ノ"), + (0x32E9, "M", "ハ"), + (0x32EA, "M", "ヒ"), + (0x32EB, "M", "フ"), + (0x32EC, "M", "ヘ"), + (0x32ED, "M", "ホ"), + (0x32EE, "M", "マ"), + (0x32EF, "M", "ミ"), + (0x32F0, "M", "ム"), + (0x32F1, "M", "メ"), + (0x32F2, "M", "モ"), + (0x32F3, "M", "ヤ"), + (0x32F4, "M", "ユ"), + (0x32F5, "M", "ヨ"), + (0x32F6, "M", "ラ"), + (0x32F7, "M", "リ"), + (0x32F8, "M", "ル"), + (0x32F9, "M", "レ"), + (0x32FA, "M", "ロ"), + (0x32FB, "M", "ワ"), + (0x32FC, "M", "ヰ"), + (0x32FD, "M", "ヱ"), + (0x32FE, "M", "ヲ"), + (0x32FF, "M", "令和"), + (0x3300, "M", "アパート"), + (0x3301, "M", "アルファ"), + (0x3302, "M", "アンペア"), + (0x3303, "M", "アール"), + (0x3304, "M", "イニング"), + (0x3305, "M", "インチ"), + (0x3306, "M", "ウォン"), + (0x3307, "M", "エスクード"), + (0x3308, "M", "エーカー"), + (0x3309, "M", "オンス"), + (0x330A, "M", "オーム"), + (0x330B, "M", "カイリ"), + (0x330C, "M", "カラット"), + (0x330D, "M", "カロリー"), + (0x330E, "M", "ガロン"), + (0x330F, "M", "ガンマ"), + (0x3310, "M", "ギガ"), + (0x3311, "M", "ギニー"), + (0x3312, "M", "キュリー"), + (0x3313, "M", "ギルダー"), + (0x3314, "M", "キロ"), + (0x3315, "M", "キログラム"), + (0x3316, "M", "キロメートル"), + (0x3317, "M", "キロワット"), + (0x3318, "M", "グラム"), + (0x3319, "M", "グラムトン"), + ] + + +def _seg_33() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x331A, "M", "クルゼイロ"), + (0x331B, "M", "クローネ"), + (0x331C, "M", "ケース"), + (0x331D, "M", "コルナ"), + (0x331E, "M", "コーポ"), + (0x331F, "M", "サイクル"), + (0x3320, "M", "サンチーム"), + (0x3321, "M", "シリング"), + (0x3322, "M", "センチ"), + (0x3323, "M", "セント"), + (0x3324, "M", "ダース"), + (0x3325, "M", "デシ"), + (0x3326, "M", "ドル"), + (0x3327, "M", "トン"), + (0x3328, "M", "ナノ"), + (0x3329, "M", "ノット"), + (0x332A, "M", "ハイツ"), + (0x332B, "M", "パーセント"), + (0x332C, "M", "パーツ"), + (0x332D, "M", "バーレル"), + (0x332E, "M", "ピアストル"), + (0x332F, "M", "ピクル"), + (0x3330, "M", "ピコ"), + (0x3331, "M", "ビル"), + (0x3332, "M", "ファラッド"), + (0x3333, "M", "フィート"), + (0x3334, "M", "ブッシェル"), + (0x3335, "M", "フラン"), + (0x3336, "M", "ヘクタール"), + (0x3337, "M", "ペソ"), + (0x3338, "M", "ペニヒ"), + (0x3339, "M", "ヘルツ"), + (0x333A, "M", "ペンス"), + (0x333B, "M", "ページ"), + (0x333C, "M", "ベータ"), + (0x333D, "M", "ポイント"), + (0x333E, "M", "ボルト"), + (0x333F, "M", "ホン"), + (0x3340, "M", "ポンド"), + (0x3341, "M", "ホール"), + (0x3342, "M", "ホーン"), + (0x3343, "M", "マイクロ"), + (0x3344, "M", "マイル"), + (0x3345, "M", "マッハ"), + (0x3346, "M", "マルク"), + (0x3347, "M", "マンション"), + (0x3348, "M", "ミクロン"), + (0x3349, "M", "ミリ"), + (0x334A, "M", "ミリバール"), + (0x334B, "M", "メガ"), + (0x334C, "M", "メガトン"), + (0x334D, "M", "メートル"), + (0x334E, "M", "ヤード"), + (0x334F, "M", "ヤール"), + (0x3350, "M", "ユアン"), + (0x3351, "M", "リットル"), + (0x3352, "M", "リラ"), + (0x3353, "M", "ルピー"), + (0x3354, "M", "ルーブル"), + (0x3355, "M", "レム"), + (0x3356, "M", "レントゲン"), + (0x3357, "M", "ワット"), + (0x3358, "M", "0点"), + (0x3359, "M", "1点"), + (0x335A, "M", "2点"), + (0x335B, "M", "3点"), + (0x335C, "M", "4点"), + (0x335D, "M", "5点"), + (0x335E, "M", "6点"), + (0x335F, "M", "7点"), + (0x3360, "M", "8点"), + (0x3361, "M", "9点"), + (0x3362, "M", "10点"), + (0x3363, "M", "11点"), + (0x3364, "M", "12点"), + (0x3365, "M", "13点"), + (0x3366, "M", "14点"), + (0x3367, "M", "15点"), + (0x3368, "M", "16点"), + (0x3369, "M", "17点"), + (0x336A, "M", "18点"), + (0x336B, "M", "19点"), + (0x336C, "M", "20点"), + (0x336D, "M", "21点"), + (0x336E, "M", "22点"), + (0x336F, "M", "23点"), + (0x3370, "M", "24点"), + (0x3371, "M", "hpa"), + (0x3372, "M", "da"), + (0x3373, "M", "au"), + (0x3374, "M", "bar"), + (0x3375, "M", "ov"), + (0x3376, "M", "pc"), + (0x3377, "M", "dm"), + (0x3378, "M", "dm2"), + (0x3379, "M", "dm3"), + (0x337A, "M", "iu"), + (0x337B, "M", "平成"), + (0x337C, "M", "昭和"), + (0x337D, "M", "大正"), + ] + + +def _seg_34() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x337E, "M", "明治"), + (0x337F, "M", "株式会社"), + (0x3380, "M", "pa"), + (0x3381, "M", "na"), + (0x3382, "M", "μa"), + (0x3383, "M", "ma"), + (0x3384, "M", "ka"), + (0x3385, "M", "kb"), + (0x3386, "M", "mb"), + (0x3387, "M", "gb"), + (0x3388, "M", "cal"), + (0x3389, "M", "kcal"), + (0x338A, "M", "pf"), + (0x338B, "M", "nf"), + (0x338C, "M", "μf"), + (0x338D, "M", "μg"), + (0x338E, "M", "mg"), + (0x338F, "M", "kg"), + (0x3390, "M", "hz"), + (0x3391, "M", "khz"), + (0x3392, "M", "mhz"), + (0x3393, "M", "ghz"), + (0x3394, "M", "thz"), + (0x3395, "M", "μl"), + (0x3396, "M", "ml"), + (0x3397, "M", "dl"), + (0x3398, "M", "kl"), + (0x3399, "M", "fm"), + (0x339A, "M", "nm"), + (0x339B, "M", "μm"), + (0x339C, "M", "mm"), + (0x339D, "M", "cm"), + (0x339E, "M", "km"), + (0x339F, "M", "mm2"), + (0x33A0, "M", "cm2"), + (0x33A1, "M", "m2"), + (0x33A2, "M", "km2"), + (0x33A3, "M", "mm3"), + (0x33A4, "M", "cm3"), + (0x33A5, "M", "m3"), + (0x33A6, "M", "km3"), + (0x33A7, "M", "m∕s"), + (0x33A8, "M", "m∕s2"), + (0x33A9, "M", "pa"), + (0x33AA, "M", "kpa"), + (0x33AB, "M", "mpa"), + (0x33AC, "M", "gpa"), + (0x33AD, "M", "rad"), + (0x33AE, "M", "rad∕s"), + (0x33AF, "M", "rad∕s2"), + (0x33B0, "M", "ps"), + (0x33B1, "M", "ns"), + (0x33B2, "M", "μs"), + (0x33B3, "M", "ms"), + (0x33B4, "M", "pv"), + (0x33B5, "M", "nv"), + (0x33B6, "M", "μv"), + (0x33B7, "M", "mv"), + (0x33B8, "M", "kv"), + (0x33B9, "M", "mv"), + (0x33BA, "M", "pw"), + (0x33BB, "M", "nw"), + (0x33BC, "M", "μw"), + (0x33BD, "M", "mw"), + (0x33BE, "M", "kw"), + (0x33BF, "M", "mw"), + (0x33C0, "M", "kω"), + (0x33C1, "M", "mω"), + (0x33C2, "X"), + (0x33C3, "M", "bq"), + (0x33C4, "M", "cc"), + (0x33C5, "M", "cd"), + (0x33C6, "M", "c∕kg"), + (0x33C7, "X"), + (0x33C8, "M", "db"), + (0x33C9, "M", "gy"), + (0x33CA, "M", "ha"), + (0x33CB, "M", "hp"), + (0x33CC, "M", "in"), + (0x33CD, "M", "kk"), + (0x33CE, "M", "km"), + (0x33CF, "M", "kt"), + (0x33D0, "M", "lm"), + (0x33D1, "M", "ln"), + (0x33D2, "M", "log"), + (0x33D3, "M", "lx"), + (0x33D4, "M", "mb"), + (0x33D5, "M", "mil"), + (0x33D6, "M", "mol"), + (0x33D7, "M", "ph"), + (0x33D8, "X"), + (0x33D9, "M", "ppm"), + (0x33DA, "M", "pr"), + (0x33DB, "M", "sr"), + (0x33DC, "M", "sv"), + (0x33DD, "M", "wb"), + (0x33DE, "M", "v∕m"), + (0x33DF, "M", "a∕m"), + (0x33E0, "M", "1日"), + (0x33E1, "M", "2日"), + ] + + +def _seg_35() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x33E2, "M", "3日"), + (0x33E3, "M", "4日"), + (0x33E4, "M", "5日"), + (0x33E5, "M", "6日"), + (0x33E6, "M", "7日"), + (0x33E7, "M", "8日"), + (0x33E8, "M", "9日"), + (0x33E9, "M", "10日"), + (0x33EA, "M", "11日"), + (0x33EB, "M", "12日"), + (0x33EC, "M", "13日"), + (0x33ED, "M", "14日"), + (0x33EE, "M", "15日"), + (0x33EF, "M", "16日"), + (0x33F0, "M", "17日"), + (0x33F1, "M", "18日"), + (0x33F2, "M", "19日"), + (0x33F3, "M", "20日"), + (0x33F4, "M", "21日"), + (0x33F5, "M", "22日"), + (0x33F6, "M", "23日"), + (0x33F7, "M", "24日"), + (0x33F8, "M", "25日"), + (0x33F9, "M", "26日"), + (0x33FA, "M", "27日"), + (0x33FB, "M", "28日"), + (0x33FC, "M", "29日"), + (0x33FD, "M", "30日"), + (0x33FE, "M", "31日"), + (0x33FF, "M", "gal"), + (0x3400, "V"), + (0xA48D, "X"), + (0xA490, "V"), + (0xA4C7, "X"), + (0xA4D0, "V"), + (0xA62C, "X"), + (0xA640, "M", "ꙁ"), + (0xA641, "V"), + (0xA642, "M", "ꙃ"), + (0xA643, "V"), + (0xA644, "M", "ꙅ"), + (0xA645, "V"), + (0xA646, "M", "ꙇ"), + (0xA647, "V"), + (0xA648, "M", "ꙉ"), + (0xA649, "V"), + (0xA64A, "M", "ꙋ"), + (0xA64B, "V"), + (0xA64C, "M", "ꙍ"), + (0xA64D, "V"), + (0xA64E, "M", "ꙏ"), + (0xA64F, "V"), + (0xA650, "M", "ꙑ"), + (0xA651, "V"), + (0xA652, "M", "ꙓ"), + (0xA653, "V"), + (0xA654, "M", "ꙕ"), + (0xA655, "V"), + (0xA656, "M", "ꙗ"), + (0xA657, "V"), + (0xA658, "M", "ꙙ"), + (0xA659, "V"), + (0xA65A, "M", "ꙛ"), + (0xA65B, "V"), + (0xA65C, "M", "ꙝ"), + (0xA65D, "V"), + (0xA65E, "M", "ꙟ"), + (0xA65F, "V"), + (0xA660, "M", "ꙡ"), + (0xA661, "V"), + (0xA662, "M", "ꙣ"), + (0xA663, "V"), + (0xA664, "M", "ꙥ"), + (0xA665, "V"), + (0xA666, "M", "ꙧ"), + (0xA667, "V"), + (0xA668, "M", "ꙩ"), + (0xA669, "V"), + (0xA66A, "M", "ꙫ"), + (0xA66B, "V"), + (0xA66C, "M", "ꙭ"), + (0xA66D, "V"), + (0xA680, "M", "ꚁ"), + (0xA681, "V"), + (0xA682, "M", "ꚃ"), + (0xA683, "V"), + (0xA684, "M", "ꚅ"), + (0xA685, "V"), + (0xA686, "M", "ꚇ"), + (0xA687, "V"), + (0xA688, "M", "ꚉ"), + (0xA689, "V"), + (0xA68A, "M", "ꚋ"), + (0xA68B, "V"), + (0xA68C, "M", "ꚍ"), + (0xA68D, "V"), + (0xA68E, "M", "ꚏ"), + (0xA68F, "V"), + (0xA690, "M", "ꚑ"), + (0xA691, "V"), + ] + + +def _seg_36() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xA692, "M", "ꚓ"), + (0xA693, "V"), + (0xA694, "M", "ꚕ"), + (0xA695, "V"), + (0xA696, "M", "ꚗ"), + (0xA697, "V"), + (0xA698, "M", "ꚙ"), + (0xA699, "V"), + (0xA69A, "M", "ꚛ"), + (0xA69B, "V"), + (0xA69C, "M", "ъ"), + (0xA69D, "M", "ь"), + (0xA69E, "V"), + (0xA6F8, "X"), + (0xA700, "V"), + (0xA722, "M", "ꜣ"), + (0xA723, "V"), + (0xA724, "M", "ꜥ"), + (0xA725, "V"), + (0xA726, "M", "ꜧ"), + (0xA727, "V"), + (0xA728, "M", "ꜩ"), + (0xA729, "V"), + (0xA72A, "M", "ꜫ"), + (0xA72B, "V"), + (0xA72C, "M", "ꜭ"), + (0xA72D, "V"), + (0xA72E, "M", "ꜯ"), + (0xA72F, "V"), + (0xA732, "M", "ꜳ"), + (0xA733, "V"), + (0xA734, "M", "ꜵ"), + (0xA735, "V"), + (0xA736, "M", "ꜷ"), + (0xA737, "V"), + (0xA738, "M", "ꜹ"), + (0xA739, "V"), + (0xA73A, "M", "ꜻ"), + (0xA73B, "V"), + (0xA73C, "M", "ꜽ"), + (0xA73D, "V"), + (0xA73E, "M", "ꜿ"), + (0xA73F, "V"), + (0xA740, "M", "ꝁ"), + (0xA741, "V"), + (0xA742, "M", "ꝃ"), + (0xA743, "V"), + (0xA744, "M", "ꝅ"), + (0xA745, "V"), + (0xA746, "M", "ꝇ"), + (0xA747, "V"), + (0xA748, "M", "ꝉ"), + (0xA749, "V"), + (0xA74A, "M", "ꝋ"), + (0xA74B, "V"), + (0xA74C, "M", "ꝍ"), + (0xA74D, "V"), + (0xA74E, "M", "ꝏ"), + (0xA74F, "V"), + (0xA750, "M", "ꝑ"), + (0xA751, "V"), + (0xA752, "M", "ꝓ"), + (0xA753, "V"), + (0xA754, "M", "ꝕ"), + (0xA755, "V"), + (0xA756, "M", "ꝗ"), + (0xA757, "V"), + (0xA758, "M", "ꝙ"), + (0xA759, "V"), + (0xA75A, "M", "ꝛ"), + (0xA75B, "V"), + (0xA75C, "M", "ꝝ"), + (0xA75D, "V"), + (0xA75E, "M", "ꝟ"), + (0xA75F, "V"), + (0xA760, "M", "ꝡ"), + (0xA761, "V"), + (0xA762, "M", "ꝣ"), + (0xA763, "V"), + (0xA764, "M", "ꝥ"), + (0xA765, "V"), + (0xA766, "M", "ꝧ"), + (0xA767, "V"), + (0xA768, "M", "ꝩ"), + (0xA769, "V"), + (0xA76A, "M", "ꝫ"), + (0xA76B, "V"), + (0xA76C, "M", "ꝭ"), + (0xA76D, "V"), + (0xA76E, "M", "ꝯ"), + (0xA76F, "V"), + (0xA770, "M", "ꝯ"), + (0xA771, "V"), + (0xA779, "M", "ꝺ"), + (0xA77A, "V"), + (0xA77B, "M", "ꝼ"), + (0xA77C, "V"), + (0xA77D, "M", "ᵹ"), + (0xA77E, "M", "ꝿ"), + (0xA77F, "V"), + ] + + +def _seg_37() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xA780, "M", "ꞁ"), + (0xA781, "V"), + (0xA782, "M", "ꞃ"), + (0xA783, "V"), + (0xA784, "M", "ꞅ"), + (0xA785, "V"), + (0xA786, "M", "ꞇ"), + (0xA787, "V"), + (0xA78B, "M", "ꞌ"), + (0xA78C, "V"), + (0xA78D, "M", "ɥ"), + (0xA78E, "V"), + (0xA790, "M", "ꞑ"), + (0xA791, "V"), + (0xA792, "M", "ꞓ"), + (0xA793, "V"), + (0xA796, "M", "ꞗ"), + (0xA797, "V"), + (0xA798, "M", "ꞙ"), + (0xA799, "V"), + (0xA79A, "M", "ꞛ"), + (0xA79B, "V"), + (0xA79C, "M", "ꞝ"), + (0xA79D, "V"), + (0xA79E, "M", "ꞟ"), + (0xA79F, "V"), + (0xA7A0, "M", "ꞡ"), + (0xA7A1, "V"), + (0xA7A2, "M", "ꞣ"), + (0xA7A3, "V"), + (0xA7A4, "M", "ꞥ"), + (0xA7A5, "V"), + (0xA7A6, "M", "ꞧ"), + (0xA7A7, "V"), + (0xA7A8, "M", "ꞩ"), + (0xA7A9, "V"), + (0xA7AA, "M", "ɦ"), + (0xA7AB, "M", "ɜ"), + (0xA7AC, "M", "ɡ"), + (0xA7AD, "M", "ɬ"), + (0xA7AE, "M", "ɪ"), + (0xA7AF, "V"), + (0xA7B0, "M", "ʞ"), + (0xA7B1, "M", "ʇ"), + (0xA7B2, "M", "ʝ"), + (0xA7B3, "M", "ꭓ"), + (0xA7B4, "M", "ꞵ"), + (0xA7B5, "V"), + (0xA7B6, "M", "ꞷ"), + (0xA7B7, "V"), + (0xA7B8, "M", "ꞹ"), + (0xA7B9, "V"), + (0xA7BA, "M", "ꞻ"), + (0xA7BB, "V"), + (0xA7BC, "M", "ꞽ"), + (0xA7BD, "V"), + (0xA7BE, "M", "ꞿ"), + (0xA7BF, "V"), + (0xA7C0, "M", "ꟁ"), + (0xA7C1, "V"), + (0xA7C2, "M", "ꟃ"), + (0xA7C3, "V"), + (0xA7C4, "M", "ꞔ"), + (0xA7C5, "M", "ʂ"), + (0xA7C6, "M", "ᶎ"), + (0xA7C7, "M", "ꟈ"), + (0xA7C8, "V"), + (0xA7C9, "M", "ꟊ"), + (0xA7CA, "V"), + (0xA7CB, "X"), + (0xA7D0, "M", "ꟑ"), + (0xA7D1, "V"), + (0xA7D2, "X"), + (0xA7D3, "V"), + (0xA7D4, "X"), + (0xA7D5, "V"), + (0xA7D6, "M", "ꟗ"), + (0xA7D7, "V"), + (0xA7D8, "M", "ꟙ"), + (0xA7D9, "V"), + (0xA7DA, "X"), + (0xA7F2, "M", "c"), + (0xA7F3, "M", "f"), + (0xA7F4, "M", "q"), + (0xA7F5, "M", "ꟶ"), + (0xA7F6, "V"), + (0xA7F8, "M", "ħ"), + (0xA7F9, "M", "œ"), + (0xA7FA, "V"), + (0xA82D, "X"), + (0xA830, "V"), + (0xA83A, "X"), + (0xA840, "V"), + (0xA878, "X"), + (0xA880, "V"), + (0xA8C6, "X"), + (0xA8CE, "V"), + (0xA8DA, "X"), + (0xA8E0, "V"), + (0xA954, "X"), + ] + + +def _seg_38() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xA95F, "V"), + (0xA97D, "X"), + (0xA980, "V"), + (0xA9CE, "X"), + (0xA9CF, "V"), + (0xA9DA, "X"), + (0xA9DE, "V"), + (0xA9FF, "X"), + (0xAA00, "V"), + (0xAA37, "X"), + (0xAA40, "V"), + (0xAA4E, "X"), + (0xAA50, "V"), + (0xAA5A, "X"), + (0xAA5C, "V"), + (0xAAC3, "X"), + (0xAADB, "V"), + (0xAAF7, "X"), + (0xAB01, "V"), + (0xAB07, "X"), + (0xAB09, "V"), + (0xAB0F, "X"), + (0xAB11, "V"), + (0xAB17, "X"), + (0xAB20, "V"), + (0xAB27, "X"), + (0xAB28, "V"), + (0xAB2F, "X"), + (0xAB30, "V"), + (0xAB5C, "M", "ꜧ"), + (0xAB5D, "M", "ꬷ"), + (0xAB5E, "M", "ɫ"), + (0xAB5F, "M", "ꭒ"), + (0xAB60, "V"), + (0xAB69, "M", "ʍ"), + (0xAB6A, "V"), + (0xAB6C, "X"), + (0xAB70, "M", "Ꭰ"), + (0xAB71, "M", "Ꭱ"), + (0xAB72, "M", "Ꭲ"), + (0xAB73, "M", "Ꭳ"), + (0xAB74, "M", "Ꭴ"), + (0xAB75, "M", "Ꭵ"), + (0xAB76, "M", "Ꭶ"), + (0xAB77, "M", "Ꭷ"), + (0xAB78, "M", "Ꭸ"), + (0xAB79, "M", "Ꭹ"), + (0xAB7A, "M", "Ꭺ"), + (0xAB7B, "M", "Ꭻ"), + (0xAB7C, "M", "Ꭼ"), + (0xAB7D, "M", "Ꭽ"), + (0xAB7E, "M", "Ꭾ"), + (0xAB7F, "M", "Ꭿ"), + (0xAB80, "M", "Ꮀ"), + (0xAB81, "M", "Ꮁ"), + (0xAB82, "M", "Ꮂ"), + (0xAB83, "M", "Ꮃ"), + (0xAB84, "M", "Ꮄ"), + (0xAB85, "M", "Ꮅ"), + (0xAB86, "M", "Ꮆ"), + (0xAB87, "M", "Ꮇ"), + (0xAB88, "M", "Ꮈ"), + (0xAB89, "M", "Ꮉ"), + (0xAB8A, "M", "Ꮊ"), + (0xAB8B, "M", "Ꮋ"), + (0xAB8C, "M", "Ꮌ"), + (0xAB8D, "M", "Ꮍ"), + (0xAB8E, "M", "Ꮎ"), + (0xAB8F, "M", "Ꮏ"), + (0xAB90, "M", "Ꮐ"), + (0xAB91, "M", "Ꮑ"), + (0xAB92, "M", "Ꮒ"), + (0xAB93, "M", "Ꮓ"), + (0xAB94, "M", "Ꮔ"), + (0xAB95, "M", "Ꮕ"), + (0xAB96, "M", "Ꮖ"), + (0xAB97, "M", "Ꮗ"), + (0xAB98, "M", "Ꮘ"), + (0xAB99, "M", "Ꮙ"), + (0xAB9A, "M", "Ꮚ"), + (0xAB9B, "M", "Ꮛ"), + (0xAB9C, "M", "Ꮜ"), + (0xAB9D, "M", "Ꮝ"), + (0xAB9E, "M", "Ꮞ"), + (0xAB9F, "M", "Ꮟ"), + (0xABA0, "M", "Ꮠ"), + (0xABA1, "M", "Ꮡ"), + (0xABA2, "M", "Ꮢ"), + (0xABA3, "M", "Ꮣ"), + (0xABA4, "M", "Ꮤ"), + (0xABA5, "M", "Ꮥ"), + (0xABA6, "M", "Ꮦ"), + (0xABA7, "M", "Ꮧ"), + (0xABA8, "M", "Ꮨ"), + (0xABA9, "M", "Ꮩ"), + (0xABAA, "M", "Ꮪ"), + (0xABAB, "M", "Ꮫ"), + (0xABAC, "M", "Ꮬ"), + (0xABAD, "M", "Ꮭ"), + (0xABAE, "M", "Ꮮ"), + ] + + +def _seg_39() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xABAF, "M", "Ꮯ"), + (0xABB0, "M", "Ꮰ"), + (0xABB1, "M", "Ꮱ"), + (0xABB2, "M", "Ꮲ"), + (0xABB3, "M", "Ꮳ"), + (0xABB4, "M", "Ꮴ"), + (0xABB5, "M", "Ꮵ"), + (0xABB6, "M", "Ꮶ"), + (0xABB7, "M", "Ꮷ"), + (0xABB8, "M", "Ꮸ"), + (0xABB9, "M", "Ꮹ"), + (0xABBA, "M", "Ꮺ"), + (0xABBB, "M", "Ꮻ"), + (0xABBC, "M", "Ꮼ"), + (0xABBD, "M", "Ꮽ"), + (0xABBE, "M", "Ꮾ"), + (0xABBF, "M", "Ꮿ"), + (0xABC0, "V"), + (0xABEE, "X"), + (0xABF0, "V"), + (0xABFA, "X"), + (0xAC00, "V"), + (0xD7A4, "X"), + (0xD7B0, "V"), + (0xD7C7, "X"), + (0xD7CB, "V"), + (0xD7FC, "X"), + (0xF900, "M", "豈"), + (0xF901, "M", "更"), + (0xF902, "M", "車"), + (0xF903, "M", "賈"), + (0xF904, "M", "滑"), + (0xF905, "M", "串"), + (0xF906, "M", "句"), + (0xF907, "M", "龜"), + (0xF909, "M", "契"), + (0xF90A, "M", "金"), + (0xF90B, "M", "喇"), + (0xF90C, "M", "奈"), + (0xF90D, "M", "懶"), + (0xF90E, "M", "癩"), + (0xF90F, "M", "羅"), + (0xF910, "M", "蘿"), + (0xF911, "M", "螺"), + (0xF912, "M", "裸"), + (0xF913, "M", "邏"), + (0xF914, "M", "樂"), + (0xF915, "M", "洛"), + (0xF916, "M", "烙"), + (0xF917, "M", "珞"), + (0xF918, "M", "落"), + (0xF919, "M", "酪"), + (0xF91A, "M", "駱"), + (0xF91B, "M", "亂"), + (0xF91C, "M", "卵"), + (0xF91D, "M", "欄"), + (0xF91E, "M", "爛"), + (0xF91F, "M", "蘭"), + (0xF920, "M", "鸞"), + (0xF921, "M", "嵐"), + (0xF922, "M", "濫"), + (0xF923, "M", "藍"), + (0xF924, "M", "襤"), + (0xF925, "M", "拉"), + (0xF926, "M", "臘"), + (0xF927, "M", "蠟"), + (0xF928, "M", "廊"), + (0xF929, "M", "朗"), + (0xF92A, "M", "浪"), + (0xF92B, "M", "狼"), + (0xF92C, "M", "郎"), + (0xF92D, "M", "來"), + (0xF92E, "M", "冷"), + (0xF92F, "M", "勞"), + (0xF930, "M", "擄"), + (0xF931, "M", "櫓"), + (0xF932, "M", "爐"), + (0xF933, "M", "盧"), + (0xF934, "M", "老"), + (0xF935, "M", "蘆"), + (0xF936, "M", "虜"), + (0xF937, "M", "路"), + (0xF938, "M", "露"), + (0xF939, "M", "魯"), + (0xF93A, "M", "鷺"), + (0xF93B, "M", "碌"), + (0xF93C, "M", "祿"), + (0xF93D, "M", "綠"), + (0xF93E, "M", "菉"), + (0xF93F, "M", "錄"), + (0xF940, "M", "鹿"), + (0xF941, "M", "論"), + (0xF942, "M", "壟"), + (0xF943, "M", "弄"), + (0xF944, "M", "籠"), + (0xF945, "M", "聾"), + (0xF946, "M", "牢"), + (0xF947, "M", "磊"), + (0xF948, "M", "賂"), + (0xF949, "M", "雷"), + ] + + +def _seg_40() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xF94A, "M", "壘"), + (0xF94B, "M", "屢"), + (0xF94C, "M", "樓"), + (0xF94D, "M", "淚"), + (0xF94E, "M", "漏"), + (0xF94F, "M", "累"), + (0xF950, "M", "縷"), + (0xF951, "M", "陋"), + (0xF952, "M", "勒"), + (0xF953, "M", "肋"), + (0xF954, "M", "凜"), + (0xF955, "M", "凌"), + (0xF956, "M", "稜"), + (0xF957, "M", "綾"), + (0xF958, "M", "菱"), + (0xF959, "M", "陵"), + (0xF95A, "M", "讀"), + (0xF95B, "M", "拏"), + (0xF95C, "M", "樂"), + (0xF95D, "M", "諾"), + (0xF95E, "M", "丹"), + (0xF95F, "M", "寧"), + (0xF960, "M", "怒"), + (0xF961, "M", "率"), + (0xF962, "M", "異"), + (0xF963, "M", "北"), + (0xF964, "M", "磻"), + (0xF965, "M", "便"), + (0xF966, "M", "復"), + (0xF967, "M", "不"), + (0xF968, "M", "泌"), + (0xF969, "M", "數"), + (0xF96A, "M", "索"), + (0xF96B, "M", "參"), + (0xF96C, "M", "塞"), + (0xF96D, "M", "省"), + (0xF96E, "M", "葉"), + (0xF96F, "M", "說"), + (0xF970, "M", "殺"), + (0xF971, "M", "辰"), + (0xF972, "M", "沈"), + (0xF973, "M", "拾"), + (0xF974, "M", "若"), + (0xF975, "M", "掠"), + (0xF976, "M", "略"), + (0xF977, "M", "亮"), + (0xF978, "M", "兩"), + (0xF979, "M", "凉"), + (0xF97A, "M", "梁"), + (0xF97B, "M", "糧"), + (0xF97C, "M", "良"), + (0xF97D, "M", "諒"), + (0xF97E, "M", "量"), + (0xF97F, "M", "勵"), + (0xF980, "M", "呂"), + (0xF981, "M", "女"), + (0xF982, "M", "廬"), + (0xF983, "M", "旅"), + (0xF984, "M", "濾"), + (0xF985, "M", "礪"), + (0xF986, "M", "閭"), + (0xF987, "M", "驪"), + (0xF988, "M", "麗"), + (0xF989, "M", "黎"), + (0xF98A, "M", "力"), + (0xF98B, "M", "曆"), + (0xF98C, "M", "歷"), + (0xF98D, "M", "轢"), + (0xF98E, "M", "年"), + (0xF98F, "M", "憐"), + (0xF990, "M", "戀"), + (0xF991, "M", "撚"), + (0xF992, "M", "漣"), + (0xF993, "M", "煉"), + (0xF994, "M", "璉"), + (0xF995, "M", "秊"), + (0xF996, "M", "練"), + (0xF997, "M", "聯"), + (0xF998, "M", "輦"), + (0xF999, "M", "蓮"), + (0xF99A, "M", "連"), + (0xF99B, "M", "鍊"), + (0xF99C, "M", "列"), + (0xF99D, "M", "劣"), + (0xF99E, "M", "咽"), + (0xF99F, "M", "烈"), + (0xF9A0, "M", "裂"), + (0xF9A1, "M", "說"), + (0xF9A2, "M", "廉"), + (0xF9A3, "M", "念"), + (0xF9A4, "M", "捻"), + (0xF9A5, "M", "殮"), + (0xF9A6, "M", "簾"), + (0xF9A7, "M", "獵"), + (0xF9A8, "M", "令"), + (0xF9A9, "M", "囹"), + (0xF9AA, "M", "寧"), + (0xF9AB, "M", "嶺"), + (0xF9AC, "M", "怜"), + (0xF9AD, "M", "玲"), + ] + + +def _seg_41() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xF9AE, "M", "瑩"), + (0xF9AF, "M", "羚"), + (0xF9B0, "M", "聆"), + (0xF9B1, "M", "鈴"), + (0xF9B2, "M", "零"), + (0xF9B3, "M", "靈"), + (0xF9B4, "M", "領"), + (0xF9B5, "M", "例"), + (0xF9B6, "M", "禮"), + (0xF9B7, "M", "醴"), + (0xF9B8, "M", "隸"), + (0xF9B9, "M", "惡"), + (0xF9BA, "M", "了"), + (0xF9BB, "M", "僚"), + (0xF9BC, "M", "寮"), + (0xF9BD, "M", "尿"), + (0xF9BE, "M", "料"), + (0xF9BF, "M", "樂"), + (0xF9C0, "M", "燎"), + (0xF9C1, "M", "療"), + (0xF9C2, "M", "蓼"), + (0xF9C3, "M", "遼"), + (0xF9C4, "M", "龍"), + (0xF9C5, "M", "暈"), + (0xF9C6, "M", "阮"), + (0xF9C7, "M", "劉"), + (0xF9C8, "M", "杻"), + (0xF9C9, "M", "柳"), + (0xF9CA, "M", "流"), + (0xF9CB, "M", "溜"), + (0xF9CC, "M", "琉"), + (0xF9CD, "M", "留"), + (0xF9CE, "M", "硫"), + (0xF9CF, "M", "紐"), + (0xF9D0, "M", "類"), + (0xF9D1, "M", "六"), + (0xF9D2, "M", "戮"), + (0xF9D3, "M", "陸"), + (0xF9D4, "M", "倫"), + (0xF9D5, "M", "崙"), + (0xF9D6, "M", "淪"), + (0xF9D7, "M", "輪"), + (0xF9D8, "M", "律"), + (0xF9D9, "M", "慄"), + (0xF9DA, "M", "栗"), + (0xF9DB, "M", "率"), + (0xF9DC, "M", "隆"), + (0xF9DD, "M", "利"), + (0xF9DE, "M", "吏"), + (0xF9DF, "M", "履"), + (0xF9E0, "M", "易"), + (0xF9E1, "M", "李"), + (0xF9E2, "M", "梨"), + (0xF9E3, "M", "泥"), + (0xF9E4, "M", "理"), + (0xF9E5, "M", "痢"), + (0xF9E6, "M", "罹"), + (0xF9E7, "M", "裏"), + (0xF9E8, "M", "裡"), + (0xF9E9, "M", "里"), + (0xF9EA, "M", "離"), + (0xF9EB, "M", "匿"), + (0xF9EC, "M", "溺"), + (0xF9ED, "M", "吝"), + (0xF9EE, "M", "燐"), + (0xF9EF, "M", "璘"), + (0xF9F0, "M", "藺"), + (0xF9F1, "M", "隣"), + (0xF9F2, "M", "鱗"), + (0xF9F3, "M", "麟"), + (0xF9F4, "M", "林"), + (0xF9F5, "M", "淋"), + (0xF9F6, "M", "臨"), + (0xF9F7, "M", "立"), + (0xF9F8, "M", "笠"), + (0xF9F9, "M", "粒"), + (0xF9FA, "M", "狀"), + (0xF9FB, "M", "炙"), + (0xF9FC, "M", "識"), + (0xF9FD, "M", "什"), + (0xF9FE, "M", "茶"), + (0xF9FF, "M", "刺"), + (0xFA00, "M", "切"), + (0xFA01, "M", "度"), + (0xFA02, "M", "拓"), + (0xFA03, "M", "糖"), + (0xFA04, "M", "宅"), + (0xFA05, "M", "洞"), + (0xFA06, "M", "暴"), + (0xFA07, "M", "輻"), + (0xFA08, "M", "行"), + (0xFA09, "M", "降"), + (0xFA0A, "M", "見"), + (0xFA0B, "M", "廓"), + (0xFA0C, "M", "兀"), + (0xFA0D, "M", "嗀"), + (0xFA0E, "V"), + (0xFA10, "M", "塚"), + (0xFA11, "V"), + (0xFA12, "M", "晴"), + ] + + +def _seg_42() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xFA13, "V"), + (0xFA15, "M", "凞"), + (0xFA16, "M", "猪"), + (0xFA17, "M", "益"), + (0xFA18, "M", "礼"), + (0xFA19, "M", "神"), + (0xFA1A, "M", "祥"), + (0xFA1B, "M", "福"), + (0xFA1C, "M", "靖"), + (0xFA1D, "M", "精"), + (0xFA1E, "M", "羽"), + (0xFA1F, "V"), + (0xFA20, "M", "蘒"), + (0xFA21, "V"), + (0xFA22, "M", "諸"), + (0xFA23, "V"), + (0xFA25, "M", "逸"), + (0xFA26, "M", "都"), + (0xFA27, "V"), + (0xFA2A, "M", "飯"), + (0xFA2B, "M", "飼"), + (0xFA2C, "M", "館"), + (0xFA2D, "M", "鶴"), + (0xFA2E, "M", "郞"), + (0xFA2F, "M", "隷"), + (0xFA30, "M", "侮"), + (0xFA31, "M", "僧"), + (0xFA32, "M", "免"), + (0xFA33, "M", "勉"), + (0xFA34, "M", "勤"), + (0xFA35, "M", "卑"), + (0xFA36, "M", "喝"), + (0xFA37, "M", "嘆"), + (0xFA38, "M", "器"), + (0xFA39, "M", "塀"), + (0xFA3A, "M", "墨"), + (0xFA3B, "M", "層"), + (0xFA3C, "M", "屮"), + (0xFA3D, "M", "悔"), + (0xFA3E, "M", "慨"), + (0xFA3F, "M", "憎"), + (0xFA40, "M", "懲"), + (0xFA41, "M", "敏"), + (0xFA42, "M", "既"), + (0xFA43, "M", "暑"), + (0xFA44, "M", "梅"), + (0xFA45, "M", "海"), + (0xFA46, "M", "渚"), + (0xFA47, "M", "漢"), + (0xFA48, "M", "煮"), + (0xFA49, "M", "爫"), + (0xFA4A, "M", "琢"), + (0xFA4B, "M", "碑"), + (0xFA4C, "M", "社"), + (0xFA4D, "M", "祉"), + (0xFA4E, "M", "祈"), + (0xFA4F, "M", "祐"), + (0xFA50, "M", "祖"), + (0xFA51, "M", "祝"), + (0xFA52, "M", "禍"), + (0xFA53, "M", "禎"), + (0xFA54, "M", "穀"), + (0xFA55, "M", "突"), + (0xFA56, "M", "節"), + (0xFA57, "M", "練"), + (0xFA58, "M", "縉"), + (0xFA59, "M", "繁"), + (0xFA5A, "M", "署"), + (0xFA5B, "M", "者"), + (0xFA5C, "M", "臭"), + (0xFA5D, "M", "艹"), + (0xFA5F, "M", "著"), + (0xFA60, "M", "褐"), + (0xFA61, "M", "視"), + (0xFA62, "M", "謁"), + (0xFA63, "M", "謹"), + (0xFA64, "M", "賓"), + (0xFA65, "M", "贈"), + (0xFA66, "M", "辶"), + (0xFA67, "M", "逸"), + (0xFA68, "M", "難"), + (0xFA69, "M", "響"), + (0xFA6A, "M", "頻"), + (0xFA6B, "M", "恵"), + (0xFA6C, "M", "𤋮"), + (0xFA6D, "M", "舘"), + (0xFA6E, "X"), + (0xFA70, "M", "並"), + (0xFA71, "M", "况"), + (0xFA72, "M", "全"), + (0xFA73, "M", "侀"), + (0xFA74, "M", "充"), + (0xFA75, "M", "冀"), + (0xFA76, "M", "勇"), + (0xFA77, "M", "勺"), + (0xFA78, "M", "喝"), + (0xFA79, "M", "啕"), + (0xFA7A, "M", "喙"), + (0xFA7B, "M", "嗢"), + (0xFA7C, "M", "塚"), + ] + + +def _seg_43() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xFA7D, "M", "墳"), + (0xFA7E, "M", "奄"), + (0xFA7F, "M", "奔"), + (0xFA80, "M", "婢"), + (0xFA81, "M", "嬨"), + (0xFA82, "M", "廒"), + (0xFA83, "M", "廙"), + (0xFA84, "M", "彩"), + (0xFA85, "M", "徭"), + (0xFA86, "M", "惘"), + (0xFA87, "M", "慎"), + (0xFA88, "M", "愈"), + (0xFA89, "M", "憎"), + (0xFA8A, "M", "慠"), + (0xFA8B, "M", "懲"), + (0xFA8C, "M", "戴"), + (0xFA8D, "M", "揄"), + (0xFA8E, "M", "搜"), + (0xFA8F, "M", "摒"), + (0xFA90, "M", "敖"), + (0xFA91, "M", "晴"), + (0xFA92, "M", "朗"), + (0xFA93, "M", "望"), + (0xFA94, "M", "杖"), + (0xFA95, "M", "歹"), + (0xFA96, "M", "殺"), + (0xFA97, "M", "流"), + (0xFA98, "M", "滛"), + (0xFA99, "M", "滋"), + (0xFA9A, "M", "漢"), + (0xFA9B, "M", "瀞"), + (0xFA9C, "M", "煮"), + (0xFA9D, "M", "瞧"), + (0xFA9E, "M", "爵"), + (0xFA9F, "M", "犯"), + (0xFAA0, "M", "猪"), + (0xFAA1, "M", "瑱"), + (0xFAA2, "M", "甆"), + (0xFAA3, "M", "画"), + (0xFAA4, "M", "瘝"), + (0xFAA5, "M", "瘟"), + (0xFAA6, "M", "益"), + (0xFAA7, "M", "盛"), + (0xFAA8, "M", "直"), + (0xFAA9, "M", "睊"), + (0xFAAA, "M", "着"), + (0xFAAB, "M", "磌"), + (0xFAAC, "M", "窱"), + (0xFAAD, "M", "節"), + (0xFAAE, "M", "类"), + (0xFAAF, "M", "絛"), + (0xFAB0, "M", "練"), + (0xFAB1, "M", "缾"), + (0xFAB2, "M", "者"), + (0xFAB3, "M", "荒"), + (0xFAB4, "M", "華"), + (0xFAB5, "M", "蝹"), + (0xFAB6, "M", "襁"), + (0xFAB7, "M", "覆"), + (0xFAB8, "M", "視"), + (0xFAB9, "M", "調"), + (0xFABA, "M", "諸"), + (0xFABB, "M", "請"), + (0xFABC, "M", "謁"), + (0xFABD, "M", "諾"), + (0xFABE, "M", "諭"), + (0xFABF, "M", "謹"), + (0xFAC0, "M", "變"), + (0xFAC1, "M", "贈"), + (0xFAC2, "M", "輸"), + (0xFAC3, "M", "遲"), + (0xFAC4, "M", "醙"), + (0xFAC5, "M", "鉶"), + (0xFAC6, "M", "陼"), + (0xFAC7, "M", "難"), + (0xFAC8, "M", "靖"), + (0xFAC9, "M", "韛"), + (0xFACA, "M", "響"), + (0xFACB, "M", "頋"), + (0xFACC, "M", "頻"), + (0xFACD, "M", "鬒"), + (0xFACE, "M", "龜"), + (0xFACF, "M", "𢡊"), + (0xFAD0, "M", "𢡄"), + (0xFAD1, "M", "𣏕"), + (0xFAD2, "M", "㮝"), + (0xFAD3, "M", "䀘"), + (0xFAD4, "M", "䀹"), + (0xFAD5, "M", "𥉉"), + (0xFAD6, "M", "𥳐"), + (0xFAD7, "M", "𧻓"), + (0xFAD8, "M", "齃"), + (0xFAD9, "M", "龎"), + (0xFADA, "X"), + (0xFB00, "M", "ff"), + (0xFB01, "M", "fi"), + (0xFB02, "M", "fl"), + (0xFB03, "M", "ffi"), + (0xFB04, "M", "ffl"), + (0xFB05, "M", "st"), + ] + + +def _seg_44() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xFB07, "X"), + (0xFB13, "M", "մն"), + (0xFB14, "M", "մե"), + (0xFB15, "M", "մի"), + (0xFB16, "M", "վն"), + (0xFB17, "M", "մխ"), + (0xFB18, "X"), + (0xFB1D, "M", "יִ"), + (0xFB1E, "V"), + (0xFB1F, "M", "ײַ"), + (0xFB20, "M", "ע"), + (0xFB21, "M", "א"), + (0xFB22, "M", "ד"), + (0xFB23, "M", "ה"), + (0xFB24, "M", "כ"), + (0xFB25, "M", "ל"), + (0xFB26, "M", "ם"), + (0xFB27, "M", "ר"), + (0xFB28, "M", "ת"), + (0xFB29, "3", "+"), + (0xFB2A, "M", "שׁ"), + (0xFB2B, "M", "שׂ"), + (0xFB2C, "M", "שּׁ"), + (0xFB2D, "M", "שּׂ"), + (0xFB2E, "M", "אַ"), + (0xFB2F, "M", "אָ"), + (0xFB30, "M", "אּ"), + (0xFB31, "M", "בּ"), + (0xFB32, "M", "גּ"), + (0xFB33, "M", "דּ"), + (0xFB34, "M", "הּ"), + (0xFB35, "M", "וּ"), + (0xFB36, "M", "זּ"), + (0xFB37, "X"), + (0xFB38, "M", "טּ"), + (0xFB39, "M", "יּ"), + (0xFB3A, "M", "ךּ"), + (0xFB3B, "M", "כּ"), + (0xFB3C, "M", "לּ"), + (0xFB3D, "X"), + (0xFB3E, "M", "מּ"), + (0xFB3F, "X"), + (0xFB40, "M", "נּ"), + (0xFB41, "M", "סּ"), + (0xFB42, "X"), + (0xFB43, "M", "ףּ"), + (0xFB44, "M", "פּ"), + (0xFB45, "X"), + (0xFB46, "M", "צּ"), + (0xFB47, "M", "קּ"), + (0xFB48, "M", "רּ"), + (0xFB49, "M", "שּ"), + (0xFB4A, "M", "תּ"), + (0xFB4B, "M", "וֹ"), + (0xFB4C, "M", "בֿ"), + (0xFB4D, "M", "כֿ"), + (0xFB4E, "M", "פֿ"), + (0xFB4F, "M", "אל"), + (0xFB50, "M", "ٱ"), + (0xFB52, "M", "ٻ"), + (0xFB56, "M", "پ"), + (0xFB5A, "M", "ڀ"), + (0xFB5E, "M", "ٺ"), + (0xFB62, "M", "ٿ"), + (0xFB66, "M", "ٹ"), + (0xFB6A, "M", "ڤ"), + (0xFB6E, "M", "ڦ"), + (0xFB72, "M", "ڄ"), + (0xFB76, "M", "ڃ"), + (0xFB7A, "M", "چ"), + (0xFB7E, "M", "ڇ"), + (0xFB82, "M", "ڍ"), + (0xFB84, "M", "ڌ"), + (0xFB86, "M", "ڎ"), + (0xFB88, "M", "ڈ"), + (0xFB8A, "M", "ژ"), + (0xFB8C, "M", "ڑ"), + (0xFB8E, "M", "ک"), + (0xFB92, "M", "گ"), + (0xFB96, "M", "ڳ"), + (0xFB9A, "M", "ڱ"), + (0xFB9E, "M", "ں"), + (0xFBA0, "M", "ڻ"), + (0xFBA4, "M", "ۀ"), + (0xFBA6, "M", "ہ"), + (0xFBAA, "M", "ھ"), + (0xFBAE, "M", "ے"), + (0xFBB0, "M", "ۓ"), + (0xFBB2, "V"), + (0xFBC3, "X"), + (0xFBD3, "M", "ڭ"), + (0xFBD7, "M", "ۇ"), + (0xFBD9, "M", "ۆ"), + (0xFBDB, "M", "ۈ"), + (0xFBDD, "M", "ۇٴ"), + (0xFBDE, "M", "ۋ"), + (0xFBE0, "M", "ۅ"), + (0xFBE2, "M", "ۉ"), + (0xFBE4, "M", "ې"), + (0xFBE8, "M", "ى"), + ] + + +def _seg_45() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xFBEA, "M", "ئا"), + (0xFBEC, "M", "ئە"), + (0xFBEE, "M", "ئو"), + (0xFBF0, "M", "ئۇ"), + (0xFBF2, "M", "ئۆ"), + (0xFBF4, "M", "ئۈ"), + (0xFBF6, "M", "ئې"), + (0xFBF9, "M", "ئى"), + (0xFBFC, "M", "ی"), + (0xFC00, "M", "ئج"), + (0xFC01, "M", "ئح"), + (0xFC02, "M", "ئم"), + (0xFC03, "M", "ئى"), + (0xFC04, "M", "ئي"), + (0xFC05, "M", "بج"), + (0xFC06, "M", "بح"), + (0xFC07, "M", "بخ"), + (0xFC08, "M", "بم"), + (0xFC09, "M", "بى"), + (0xFC0A, "M", "بي"), + (0xFC0B, "M", "تج"), + (0xFC0C, "M", "تح"), + (0xFC0D, "M", "تخ"), + (0xFC0E, "M", "تم"), + (0xFC0F, "M", "تى"), + (0xFC10, "M", "تي"), + (0xFC11, "M", "ثج"), + (0xFC12, "M", "ثم"), + (0xFC13, "M", "ثى"), + (0xFC14, "M", "ثي"), + (0xFC15, "M", "جح"), + (0xFC16, "M", "جم"), + (0xFC17, "M", "حج"), + (0xFC18, "M", "حم"), + (0xFC19, "M", "خج"), + (0xFC1A, "M", "خح"), + (0xFC1B, "M", "خم"), + (0xFC1C, "M", "سج"), + (0xFC1D, "M", "سح"), + (0xFC1E, "M", "سخ"), + (0xFC1F, "M", "سم"), + (0xFC20, "M", "صح"), + (0xFC21, "M", "صم"), + (0xFC22, "M", "ضج"), + (0xFC23, "M", "ضح"), + (0xFC24, "M", "ضخ"), + (0xFC25, "M", "ضم"), + (0xFC26, "M", "طح"), + (0xFC27, "M", "طم"), + (0xFC28, "M", "ظم"), + (0xFC29, "M", "عج"), + (0xFC2A, "M", "عم"), + (0xFC2B, "M", "غج"), + (0xFC2C, "M", "غم"), + (0xFC2D, "M", "فج"), + (0xFC2E, "M", "فح"), + (0xFC2F, "M", "فخ"), + (0xFC30, "M", "فم"), + (0xFC31, "M", "فى"), + (0xFC32, "M", "في"), + (0xFC33, "M", "قح"), + (0xFC34, "M", "قم"), + (0xFC35, "M", "قى"), + (0xFC36, "M", "قي"), + (0xFC37, "M", "كا"), + (0xFC38, "M", "كج"), + (0xFC39, "M", "كح"), + (0xFC3A, "M", "كخ"), + (0xFC3B, "M", "كل"), + (0xFC3C, "M", "كم"), + (0xFC3D, "M", "كى"), + (0xFC3E, "M", "كي"), + (0xFC3F, "M", "لج"), + (0xFC40, "M", "لح"), + (0xFC41, "M", "لخ"), + (0xFC42, "M", "لم"), + (0xFC43, "M", "لى"), + (0xFC44, "M", "لي"), + (0xFC45, "M", "مج"), + (0xFC46, "M", "مح"), + (0xFC47, "M", "مخ"), + (0xFC48, "M", "مم"), + (0xFC49, "M", "مى"), + (0xFC4A, "M", "مي"), + (0xFC4B, "M", "نج"), + (0xFC4C, "M", "نح"), + (0xFC4D, "M", "نخ"), + (0xFC4E, "M", "نم"), + (0xFC4F, "M", "نى"), + (0xFC50, "M", "ني"), + (0xFC51, "M", "هج"), + (0xFC52, "M", "هم"), + (0xFC53, "M", "هى"), + (0xFC54, "M", "هي"), + (0xFC55, "M", "يج"), + (0xFC56, "M", "يح"), + (0xFC57, "M", "يخ"), + (0xFC58, "M", "يم"), + (0xFC59, "M", "يى"), + (0xFC5A, "M", "يي"), + ] + + +def _seg_46() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xFC5B, "M", "ذٰ"), + (0xFC5C, "M", "رٰ"), + (0xFC5D, "M", "ىٰ"), + (0xFC5E, "3", " ٌّ"), + (0xFC5F, "3", " ٍّ"), + (0xFC60, "3", " َّ"), + (0xFC61, "3", " ُّ"), + (0xFC62, "3", " ِّ"), + (0xFC63, "3", " ّٰ"), + (0xFC64, "M", "ئر"), + (0xFC65, "M", "ئز"), + (0xFC66, "M", "ئم"), + (0xFC67, "M", "ئن"), + (0xFC68, "M", "ئى"), + (0xFC69, "M", "ئي"), + (0xFC6A, "M", "بر"), + (0xFC6B, "M", "بز"), + (0xFC6C, "M", "بم"), + (0xFC6D, "M", "بن"), + (0xFC6E, "M", "بى"), + (0xFC6F, "M", "بي"), + (0xFC70, "M", "تر"), + (0xFC71, "M", "تز"), + (0xFC72, "M", "تم"), + (0xFC73, "M", "تن"), + (0xFC74, "M", "تى"), + (0xFC75, "M", "تي"), + (0xFC76, "M", "ثر"), + (0xFC77, "M", "ثز"), + (0xFC78, "M", "ثم"), + (0xFC79, "M", "ثن"), + (0xFC7A, "M", "ثى"), + (0xFC7B, "M", "ثي"), + (0xFC7C, "M", "فى"), + (0xFC7D, "M", "في"), + (0xFC7E, "M", "قى"), + (0xFC7F, "M", "قي"), + (0xFC80, "M", "كا"), + (0xFC81, "M", "كل"), + (0xFC82, "M", "كم"), + (0xFC83, "M", "كى"), + (0xFC84, "M", "كي"), + (0xFC85, "M", "لم"), + (0xFC86, "M", "لى"), + (0xFC87, "M", "لي"), + (0xFC88, "M", "ما"), + (0xFC89, "M", "مم"), + (0xFC8A, "M", "نر"), + (0xFC8B, "M", "نز"), + (0xFC8C, "M", "نم"), + (0xFC8D, "M", "نن"), + (0xFC8E, "M", "نى"), + (0xFC8F, "M", "ني"), + (0xFC90, "M", "ىٰ"), + (0xFC91, "M", "ير"), + (0xFC92, "M", "يز"), + (0xFC93, "M", "يم"), + (0xFC94, "M", "ين"), + (0xFC95, "M", "يى"), + (0xFC96, "M", "يي"), + (0xFC97, "M", "ئج"), + (0xFC98, "M", "ئح"), + (0xFC99, "M", "ئخ"), + (0xFC9A, "M", "ئم"), + (0xFC9B, "M", "ئه"), + (0xFC9C, "M", "بج"), + (0xFC9D, "M", "بح"), + (0xFC9E, "M", "بخ"), + (0xFC9F, "M", "بم"), + (0xFCA0, "M", "به"), + (0xFCA1, "M", "تج"), + (0xFCA2, "M", "تح"), + (0xFCA3, "M", "تخ"), + (0xFCA4, "M", "تم"), + (0xFCA5, "M", "ته"), + (0xFCA6, "M", "ثم"), + (0xFCA7, "M", "جح"), + (0xFCA8, "M", "جم"), + (0xFCA9, "M", "حج"), + (0xFCAA, "M", "حم"), + (0xFCAB, "M", "خج"), + (0xFCAC, "M", "خم"), + (0xFCAD, "M", "سج"), + (0xFCAE, "M", "سح"), + (0xFCAF, "M", "سخ"), + (0xFCB0, "M", "سم"), + (0xFCB1, "M", "صح"), + (0xFCB2, "M", "صخ"), + (0xFCB3, "M", "صم"), + (0xFCB4, "M", "ضج"), + (0xFCB5, "M", "ضح"), + (0xFCB6, "M", "ضخ"), + (0xFCB7, "M", "ضم"), + (0xFCB8, "M", "طح"), + (0xFCB9, "M", "ظم"), + (0xFCBA, "M", "عج"), + (0xFCBB, "M", "عم"), + (0xFCBC, "M", "غج"), + (0xFCBD, "M", "غم"), + (0xFCBE, "M", "فج"), + ] + + +def _seg_47() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xFCBF, "M", "فح"), + (0xFCC0, "M", "فخ"), + (0xFCC1, "M", "فم"), + (0xFCC2, "M", "قح"), + (0xFCC3, "M", "قم"), + (0xFCC4, "M", "كج"), + (0xFCC5, "M", "كح"), + (0xFCC6, "M", "كخ"), + (0xFCC7, "M", "كل"), + (0xFCC8, "M", "كم"), + (0xFCC9, "M", "لج"), + (0xFCCA, "M", "لح"), + (0xFCCB, "M", "لخ"), + (0xFCCC, "M", "لم"), + (0xFCCD, "M", "له"), + (0xFCCE, "M", "مج"), + (0xFCCF, "M", "مح"), + (0xFCD0, "M", "مخ"), + (0xFCD1, "M", "مم"), + (0xFCD2, "M", "نج"), + (0xFCD3, "M", "نح"), + (0xFCD4, "M", "نخ"), + (0xFCD5, "M", "نم"), + (0xFCD6, "M", "نه"), + (0xFCD7, "M", "هج"), + (0xFCD8, "M", "هم"), + (0xFCD9, "M", "هٰ"), + (0xFCDA, "M", "يج"), + (0xFCDB, "M", "يح"), + (0xFCDC, "M", "يخ"), + (0xFCDD, "M", "يم"), + (0xFCDE, "M", "يه"), + (0xFCDF, "M", "ئم"), + (0xFCE0, "M", "ئه"), + (0xFCE1, "M", "بم"), + (0xFCE2, "M", "به"), + (0xFCE3, "M", "تم"), + (0xFCE4, "M", "ته"), + (0xFCE5, "M", "ثم"), + (0xFCE6, "M", "ثه"), + (0xFCE7, "M", "سم"), + (0xFCE8, "M", "سه"), + (0xFCE9, "M", "شم"), + (0xFCEA, "M", "شه"), + (0xFCEB, "M", "كل"), + (0xFCEC, "M", "كم"), + (0xFCED, "M", "لم"), + (0xFCEE, "M", "نم"), + (0xFCEF, "M", "نه"), + (0xFCF0, "M", "يم"), + (0xFCF1, "M", "يه"), + (0xFCF2, "M", "ـَّ"), + (0xFCF3, "M", "ـُّ"), + (0xFCF4, "M", "ـِّ"), + (0xFCF5, "M", "طى"), + (0xFCF6, "M", "طي"), + (0xFCF7, "M", "عى"), + (0xFCF8, "M", "عي"), + (0xFCF9, "M", "غى"), + (0xFCFA, "M", "غي"), + (0xFCFB, "M", "سى"), + (0xFCFC, "M", "سي"), + (0xFCFD, "M", "شى"), + (0xFCFE, "M", "شي"), + (0xFCFF, "M", "حى"), + (0xFD00, "M", "حي"), + (0xFD01, "M", "جى"), + (0xFD02, "M", "جي"), + (0xFD03, "M", "خى"), + (0xFD04, "M", "خي"), + (0xFD05, "M", "صى"), + (0xFD06, "M", "صي"), + (0xFD07, "M", "ضى"), + (0xFD08, "M", "ضي"), + (0xFD09, "M", "شج"), + (0xFD0A, "M", "شح"), + (0xFD0B, "M", "شخ"), + (0xFD0C, "M", "شم"), + (0xFD0D, "M", "شر"), + (0xFD0E, "M", "سر"), + (0xFD0F, "M", "صر"), + (0xFD10, "M", "ضر"), + (0xFD11, "M", "طى"), + (0xFD12, "M", "طي"), + (0xFD13, "M", "عى"), + (0xFD14, "M", "عي"), + (0xFD15, "M", "غى"), + (0xFD16, "M", "غي"), + (0xFD17, "M", "سى"), + (0xFD18, "M", "سي"), + (0xFD19, "M", "شى"), + (0xFD1A, "M", "شي"), + (0xFD1B, "M", "حى"), + (0xFD1C, "M", "حي"), + (0xFD1D, "M", "جى"), + (0xFD1E, "M", "جي"), + (0xFD1F, "M", "خى"), + (0xFD20, "M", "خي"), + (0xFD21, "M", "صى"), + (0xFD22, "M", "صي"), + ] + + +def _seg_48() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xFD23, "M", "ضى"), + (0xFD24, "M", "ضي"), + (0xFD25, "M", "شج"), + (0xFD26, "M", "شح"), + (0xFD27, "M", "شخ"), + (0xFD28, "M", "شم"), + (0xFD29, "M", "شر"), + (0xFD2A, "M", "سر"), + (0xFD2B, "M", "صر"), + (0xFD2C, "M", "ضر"), + (0xFD2D, "M", "شج"), + (0xFD2E, "M", "شح"), + (0xFD2F, "M", "شخ"), + (0xFD30, "M", "شم"), + (0xFD31, "M", "سه"), + (0xFD32, "M", "شه"), + (0xFD33, "M", "طم"), + (0xFD34, "M", "سج"), + (0xFD35, "M", "سح"), + (0xFD36, "M", "سخ"), + (0xFD37, "M", "شج"), + (0xFD38, "M", "شح"), + (0xFD39, "M", "شخ"), + (0xFD3A, "M", "طم"), + (0xFD3B, "M", "ظم"), + (0xFD3C, "M", "اً"), + (0xFD3E, "V"), + (0xFD50, "M", "تجم"), + (0xFD51, "M", "تحج"), + (0xFD53, "M", "تحم"), + (0xFD54, "M", "تخم"), + (0xFD55, "M", "تمج"), + (0xFD56, "M", "تمح"), + (0xFD57, "M", "تمخ"), + (0xFD58, "M", "جمح"), + (0xFD5A, "M", "حمي"), + (0xFD5B, "M", "حمى"), + (0xFD5C, "M", "سحج"), + (0xFD5D, "M", "سجح"), + (0xFD5E, "M", "سجى"), + (0xFD5F, "M", "سمح"), + (0xFD61, "M", "سمج"), + (0xFD62, "M", "سمم"), + (0xFD64, "M", "صحح"), + (0xFD66, "M", "صمم"), + (0xFD67, "M", "شحم"), + (0xFD69, "M", "شجي"), + (0xFD6A, "M", "شمخ"), + (0xFD6C, "M", "شمم"), + (0xFD6E, "M", "ضحى"), + (0xFD6F, "M", "ضخم"), + (0xFD71, "M", "طمح"), + (0xFD73, "M", "طمم"), + (0xFD74, "M", "طمي"), + (0xFD75, "M", "عجم"), + (0xFD76, "M", "عمم"), + (0xFD78, "M", "عمى"), + (0xFD79, "M", "غمم"), + (0xFD7A, "M", "غمي"), + (0xFD7B, "M", "غمى"), + (0xFD7C, "M", "فخم"), + (0xFD7E, "M", "قمح"), + (0xFD7F, "M", "قمم"), + (0xFD80, "M", "لحم"), + (0xFD81, "M", "لحي"), + (0xFD82, "M", "لحى"), + (0xFD83, "M", "لجج"), + (0xFD85, "M", "لخم"), + (0xFD87, "M", "لمح"), + (0xFD89, "M", "محج"), + (0xFD8A, "M", "محم"), + (0xFD8B, "M", "محي"), + (0xFD8C, "M", "مجح"), + (0xFD8D, "M", "مجم"), + (0xFD8E, "M", "مخج"), + (0xFD8F, "M", "مخم"), + (0xFD90, "X"), + (0xFD92, "M", "مجخ"), + (0xFD93, "M", "همج"), + (0xFD94, "M", "همم"), + (0xFD95, "M", "نحم"), + (0xFD96, "M", "نحى"), + (0xFD97, "M", "نجم"), + (0xFD99, "M", "نجى"), + (0xFD9A, "M", "نمي"), + (0xFD9B, "M", "نمى"), + (0xFD9C, "M", "يمم"), + (0xFD9E, "M", "بخي"), + (0xFD9F, "M", "تجي"), + (0xFDA0, "M", "تجى"), + (0xFDA1, "M", "تخي"), + (0xFDA2, "M", "تخى"), + (0xFDA3, "M", "تمي"), + (0xFDA4, "M", "تمى"), + (0xFDA5, "M", "جمي"), + (0xFDA6, "M", "جحى"), + (0xFDA7, "M", "جمى"), + (0xFDA8, "M", "سخى"), + (0xFDA9, "M", "صحي"), + (0xFDAA, "M", "شحي"), + ] + + +def _seg_49() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xFDAB, "M", "ضحي"), + (0xFDAC, "M", "لجي"), + (0xFDAD, "M", "لمي"), + (0xFDAE, "M", "يحي"), + (0xFDAF, "M", "يجي"), + (0xFDB0, "M", "يمي"), + (0xFDB1, "M", "ممي"), + (0xFDB2, "M", "قمي"), + (0xFDB3, "M", "نحي"), + (0xFDB4, "M", "قمح"), + (0xFDB5, "M", "لحم"), + (0xFDB6, "M", "عمي"), + (0xFDB7, "M", "كمي"), + (0xFDB8, "M", "نجح"), + (0xFDB9, "M", "مخي"), + (0xFDBA, "M", "لجم"), + (0xFDBB, "M", "كمم"), + (0xFDBC, "M", "لجم"), + (0xFDBD, "M", "نجح"), + (0xFDBE, "M", "جحي"), + (0xFDBF, "M", "حجي"), + (0xFDC0, "M", "مجي"), + (0xFDC1, "M", "فمي"), + (0xFDC2, "M", "بحي"), + (0xFDC3, "M", "كمم"), + (0xFDC4, "M", "عجم"), + (0xFDC5, "M", "صمم"), + (0xFDC6, "M", "سخي"), + (0xFDC7, "M", "نجي"), + (0xFDC8, "X"), + (0xFDCF, "V"), + (0xFDD0, "X"), + (0xFDF0, "M", "صلے"), + (0xFDF1, "M", "قلے"), + (0xFDF2, "M", "الله"), + (0xFDF3, "M", "اكبر"), + (0xFDF4, "M", "محمد"), + (0xFDF5, "M", "صلعم"), + (0xFDF6, "M", "رسول"), + (0xFDF7, "M", "عليه"), + (0xFDF8, "M", "وسلم"), + (0xFDF9, "M", "صلى"), + (0xFDFA, "3", "صلى الله عليه وسلم"), + (0xFDFB, "3", "جل جلاله"), + (0xFDFC, "M", "ریال"), + (0xFDFD, "V"), + (0xFE00, "I"), + (0xFE10, "3", ","), + (0xFE11, "M", "、"), + (0xFE12, "X"), + (0xFE13, "3", ":"), + (0xFE14, "3", ";"), + (0xFE15, "3", "!"), + (0xFE16, "3", "?"), + (0xFE17, "M", "〖"), + (0xFE18, "M", "〗"), + (0xFE19, "X"), + (0xFE20, "V"), + (0xFE30, "X"), + (0xFE31, "M", "—"), + (0xFE32, "M", "–"), + (0xFE33, "3", "_"), + (0xFE35, "3", "("), + (0xFE36, "3", ")"), + (0xFE37, "3", "{"), + (0xFE38, "3", "}"), + (0xFE39, "M", "〔"), + (0xFE3A, "M", "〕"), + (0xFE3B, "M", "【"), + (0xFE3C, "M", "】"), + (0xFE3D, "M", "《"), + (0xFE3E, "M", "》"), + (0xFE3F, "M", "〈"), + (0xFE40, "M", "〉"), + (0xFE41, "M", "「"), + (0xFE42, "M", "」"), + (0xFE43, "M", "『"), + (0xFE44, "M", "』"), + (0xFE45, "V"), + (0xFE47, "3", "["), + (0xFE48, "3", "]"), + (0xFE49, "3", " ̅"), + (0xFE4D, "3", "_"), + (0xFE50, "3", ","), + (0xFE51, "M", "、"), + (0xFE52, "X"), + (0xFE54, "3", ";"), + (0xFE55, "3", ":"), + (0xFE56, "3", "?"), + (0xFE57, "3", "!"), + (0xFE58, "M", "—"), + (0xFE59, "3", "("), + (0xFE5A, "3", ")"), + (0xFE5B, "3", "{"), + (0xFE5C, "3", "}"), + (0xFE5D, "M", "〔"), + (0xFE5E, "M", "〕"), + (0xFE5F, "3", "#"), + (0xFE60, "3", "&"), + (0xFE61, "3", "*"), + ] + + +def _seg_50() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xFE62, "3", "+"), + (0xFE63, "M", "-"), + (0xFE64, "3", "<"), + (0xFE65, "3", ">"), + (0xFE66, "3", "="), + (0xFE67, "X"), + (0xFE68, "3", "\\"), + (0xFE69, "3", "$"), + (0xFE6A, "3", "%"), + (0xFE6B, "3", "@"), + (0xFE6C, "X"), + (0xFE70, "3", " ً"), + (0xFE71, "M", "ـً"), + (0xFE72, "3", " ٌ"), + (0xFE73, "V"), + (0xFE74, "3", " ٍ"), + (0xFE75, "X"), + (0xFE76, "3", " َ"), + (0xFE77, "M", "ـَ"), + (0xFE78, "3", " ُ"), + (0xFE79, "M", "ـُ"), + (0xFE7A, "3", " ِ"), + (0xFE7B, "M", "ـِ"), + (0xFE7C, "3", " ّ"), + (0xFE7D, "M", "ـّ"), + (0xFE7E, "3", " ْ"), + (0xFE7F, "M", "ـْ"), + (0xFE80, "M", "ء"), + (0xFE81, "M", "آ"), + (0xFE83, "M", "أ"), + (0xFE85, "M", "ؤ"), + (0xFE87, "M", "إ"), + (0xFE89, "M", "ئ"), + (0xFE8D, "M", "ا"), + (0xFE8F, "M", "ب"), + (0xFE93, "M", "ة"), + (0xFE95, "M", "ت"), + (0xFE99, "M", "ث"), + (0xFE9D, "M", "ج"), + (0xFEA1, "M", "ح"), + (0xFEA5, "M", "خ"), + (0xFEA9, "M", "د"), + (0xFEAB, "M", "ذ"), + (0xFEAD, "M", "ر"), + (0xFEAF, "M", "ز"), + (0xFEB1, "M", "س"), + (0xFEB5, "M", "ش"), + (0xFEB9, "M", "ص"), + (0xFEBD, "M", "ض"), + (0xFEC1, "M", "ط"), + (0xFEC5, "M", "ظ"), + (0xFEC9, "M", "ع"), + (0xFECD, "M", "غ"), + (0xFED1, "M", "ف"), + (0xFED5, "M", "ق"), + (0xFED9, "M", "ك"), + (0xFEDD, "M", "ل"), + (0xFEE1, "M", "م"), + (0xFEE5, "M", "ن"), + (0xFEE9, "M", "ه"), + (0xFEED, "M", "و"), + (0xFEEF, "M", "ى"), + (0xFEF1, "M", "ي"), + (0xFEF5, "M", "لآ"), + (0xFEF7, "M", "لأ"), + (0xFEF9, "M", "لإ"), + (0xFEFB, "M", "لا"), + (0xFEFD, "X"), + (0xFEFF, "I"), + (0xFF00, "X"), + (0xFF01, "3", "!"), + (0xFF02, "3", '"'), + (0xFF03, "3", "#"), + (0xFF04, "3", "$"), + (0xFF05, "3", "%"), + (0xFF06, "3", "&"), + (0xFF07, "3", "'"), + (0xFF08, "3", "("), + (0xFF09, "3", ")"), + (0xFF0A, "3", "*"), + (0xFF0B, "3", "+"), + (0xFF0C, "3", ","), + (0xFF0D, "M", "-"), + (0xFF0E, "M", "."), + (0xFF0F, "3", "/"), + (0xFF10, "M", "0"), + (0xFF11, "M", "1"), + (0xFF12, "M", "2"), + (0xFF13, "M", "3"), + (0xFF14, "M", "4"), + (0xFF15, "M", "5"), + (0xFF16, "M", "6"), + (0xFF17, "M", "7"), + (0xFF18, "M", "8"), + (0xFF19, "M", "9"), + (0xFF1A, "3", ":"), + (0xFF1B, "3", ";"), + (0xFF1C, "3", "<"), + (0xFF1D, "3", "="), + (0xFF1E, "3", ">"), + ] + + +def _seg_51() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xFF1F, "3", "?"), + (0xFF20, "3", "@"), + (0xFF21, "M", "a"), + (0xFF22, "M", "b"), + (0xFF23, "M", "c"), + (0xFF24, "M", "d"), + (0xFF25, "M", "e"), + (0xFF26, "M", "f"), + (0xFF27, "M", "g"), + (0xFF28, "M", "h"), + (0xFF29, "M", "i"), + (0xFF2A, "M", "j"), + (0xFF2B, "M", "k"), + (0xFF2C, "M", "l"), + (0xFF2D, "M", "m"), + (0xFF2E, "M", "n"), + (0xFF2F, "M", "o"), + (0xFF30, "M", "p"), + (0xFF31, "M", "q"), + (0xFF32, "M", "r"), + (0xFF33, "M", "s"), + (0xFF34, "M", "t"), + (0xFF35, "M", "u"), + (0xFF36, "M", "v"), + (0xFF37, "M", "w"), + (0xFF38, "M", "x"), + (0xFF39, "M", "y"), + (0xFF3A, "M", "z"), + (0xFF3B, "3", "["), + (0xFF3C, "3", "\\"), + (0xFF3D, "3", "]"), + (0xFF3E, "3", "^"), + (0xFF3F, "3", "_"), + (0xFF40, "3", "`"), + (0xFF41, "M", "a"), + (0xFF42, "M", "b"), + (0xFF43, "M", "c"), + (0xFF44, "M", "d"), + (0xFF45, "M", "e"), + (0xFF46, "M", "f"), + (0xFF47, "M", "g"), + (0xFF48, "M", "h"), + (0xFF49, "M", "i"), + (0xFF4A, "M", "j"), + (0xFF4B, "M", "k"), + (0xFF4C, "M", "l"), + (0xFF4D, "M", "m"), + (0xFF4E, "M", "n"), + (0xFF4F, "M", "o"), + (0xFF50, "M", "p"), + (0xFF51, "M", "q"), + (0xFF52, "M", "r"), + (0xFF53, "M", "s"), + (0xFF54, "M", "t"), + (0xFF55, "M", "u"), + (0xFF56, "M", "v"), + (0xFF57, "M", "w"), + (0xFF58, "M", "x"), + (0xFF59, "M", "y"), + (0xFF5A, "M", "z"), + (0xFF5B, "3", "{"), + (0xFF5C, "3", "|"), + (0xFF5D, "3", "}"), + (0xFF5E, "3", "~"), + (0xFF5F, "M", "⦅"), + (0xFF60, "M", "⦆"), + (0xFF61, "M", "."), + (0xFF62, "M", "「"), + (0xFF63, "M", "」"), + (0xFF64, "M", "、"), + (0xFF65, "M", "・"), + (0xFF66, "M", "ヲ"), + (0xFF67, "M", "ァ"), + (0xFF68, "M", "ィ"), + (0xFF69, "M", "ゥ"), + (0xFF6A, "M", "ェ"), + (0xFF6B, "M", "ォ"), + (0xFF6C, "M", "ャ"), + (0xFF6D, "M", "ュ"), + (0xFF6E, "M", "ョ"), + (0xFF6F, "M", "ッ"), + (0xFF70, "M", "ー"), + (0xFF71, "M", "ア"), + (0xFF72, "M", "イ"), + (0xFF73, "M", "ウ"), + (0xFF74, "M", "エ"), + (0xFF75, "M", "オ"), + (0xFF76, "M", "カ"), + (0xFF77, "M", "キ"), + (0xFF78, "M", "ク"), + (0xFF79, "M", "ケ"), + (0xFF7A, "M", "コ"), + (0xFF7B, "M", "サ"), + (0xFF7C, "M", "シ"), + (0xFF7D, "M", "ス"), + (0xFF7E, "M", "セ"), + (0xFF7F, "M", "ソ"), + (0xFF80, "M", "タ"), + (0xFF81, "M", "チ"), + (0xFF82, "M", "ツ"), + ] + + +def _seg_52() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xFF83, "M", "テ"), + (0xFF84, "M", "ト"), + (0xFF85, "M", "ナ"), + (0xFF86, "M", "ニ"), + (0xFF87, "M", "ヌ"), + (0xFF88, "M", "ネ"), + (0xFF89, "M", "ノ"), + (0xFF8A, "M", "ハ"), + (0xFF8B, "M", "ヒ"), + (0xFF8C, "M", "フ"), + (0xFF8D, "M", "ヘ"), + (0xFF8E, "M", "ホ"), + (0xFF8F, "M", "マ"), + (0xFF90, "M", "ミ"), + (0xFF91, "M", "ム"), + (0xFF92, "M", "メ"), + (0xFF93, "M", "モ"), + (0xFF94, "M", "ヤ"), + (0xFF95, "M", "ユ"), + (0xFF96, "M", "ヨ"), + (0xFF97, "M", "ラ"), + (0xFF98, "M", "リ"), + (0xFF99, "M", "ル"), + (0xFF9A, "M", "レ"), + (0xFF9B, "M", "ロ"), + (0xFF9C, "M", "ワ"), + (0xFF9D, "M", "ン"), + (0xFF9E, "M", "゙"), + (0xFF9F, "M", "゚"), + (0xFFA0, "X"), + (0xFFA1, "M", "ᄀ"), + (0xFFA2, "M", "ᄁ"), + (0xFFA3, "M", "ᆪ"), + (0xFFA4, "M", "ᄂ"), + (0xFFA5, "M", "ᆬ"), + (0xFFA6, "M", "ᆭ"), + (0xFFA7, "M", "ᄃ"), + (0xFFA8, "M", "ᄄ"), + (0xFFA9, "M", "ᄅ"), + (0xFFAA, "M", "ᆰ"), + (0xFFAB, "M", "ᆱ"), + (0xFFAC, "M", "ᆲ"), + (0xFFAD, "M", "ᆳ"), + (0xFFAE, "M", "ᆴ"), + (0xFFAF, "M", "ᆵ"), + (0xFFB0, "M", "ᄚ"), + (0xFFB1, "M", "ᄆ"), + (0xFFB2, "M", "ᄇ"), + (0xFFB3, "M", "ᄈ"), + (0xFFB4, "M", "ᄡ"), + (0xFFB5, "M", "ᄉ"), + (0xFFB6, "M", "ᄊ"), + (0xFFB7, "M", "ᄋ"), + (0xFFB8, "M", "ᄌ"), + (0xFFB9, "M", "ᄍ"), + (0xFFBA, "M", "ᄎ"), + (0xFFBB, "M", "ᄏ"), + (0xFFBC, "M", "ᄐ"), + (0xFFBD, "M", "ᄑ"), + (0xFFBE, "M", "ᄒ"), + (0xFFBF, "X"), + (0xFFC2, "M", "ᅡ"), + (0xFFC3, "M", "ᅢ"), + (0xFFC4, "M", "ᅣ"), + (0xFFC5, "M", "ᅤ"), + (0xFFC6, "M", "ᅥ"), + (0xFFC7, "M", "ᅦ"), + (0xFFC8, "X"), + (0xFFCA, "M", "ᅧ"), + (0xFFCB, "M", "ᅨ"), + (0xFFCC, "M", "ᅩ"), + (0xFFCD, "M", "ᅪ"), + (0xFFCE, "M", "ᅫ"), + (0xFFCF, "M", "ᅬ"), + (0xFFD0, "X"), + (0xFFD2, "M", "ᅭ"), + (0xFFD3, "M", "ᅮ"), + (0xFFD4, "M", "ᅯ"), + (0xFFD5, "M", "ᅰ"), + (0xFFD6, "M", "ᅱ"), + (0xFFD7, "M", "ᅲ"), + (0xFFD8, "X"), + (0xFFDA, "M", "ᅳ"), + (0xFFDB, "M", "ᅴ"), + (0xFFDC, "M", "ᅵ"), + (0xFFDD, "X"), + (0xFFE0, "M", "¢"), + (0xFFE1, "M", "£"), + (0xFFE2, "M", "¬"), + (0xFFE3, "3", " ̄"), + (0xFFE4, "M", "¦"), + (0xFFE5, "M", "¥"), + (0xFFE6, "M", "₩"), + (0xFFE7, "X"), + (0xFFE8, "M", "│"), + (0xFFE9, "M", "←"), + (0xFFEA, "M", "↑"), + (0xFFEB, "M", "→"), + (0xFFEC, "M", "↓"), + (0xFFED, "M", "■"), + ] + + +def _seg_53() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0xFFEE, "M", "○"), + (0xFFEF, "X"), + (0x10000, "V"), + (0x1000C, "X"), + (0x1000D, "V"), + (0x10027, "X"), + (0x10028, "V"), + (0x1003B, "X"), + (0x1003C, "V"), + (0x1003E, "X"), + (0x1003F, "V"), + (0x1004E, "X"), + (0x10050, "V"), + (0x1005E, "X"), + (0x10080, "V"), + (0x100FB, "X"), + (0x10100, "V"), + (0x10103, "X"), + (0x10107, "V"), + (0x10134, "X"), + (0x10137, "V"), + (0x1018F, "X"), + (0x10190, "V"), + (0x1019D, "X"), + (0x101A0, "V"), + (0x101A1, "X"), + (0x101D0, "V"), + (0x101FE, "X"), + (0x10280, "V"), + (0x1029D, "X"), + (0x102A0, "V"), + (0x102D1, "X"), + (0x102E0, "V"), + (0x102FC, "X"), + (0x10300, "V"), + (0x10324, "X"), + (0x1032D, "V"), + (0x1034B, "X"), + (0x10350, "V"), + (0x1037B, "X"), + (0x10380, "V"), + (0x1039E, "X"), + (0x1039F, "V"), + (0x103C4, "X"), + (0x103C8, "V"), + (0x103D6, "X"), + (0x10400, "M", "𐐨"), + (0x10401, "M", "𐐩"), + (0x10402, "M", "𐐪"), + (0x10403, "M", "𐐫"), + (0x10404, "M", "𐐬"), + (0x10405, "M", "𐐭"), + (0x10406, "M", "𐐮"), + (0x10407, "M", "𐐯"), + (0x10408, "M", "𐐰"), + (0x10409, "M", "𐐱"), + (0x1040A, "M", "𐐲"), + (0x1040B, "M", "𐐳"), + (0x1040C, "M", "𐐴"), + (0x1040D, "M", "𐐵"), + (0x1040E, "M", "𐐶"), + (0x1040F, "M", "𐐷"), + (0x10410, "M", "𐐸"), + (0x10411, "M", "𐐹"), + (0x10412, "M", "𐐺"), + (0x10413, "M", "𐐻"), + (0x10414, "M", "𐐼"), + (0x10415, "M", "𐐽"), + (0x10416, "M", "𐐾"), + (0x10417, "M", "𐐿"), + (0x10418, "M", "𐑀"), + (0x10419, "M", "𐑁"), + (0x1041A, "M", "𐑂"), + (0x1041B, "M", "𐑃"), + (0x1041C, "M", "𐑄"), + (0x1041D, "M", "𐑅"), + (0x1041E, "M", "𐑆"), + (0x1041F, "M", "𐑇"), + (0x10420, "M", "𐑈"), + (0x10421, "M", "𐑉"), + (0x10422, "M", "𐑊"), + (0x10423, "M", "𐑋"), + (0x10424, "M", "𐑌"), + (0x10425, "M", "𐑍"), + (0x10426, "M", "𐑎"), + (0x10427, "M", "𐑏"), + (0x10428, "V"), + (0x1049E, "X"), + (0x104A0, "V"), + (0x104AA, "X"), + (0x104B0, "M", "𐓘"), + (0x104B1, "M", "𐓙"), + (0x104B2, "M", "𐓚"), + (0x104B3, "M", "𐓛"), + (0x104B4, "M", "𐓜"), + (0x104B5, "M", "𐓝"), + (0x104B6, "M", "𐓞"), + (0x104B7, "M", "𐓟"), + (0x104B8, "M", "𐓠"), + (0x104B9, "M", "𐓡"), + ] + + +def _seg_54() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x104BA, "M", "𐓢"), + (0x104BB, "M", "𐓣"), + (0x104BC, "M", "𐓤"), + (0x104BD, "M", "𐓥"), + (0x104BE, "M", "𐓦"), + (0x104BF, "M", "𐓧"), + (0x104C0, "M", "𐓨"), + (0x104C1, "M", "𐓩"), + (0x104C2, "M", "𐓪"), + (0x104C3, "M", "𐓫"), + (0x104C4, "M", "𐓬"), + (0x104C5, "M", "𐓭"), + (0x104C6, "M", "𐓮"), + (0x104C7, "M", "𐓯"), + (0x104C8, "M", "𐓰"), + (0x104C9, "M", "𐓱"), + (0x104CA, "M", "𐓲"), + (0x104CB, "M", "𐓳"), + (0x104CC, "M", "𐓴"), + (0x104CD, "M", "𐓵"), + (0x104CE, "M", "𐓶"), + (0x104CF, "M", "𐓷"), + (0x104D0, "M", "𐓸"), + (0x104D1, "M", "𐓹"), + (0x104D2, "M", "𐓺"), + (0x104D3, "M", "𐓻"), + (0x104D4, "X"), + (0x104D8, "V"), + (0x104FC, "X"), + (0x10500, "V"), + (0x10528, "X"), + (0x10530, "V"), + (0x10564, "X"), + (0x1056F, "V"), + (0x10570, "M", "𐖗"), + (0x10571, "M", "𐖘"), + (0x10572, "M", "𐖙"), + (0x10573, "M", "𐖚"), + (0x10574, "M", "𐖛"), + (0x10575, "M", "𐖜"), + (0x10576, "M", "𐖝"), + (0x10577, "M", "𐖞"), + (0x10578, "M", "𐖟"), + (0x10579, "M", "𐖠"), + (0x1057A, "M", "𐖡"), + (0x1057B, "X"), + (0x1057C, "M", "𐖣"), + (0x1057D, "M", "𐖤"), + (0x1057E, "M", "𐖥"), + (0x1057F, "M", "𐖦"), + (0x10580, "M", "𐖧"), + (0x10581, "M", "𐖨"), + (0x10582, "M", "𐖩"), + (0x10583, "M", "𐖪"), + (0x10584, "M", "𐖫"), + (0x10585, "M", "𐖬"), + (0x10586, "M", "𐖭"), + (0x10587, "M", "𐖮"), + (0x10588, "M", "𐖯"), + (0x10589, "M", "𐖰"), + (0x1058A, "M", "𐖱"), + (0x1058B, "X"), + (0x1058C, "M", "𐖳"), + (0x1058D, "M", "𐖴"), + (0x1058E, "M", "𐖵"), + (0x1058F, "M", "𐖶"), + (0x10590, "M", "𐖷"), + (0x10591, "M", "𐖸"), + (0x10592, "M", "𐖹"), + (0x10593, "X"), + (0x10594, "M", "𐖻"), + (0x10595, "M", "𐖼"), + (0x10596, "X"), + (0x10597, "V"), + (0x105A2, "X"), + (0x105A3, "V"), + (0x105B2, "X"), + (0x105B3, "V"), + (0x105BA, "X"), + (0x105BB, "V"), + (0x105BD, "X"), + (0x10600, "V"), + (0x10737, "X"), + (0x10740, "V"), + (0x10756, "X"), + (0x10760, "V"), + (0x10768, "X"), + (0x10780, "V"), + (0x10781, "M", "ː"), + (0x10782, "M", "ˑ"), + (0x10783, "M", "æ"), + (0x10784, "M", "ʙ"), + (0x10785, "M", "ɓ"), + (0x10786, "X"), + (0x10787, "M", "ʣ"), + (0x10788, "M", "ꭦ"), + (0x10789, "M", "ʥ"), + (0x1078A, "M", "ʤ"), + (0x1078B, "M", "ɖ"), + (0x1078C, "M", "ɗ"), + ] + + +def _seg_55() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1078D, "M", "ᶑ"), + (0x1078E, "M", "ɘ"), + (0x1078F, "M", "ɞ"), + (0x10790, "M", "ʩ"), + (0x10791, "M", "ɤ"), + (0x10792, "M", "ɢ"), + (0x10793, "M", "ɠ"), + (0x10794, "M", "ʛ"), + (0x10795, "M", "ħ"), + (0x10796, "M", "ʜ"), + (0x10797, "M", "ɧ"), + (0x10798, "M", "ʄ"), + (0x10799, "M", "ʪ"), + (0x1079A, "M", "ʫ"), + (0x1079B, "M", "ɬ"), + (0x1079C, "M", "𝼄"), + (0x1079D, "M", "ꞎ"), + (0x1079E, "M", "ɮ"), + (0x1079F, "M", "𝼅"), + (0x107A0, "M", "ʎ"), + (0x107A1, "M", "𝼆"), + (0x107A2, "M", "ø"), + (0x107A3, "M", "ɶ"), + (0x107A4, "M", "ɷ"), + (0x107A5, "M", "q"), + (0x107A6, "M", "ɺ"), + (0x107A7, "M", "𝼈"), + (0x107A8, "M", "ɽ"), + (0x107A9, "M", "ɾ"), + (0x107AA, "M", "ʀ"), + (0x107AB, "M", "ʨ"), + (0x107AC, "M", "ʦ"), + (0x107AD, "M", "ꭧ"), + (0x107AE, "M", "ʧ"), + (0x107AF, "M", "ʈ"), + (0x107B0, "M", "ⱱ"), + (0x107B1, "X"), + (0x107B2, "M", "ʏ"), + (0x107B3, "M", "ʡ"), + (0x107B4, "M", "ʢ"), + (0x107B5, "M", "ʘ"), + (0x107B6, "M", "ǀ"), + (0x107B7, "M", "ǁ"), + (0x107B8, "M", "ǂ"), + (0x107B9, "M", "𝼊"), + (0x107BA, "M", "𝼞"), + (0x107BB, "X"), + (0x10800, "V"), + (0x10806, "X"), + (0x10808, "V"), + (0x10809, "X"), + (0x1080A, "V"), + (0x10836, "X"), + (0x10837, "V"), + (0x10839, "X"), + (0x1083C, "V"), + (0x1083D, "X"), + (0x1083F, "V"), + (0x10856, "X"), + (0x10857, "V"), + (0x1089F, "X"), + (0x108A7, "V"), + (0x108B0, "X"), + (0x108E0, "V"), + (0x108F3, "X"), + (0x108F4, "V"), + (0x108F6, "X"), + (0x108FB, "V"), + (0x1091C, "X"), + (0x1091F, "V"), + (0x1093A, "X"), + (0x1093F, "V"), + (0x10940, "X"), + (0x10980, "V"), + (0x109B8, "X"), + (0x109BC, "V"), + (0x109D0, "X"), + (0x109D2, "V"), + (0x10A04, "X"), + (0x10A05, "V"), + (0x10A07, "X"), + (0x10A0C, "V"), + (0x10A14, "X"), + (0x10A15, "V"), + (0x10A18, "X"), + (0x10A19, "V"), + (0x10A36, "X"), + (0x10A38, "V"), + (0x10A3B, "X"), + (0x10A3F, "V"), + (0x10A49, "X"), + (0x10A50, "V"), + (0x10A59, "X"), + (0x10A60, "V"), + (0x10AA0, "X"), + (0x10AC0, "V"), + (0x10AE7, "X"), + (0x10AEB, "V"), + (0x10AF7, "X"), + (0x10B00, "V"), + ] + + +def _seg_56() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x10B36, "X"), + (0x10B39, "V"), + (0x10B56, "X"), + (0x10B58, "V"), + (0x10B73, "X"), + (0x10B78, "V"), + (0x10B92, "X"), + (0x10B99, "V"), + (0x10B9D, "X"), + (0x10BA9, "V"), + (0x10BB0, "X"), + (0x10C00, "V"), + (0x10C49, "X"), + (0x10C80, "M", "𐳀"), + (0x10C81, "M", "𐳁"), + (0x10C82, "M", "𐳂"), + (0x10C83, "M", "𐳃"), + (0x10C84, "M", "𐳄"), + (0x10C85, "M", "𐳅"), + (0x10C86, "M", "𐳆"), + (0x10C87, "M", "𐳇"), + (0x10C88, "M", "𐳈"), + (0x10C89, "M", "𐳉"), + (0x10C8A, "M", "𐳊"), + (0x10C8B, "M", "𐳋"), + (0x10C8C, "M", "𐳌"), + (0x10C8D, "M", "𐳍"), + (0x10C8E, "M", "𐳎"), + (0x10C8F, "M", "𐳏"), + (0x10C90, "M", "𐳐"), + (0x10C91, "M", "𐳑"), + (0x10C92, "M", "𐳒"), + (0x10C93, "M", "𐳓"), + (0x10C94, "M", "𐳔"), + (0x10C95, "M", "𐳕"), + (0x10C96, "M", "𐳖"), + (0x10C97, "M", "𐳗"), + (0x10C98, "M", "𐳘"), + (0x10C99, "M", "𐳙"), + (0x10C9A, "M", "𐳚"), + (0x10C9B, "M", "𐳛"), + (0x10C9C, "M", "𐳜"), + (0x10C9D, "M", "𐳝"), + (0x10C9E, "M", "𐳞"), + (0x10C9F, "M", "𐳟"), + (0x10CA0, "M", "𐳠"), + (0x10CA1, "M", "𐳡"), + (0x10CA2, "M", "𐳢"), + (0x10CA3, "M", "𐳣"), + (0x10CA4, "M", "𐳤"), + (0x10CA5, "M", "𐳥"), + (0x10CA6, "M", "𐳦"), + (0x10CA7, "M", "𐳧"), + (0x10CA8, "M", "𐳨"), + (0x10CA9, "M", "𐳩"), + (0x10CAA, "M", "𐳪"), + (0x10CAB, "M", "𐳫"), + (0x10CAC, "M", "𐳬"), + (0x10CAD, "M", "𐳭"), + (0x10CAE, "M", "𐳮"), + (0x10CAF, "M", "𐳯"), + (0x10CB0, "M", "𐳰"), + (0x10CB1, "M", "𐳱"), + (0x10CB2, "M", "𐳲"), + (0x10CB3, "X"), + (0x10CC0, "V"), + (0x10CF3, "X"), + (0x10CFA, "V"), + (0x10D28, "X"), + (0x10D30, "V"), + (0x10D3A, "X"), + (0x10E60, "V"), + (0x10E7F, "X"), + (0x10E80, "V"), + (0x10EAA, "X"), + (0x10EAB, "V"), + (0x10EAE, "X"), + (0x10EB0, "V"), + (0x10EB2, "X"), + (0x10EFD, "V"), + (0x10F28, "X"), + (0x10F30, "V"), + (0x10F5A, "X"), + (0x10F70, "V"), + (0x10F8A, "X"), + (0x10FB0, "V"), + (0x10FCC, "X"), + (0x10FE0, "V"), + (0x10FF7, "X"), + (0x11000, "V"), + (0x1104E, "X"), + (0x11052, "V"), + (0x11076, "X"), + (0x1107F, "V"), + (0x110BD, "X"), + (0x110BE, "V"), + (0x110C3, "X"), + (0x110D0, "V"), + (0x110E9, "X"), + (0x110F0, "V"), + ] + + +def _seg_57() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x110FA, "X"), + (0x11100, "V"), + (0x11135, "X"), + (0x11136, "V"), + (0x11148, "X"), + (0x11150, "V"), + (0x11177, "X"), + (0x11180, "V"), + (0x111E0, "X"), + (0x111E1, "V"), + (0x111F5, "X"), + (0x11200, "V"), + (0x11212, "X"), + (0x11213, "V"), + (0x11242, "X"), + (0x11280, "V"), + (0x11287, "X"), + (0x11288, "V"), + (0x11289, "X"), + (0x1128A, "V"), + (0x1128E, "X"), + (0x1128F, "V"), + (0x1129E, "X"), + (0x1129F, "V"), + (0x112AA, "X"), + (0x112B0, "V"), + (0x112EB, "X"), + (0x112F0, "V"), + (0x112FA, "X"), + (0x11300, "V"), + (0x11304, "X"), + (0x11305, "V"), + (0x1130D, "X"), + (0x1130F, "V"), + (0x11311, "X"), + (0x11313, "V"), + (0x11329, "X"), + (0x1132A, "V"), + (0x11331, "X"), + (0x11332, "V"), + (0x11334, "X"), + (0x11335, "V"), + (0x1133A, "X"), + (0x1133B, "V"), + (0x11345, "X"), + (0x11347, "V"), + (0x11349, "X"), + (0x1134B, "V"), + (0x1134E, "X"), + (0x11350, "V"), + (0x11351, "X"), + (0x11357, "V"), + (0x11358, "X"), + (0x1135D, "V"), + (0x11364, "X"), + (0x11366, "V"), + (0x1136D, "X"), + (0x11370, "V"), + (0x11375, "X"), + (0x11400, "V"), + (0x1145C, "X"), + (0x1145D, "V"), + (0x11462, "X"), + (0x11480, "V"), + (0x114C8, "X"), + (0x114D0, "V"), + (0x114DA, "X"), + (0x11580, "V"), + (0x115B6, "X"), + (0x115B8, "V"), + (0x115DE, "X"), + (0x11600, "V"), + (0x11645, "X"), + (0x11650, "V"), + (0x1165A, "X"), + (0x11660, "V"), + (0x1166D, "X"), + (0x11680, "V"), + (0x116BA, "X"), + (0x116C0, "V"), + (0x116CA, "X"), + (0x11700, "V"), + (0x1171B, "X"), + (0x1171D, "V"), + (0x1172C, "X"), + (0x11730, "V"), + (0x11747, "X"), + (0x11800, "V"), + (0x1183C, "X"), + (0x118A0, "M", "𑣀"), + (0x118A1, "M", "𑣁"), + (0x118A2, "M", "𑣂"), + (0x118A3, "M", "𑣃"), + (0x118A4, "M", "𑣄"), + (0x118A5, "M", "𑣅"), + (0x118A6, "M", "𑣆"), + (0x118A7, "M", "𑣇"), + (0x118A8, "M", "𑣈"), + (0x118A9, "M", "𑣉"), + (0x118AA, "M", "𑣊"), + ] + + +def _seg_58() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x118AB, "M", "𑣋"), + (0x118AC, "M", "𑣌"), + (0x118AD, "M", "𑣍"), + (0x118AE, "M", "𑣎"), + (0x118AF, "M", "𑣏"), + (0x118B0, "M", "𑣐"), + (0x118B1, "M", "𑣑"), + (0x118B2, "M", "𑣒"), + (0x118B3, "M", "𑣓"), + (0x118B4, "M", "𑣔"), + (0x118B5, "M", "𑣕"), + (0x118B6, "M", "𑣖"), + (0x118B7, "M", "𑣗"), + (0x118B8, "M", "𑣘"), + (0x118B9, "M", "𑣙"), + (0x118BA, "M", "𑣚"), + (0x118BB, "M", "𑣛"), + (0x118BC, "M", "𑣜"), + (0x118BD, "M", "𑣝"), + (0x118BE, "M", "𑣞"), + (0x118BF, "M", "𑣟"), + (0x118C0, "V"), + (0x118F3, "X"), + (0x118FF, "V"), + (0x11907, "X"), + (0x11909, "V"), + (0x1190A, "X"), + (0x1190C, "V"), + (0x11914, "X"), + (0x11915, "V"), + (0x11917, "X"), + (0x11918, "V"), + (0x11936, "X"), + (0x11937, "V"), + (0x11939, "X"), + (0x1193B, "V"), + (0x11947, "X"), + (0x11950, "V"), + (0x1195A, "X"), + (0x119A0, "V"), + (0x119A8, "X"), + (0x119AA, "V"), + (0x119D8, "X"), + (0x119DA, "V"), + (0x119E5, "X"), + (0x11A00, "V"), + (0x11A48, "X"), + (0x11A50, "V"), + (0x11AA3, "X"), + (0x11AB0, "V"), + (0x11AF9, "X"), + (0x11B00, "V"), + (0x11B0A, "X"), + (0x11C00, "V"), + (0x11C09, "X"), + (0x11C0A, "V"), + (0x11C37, "X"), + (0x11C38, "V"), + (0x11C46, "X"), + (0x11C50, "V"), + (0x11C6D, "X"), + (0x11C70, "V"), + (0x11C90, "X"), + (0x11C92, "V"), + (0x11CA8, "X"), + (0x11CA9, "V"), + (0x11CB7, "X"), + (0x11D00, "V"), + (0x11D07, "X"), + (0x11D08, "V"), + (0x11D0A, "X"), + (0x11D0B, "V"), + (0x11D37, "X"), + (0x11D3A, "V"), + (0x11D3B, "X"), + (0x11D3C, "V"), + (0x11D3E, "X"), + (0x11D3F, "V"), + (0x11D48, "X"), + (0x11D50, "V"), + (0x11D5A, "X"), + (0x11D60, "V"), + (0x11D66, "X"), + (0x11D67, "V"), + (0x11D69, "X"), + (0x11D6A, "V"), + (0x11D8F, "X"), + (0x11D90, "V"), + (0x11D92, "X"), + (0x11D93, "V"), + (0x11D99, "X"), + (0x11DA0, "V"), + (0x11DAA, "X"), + (0x11EE0, "V"), + (0x11EF9, "X"), + (0x11F00, "V"), + (0x11F11, "X"), + (0x11F12, "V"), + (0x11F3B, "X"), + (0x11F3E, "V"), + ] + + +def _seg_59() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x11F5A, "X"), + (0x11FB0, "V"), + (0x11FB1, "X"), + (0x11FC0, "V"), + (0x11FF2, "X"), + (0x11FFF, "V"), + (0x1239A, "X"), + (0x12400, "V"), + (0x1246F, "X"), + (0x12470, "V"), + (0x12475, "X"), + (0x12480, "V"), + (0x12544, "X"), + (0x12F90, "V"), + (0x12FF3, "X"), + (0x13000, "V"), + (0x13430, "X"), + (0x13440, "V"), + (0x13456, "X"), + (0x14400, "V"), + (0x14647, "X"), + (0x16800, "V"), + (0x16A39, "X"), + (0x16A40, "V"), + (0x16A5F, "X"), + (0x16A60, "V"), + (0x16A6A, "X"), + (0x16A6E, "V"), + (0x16ABF, "X"), + (0x16AC0, "V"), + (0x16ACA, "X"), + (0x16AD0, "V"), + (0x16AEE, "X"), + (0x16AF0, "V"), + (0x16AF6, "X"), + (0x16B00, "V"), + (0x16B46, "X"), + (0x16B50, "V"), + (0x16B5A, "X"), + (0x16B5B, "V"), + (0x16B62, "X"), + (0x16B63, "V"), + (0x16B78, "X"), + (0x16B7D, "V"), + (0x16B90, "X"), + (0x16E40, "M", "𖹠"), + (0x16E41, "M", "𖹡"), + (0x16E42, "M", "𖹢"), + (0x16E43, "M", "𖹣"), + (0x16E44, "M", "𖹤"), + (0x16E45, "M", "𖹥"), + (0x16E46, "M", "𖹦"), + (0x16E47, "M", "𖹧"), + (0x16E48, "M", "𖹨"), + (0x16E49, "M", "𖹩"), + (0x16E4A, "M", "𖹪"), + (0x16E4B, "M", "𖹫"), + (0x16E4C, "M", "𖹬"), + (0x16E4D, "M", "𖹭"), + (0x16E4E, "M", "𖹮"), + (0x16E4F, "M", "𖹯"), + (0x16E50, "M", "𖹰"), + (0x16E51, "M", "𖹱"), + (0x16E52, "M", "𖹲"), + (0x16E53, "M", "𖹳"), + (0x16E54, "M", "𖹴"), + (0x16E55, "M", "𖹵"), + (0x16E56, "M", "𖹶"), + (0x16E57, "M", "𖹷"), + (0x16E58, "M", "𖹸"), + (0x16E59, "M", "𖹹"), + (0x16E5A, "M", "𖹺"), + (0x16E5B, "M", "𖹻"), + (0x16E5C, "M", "𖹼"), + (0x16E5D, "M", "𖹽"), + (0x16E5E, "M", "𖹾"), + (0x16E5F, "M", "𖹿"), + (0x16E60, "V"), + (0x16E9B, "X"), + (0x16F00, "V"), + (0x16F4B, "X"), + (0x16F4F, "V"), + (0x16F88, "X"), + (0x16F8F, "V"), + (0x16FA0, "X"), + (0x16FE0, "V"), + (0x16FE5, "X"), + (0x16FF0, "V"), + (0x16FF2, "X"), + (0x17000, "V"), + (0x187F8, "X"), + (0x18800, "V"), + (0x18CD6, "X"), + (0x18D00, "V"), + (0x18D09, "X"), + (0x1AFF0, "V"), + (0x1AFF4, "X"), + (0x1AFF5, "V"), + (0x1AFFC, "X"), + (0x1AFFD, "V"), + ] + + +def _seg_60() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1AFFF, "X"), + (0x1B000, "V"), + (0x1B123, "X"), + (0x1B132, "V"), + (0x1B133, "X"), + (0x1B150, "V"), + (0x1B153, "X"), + (0x1B155, "V"), + (0x1B156, "X"), + (0x1B164, "V"), + (0x1B168, "X"), + (0x1B170, "V"), + (0x1B2FC, "X"), + (0x1BC00, "V"), + (0x1BC6B, "X"), + (0x1BC70, "V"), + (0x1BC7D, "X"), + (0x1BC80, "V"), + (0x1BC89, "X"), + (0x1BC90, "V"), + (0x1BC9A, "X"), + (0x1BC9C, "V"), + (0x1BCA0, "I"), + (0x1BCA4, "X"), + (0x1CF00, "V"), + (0x1CF2E, "X"), + (0x1CF30, "V"), + (0x1CF47, "X"), + (0x1CF50, "V"), + (0x1CFC4, "X"), + (0x1D000, "V"), + (0x1D0F6, "X"), + (0x1D100, "V"), + (0x1D127, "X"), + (0x1D129, "V"), + (0x1D15E, "M", "𝅗𝅥"), + (0x1D15F, "M", "𝅘𝅥"), + (0x1D160, "M", "𝅘𝅥𝅮"), + (0x1D161, "M", "𝅘𝅥𝅯"), + (0x1D162, "M", "𝅘𝅥𝅰"), + (0x1D163, "M", "𝅘𝅥𝅱"), + (0x1D164, "M", "𝅘𝅥𝅲"), + (0x1D165, "V"), + (0x1D173, "X"), + (0x1D17B, "V"), + (0x1D1BB, "M", "𝆹𝅥"), + (0x1D1BC, "M", "𝆺𝅥"), + (0x1D1BD, "M", "𝆹𝅥𝅮"), + (0x1D1BE, "M", "𝆺𝅥𝅮"), + (0x1D1BF, "M", "𝆹𝅥𝅯"), + (0x1D1C0, "M", "𝆺𝅥𝅯"), + (0x1D1C1, "V"), + (0x1D1EB, "X"), + (0x1D200, "V"), + (0x1D246, "X"), + (0x1D2C0, "V"), + (0x1D2D4, "X"), + (0x1D2E0, "V"), + (0x1D2F4, "X"), + (0x1D300, "V"), + (0x1D357, "X"), + (0x1D360, "V"), + (0x1D379, "X"), + (0x1D400, "M", "a"), + (0x1D401, "M", "b"), + (0x1D402, "M", "c"), + (0x1D403, "M", "d"), + (0x1D404, "M", "e"), + (0x1D405, "M", "f"), + (0x1D406, "M", "g"), + (0x1D407, "M", "h"), + (0x1D408, "M", "i"), + (0x1D409, "M", "j"), + (0x1D40A, "M", "k"), + (0x1D40B, "M", "l"), + (0x1D40C, "M", "m"), + (0x1D40D, "M", "n"), + (0x1D40E, "M", "o"), + (0x1D40F, "M", "p"), + (0x1D410, "M", "q"), + (0x1D411, "M", "r"), + (0x1D412, "M", "s"), + (0x1D413, "M", "t"), + (0x1D414, "M", "u"), + (0x1D415, "M", "v"), + (0x1D416, "M", "w"), + (0x1D417, "M", "x"), + (0x1D418, "M", "y"), + (0x1D419, "M", "z"), + (0x1D41A, "M", "a"), + (0x1D41B, "M", "b"), + (0x1D41C, "M", "c"), + (0x1D41D, "M", "d"), + (0x1D41E, "M", "e"), + (0x1D41F, "M", "f"), + (0x1D420, "M", "g"), + (0x1D421, "M", "h"), + (0x1D422, "M", "i"), + (0x1D423, "M", "j"), + (0x1D424, "M", "k"), + ] + + +def _seg_61() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1D425, "M", "l"), + (0x1D426, "M", "m"), + (0x1D427, "M", "n"), + (0x1D428, "M", "o"), + (0x1D429, "M", "p"), + (0x1D42A, "M", "q"), + (0x1D42B, "M", "r"), + (0x1D42C, "M", "s"), + (0x1D42D, "M", "t"), + (0x1D42E, "M", "u"), + (0x1D42F, "M", "v"), + (0x1D430, "M", "w"), + (0x1D431, "M", "x"), + (0x1D432, "M", "y"), + (0x1D433, "M", "z"), + (0x1D434, "M", "a"), + (0x1D435, "M", "b"), + (0x1D436, "M", "c"), + (0x1D437, "M", "d"), + (0x1D438, "M", "e"), + (0x1D439, "M", "f"), + (0x1D43A, "M", "g"), + (0x1D43B, "M", "h"), + (0x1D43C, "M", "i"), + (0x1D43D, "M", "j"), + (0x1D43E, "M", "k"), + (0x1D43F, "M", "l"), + (0x1D440, "M", "m"), + (0x1D441, "M", "n"), + (0x1D442, "M", "o"), + (0x1D443, "M", "p"), + (0x1D444, "M", "q"), + (0x1D445, "M", "r"), + (0x1D446, "M", "s"), + (0x1D447, "M", "t"), + (0x1D448, "M", "u"), + (0x1D449, "M", "v"), + (0x1D44A, "M", "w"), + (0x1D44B, "M", "x"), + (0x1D44C, "M", "y"), + (0x1D44D, "M", "z"), + (0x1D44E, "M", "a"), + (0x1D44F, "M", "b"), + (0x1D450, "M", "c"), + (0x1D451, "M", "d"), + (0x1D452, "M", "e"), + (0x1D453, "M", "f"), + (0x1D454, "M", "g"), + (0x1D455, "X"), + (0x1D456, "M", "i"), + (0x1D457, "M", "j"), + (0x1D458, "M", "k"), + (0x1D459, "M", "l"), + (0x1D45A, "M", "m"), + (0x1D45B, "M", "n"), + (0x1D45C, "M", "o"), + (0x1D45D, "M", "p"), + (0x1D45E, "M", "q"), + (0x1D45F, "M", "r"), + (0x1D460, "M", "s"), + (0x1D461, "M", "t"), + (0x1D462, "M", "u"), + (0x1D463, "M", "v"), + (0x1D464, "M", "w"), + (0x1D465, "M", "x"), + (0x1D466, "M", "y"), + (0x1D467, "M", "z"), + (0x1D468, "M", "a"), + (0x1D469, "M", "b"), + (0x1D46A, "M", "c"), + (0x1D46B, "M", "d"), + (0x1D46C, "M", "e"), + (0x1D46D, "M", "f"), + (0x1D46E, "M", "g"), + (0x1D46F, "M", "h"), + (0x1D470, "M", "i"), + (0x1D471, "M", "j"), + (0x1D472, "M", "k"), + (0x1D473, "M", "l"), + (0x1D474, "M", "m"), + (0x1D475, "M", "n"), + (0x1D476, "M", "o"), + (0x1D477, "M", "p"), + (0x1D478, "M", "q"), + (0x1D479, "M", "r"), + (0x1D47A, "M", "s"), + (0x1D47B, "M", "t"), + (0x1D47C, "M", "u"), + (0x1D47D, "M", "v"), + (0x1D47E, "M", "w"), + (0x1D47F, "M", "x"), + (0x1D480, "M", "y"), + (0x1D481, "M", "z"), + (0x1D482, "M", "a"), + (0x1D483, "M", "b"), + (0x1D484, "M", "c"), + (0x1D485, "M", "d"), + (0x1D486, "M", "e"), + (0x1D487, "M", "f"), + (0x1D488, "M", "g"), + ] + + +def _seg_62() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1D489, "M", "h"), + (0x1D48A, "M", "i"), + (0x1D48B, "M", "j"), + (0x1D48C, "M", "k"), + (0x1D48D, "M", "l"), + (0x1D48E, "M", "m"), + (0x1D48F, "M", "n"), + (0x1D490, "M", "o"), + (0x1D491, "M", "p"), + (0x1D492, "M", "q"), + (0x1D493, "M", "r"), + (0x1D494, "M", "s"), + (0x1D495, "M", "t"), + (0x1D496, "M", "u"), + (0x1D497, "M", "v"), + (0x1D498, "M", "w"), + (0x1D499, "M", "x"), + (0x1D49A, "M", "y"), + (0x1D49B, "M", "z"), + (0x1D49C, "M", "a"), + (0x1D49D, "X"), + (0x1D49E, "M", "c"), + (0x1D49F, "M", "d"), + (0x1D4A0, "X"), + (0x1D4A2, "M", "g"), + (0x1D4A3, "X"), + (0x1D4A5, "M", "j"), + (0x1D4A6, "M", "k"), + (0x1D4A7, "X"), + (0x1D4A9, "M", "n"), + (0x1D4AA, "M", "o"), + (0x1D4AB, "M", "p"), + (0x1D4AC, "M", "q"), + (0x1D4AD, "X"), + (0x1D4AE, "M", "s"), + (0x1D4AF, "M", "t"), + (0x1D4B0, "M", "u"), + (0x1D4B1, "M", "v"), + (0x1D4B2, "M", "w"), + (0x1D4B3, "M", "x"), + (0x1D4B4, "M", "y"), + (0x1D4B5, "M", "z"), + (0x1D4B6, "M", "a"), + (0x1D4B7, "M", "b"), + (0x1D4B8, "M", "c"), + (0x1D4B9, "M", "d"), + (0x1D4BA, "X"), + (0x1D4BB, "M", "f"), + (0x1D4BC, "X"), + (0x1D4BD, "M", "h"), + (0x1D4BE, "M", "i"), + (0x1D4BF, "M", "j"), + (0x1D4C0, "M", "k"), + (0x1D4C1, "M", "l"), + (0x1D4C2, "M", "m"), + (0x1D4C3, "M", "n"), + (0x1D4C4, "X"), + (0x1D4C5, "M", "p"), + (0x1D4C6, "M", "q"), + (0x1D4C7, "M", "r"), + (0x1D4C8, "M", "s"), + (0x1D4C9, "M", "t"), + (0x1D4CA, "M", "u"), + (0x1D4CB, "M", "v"), + (0x1D4CC, "M", "w"), + (0x1D4CD, "M", "x"), + (0x1D4CE, "M", "y"), + (0x1D4CF, "M", "z"), + (0x1D4D0, "M", "a"), + (0x1D4D1, "M", "b"), + (0x1D4D2, "M", "c"), + (0x1D4D3, "M", "d"), + (0x1D4D4, "M", "e"), + (0x1D4D5, "M", "f"), + (0x1D4D6, "M", "g"), + (0x1D4D7, "M", "h"), + (0x1D4D8, "M", "i"), + (0x1D4D9, "M", "j"), + (0x1D4DA, "M", "k"), + (0x1D4DB, "M", "l"), + (0x1D4DC, "M", "m"), + (0x1D4DD, "M", "n"), + (0x1D4DE, "M", "o"), + (0x1D4DF, "M", "p"), + (0x1D4E0, "M", "q"), + (0x1D4E1, "M", "r"), + (0x1D4E2, "M", "s"), + (0x1D4E3, "M", "t"), + (0x1D4E4, "M", "u"), + (0x1D4E5, "M", "v"), + (0x1D4E6, "M", "w"), + (0x1D4E7, "M", "x"), + (0x1D4E8, "M", "y"), + (0x1D4E9, "M", "z"), + (0x1D4EA, "M", "a"), + (0x1D4EB, "M", "b"), + (0x1D4EC, "M", "c"), + (0x1D4ED, "M", "d"), + (0x1D4EE, "M", "e"), + (0x1D4EF, "M", "f"), + ] + + +def _seg_63() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1D4F0, "M", "g"), + (0x1D4F1, "M", "h"), + (0x1D4F2, "M", "i"), + (0x1D4F3, "M", "j"), + (0x1D4F4, "M", "k"), + (0x1D4F5, "M", "l"), + (0x1D4F6, "M", "m"), + (0x1D4F7, "M", "n"), + (0x1D4F8, "M", "o"), + (0x1D4F9, "M", "p"), + (0x1D4FA, "M", "q"), + (0x1D4FB, "M", "r"), + (0x1D4FC, "M", "s"), + (0x1D4FD, "M", "t"), + (0x1D4FE, "M", "u"), + (0x1D4FF, "M", "v"), + (0x1D500, "M", "w"), + (0x1D501, "M", "x"), + (0x1D502, "M", "y"), + (0x1D503, "M", "z"), + (0x1D504, "M", "a"), + (0x1D505, "M", "b"), + (0x1D506, "X"), + (0x1D507, "M", "d"), + (0x1D508, "M", "e"), + (0x1D509, "M", "f"), + (0x1D50A, "M", "g"), + (0x1D50B, "X"), + (0x1D50D, "M", "j"), + (0x1D50E, "M", "k"), + (0x1D50F, "M", "l"), + (0x1D510, "M", "m"), + (0x1D511, "M", "n"), + (0x1D512, "M", "o"), + (0x1D513, "M", "p"), + (0x1D514, "M", "q"), + (0x1D515, "X"), + (0x1D516, "M", "s"), + (0x1D517, "M", "t"), + (0x1D518, "M", "u"), + (0x1D519, "M", "v"), + (0x1D51A, "M", "w"), + (0x1D51B, "M", "x"), + (0x1D51C, "M", "y"), + (0x1D51D, "X"), + (0x1D51E, "M", "a"), + (0x1D51F, "M", "b"), + (0x1D520, "M", "c"), + (0x1D521, "M", "d"), + (0x1D522, "M", "e"), + (0x1D523, "M", "f"), + (0x1D524, "M", "g"), + (0x1D525, "M", "h"), + (0x1D526, "M", "i"), + (0x1D527, "M", "j"), + (0x1D528, "M", "k"), + (0x1D529, "M", "l"), + (0x1D52A, "M", "m"), + (0x1D52B, "M", "n"), + (0x1D52C, "M", "o"), + (0x1D52D, "M", "p"), + (0x1D52E, "M", "q"), + (0x1D52F, "M", "r"), + (0x1D530, "M", "s"), + (0x1D531, "M", "t"), + (0x1D532, "M", "u"), + (0x1D533, "M", "v"), + (0x1D534, "M", "w"), + (0x1D535, "M", "x"), + (0x1D536, "M", "y"), + (0x1D537, "M", "z"), + (0x1D538, "M", "a"), + (0x1D539, "M", "b"), + (0x1D53A, "X"), + (0x1D53B, "M", "d"), + (0x1D53C, "M", "e"), + (0x1D53D, "M", "f"), + (0x1D53E, "M", "g"), + (0x1D53F, "X"), + (0x1D540, "M", "i"), + (0x1D541, "M", "j"), + (0x1D542, "M", "k"), + (0x1D543, "M", "l"), + (0x1D544, "M", "m"), + (0x1D545, "X"), + (0x1D546, "M", "o"), + (0x1D547, "X"), + (0x1D54A, "M", "s"), + (0x1D54B, "M", "t"), + (0x1D54C, "M", "u"), + (0x1D54D, "M", "v"), + (0x1D54E, "M", "w"), + (0x1D54F, "M", "x"), + (0x1D550, "M", "y"), + (0x1D551, "X"), + (0x1D552, "M", "a"), + (0x1D553, "M", "b"), + (0x1D554, "M", "c"), + (0x1D555, "M", "d"), + (0x1D556, "M", "e"), + ] + + +def _seg_64() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1D557, "M", "f"), + (0x1D558, "M", "g"), + (0x1D559, "M", "h"), + (0x1D55A, "M", "i"), + (0x1D55B, "M", "j"), + (0x1D55C, "M", "k"), + (0x1D55D, "M", "l"), + (0x1D55E, "M", "m"), + (0x1D55F, "M", "n"), + (0x1D560, "M", "o"), + (0x1D561, "M", "p"), + (0x1D562, "M", "q"), + (0x1D563, "M", "r"), + (0x1D564, "M", "s"), + (0x1D565, "M", "t"), + (0x1D566, "M", "u"), + (0x1D567, "M", "v"), + (0x1D568, "M", "w"), + (0x1D569, "M", "x"), + (0x1D56A, "M", "y"), + (0x1D56B, "M", "z"), + (0x1D56C, "M", "a"), + (0x1D56D, "M", "b"), + (0x1D56E, "M", "c"), + (0x1D56F, "M", "d"), + (0x1D570, "M", "e"), + (0x1D571, "M", "f"), + (0x1D572, "M", "g"), + (0x1D573, "M", "h"), + (0x1D574, "M", "i"), + (0x1D575, "M", "j"), + (0x1D576, "M", "k"), + (0x1D577, "M", "l"), + (0x1D578, "M", "m"), + (0x1D579, "M", "n"), + (0x1D57A, "M", "o"), + (0x1D57B, "M", "p"), + (0x1D57C, "M", "q"), + (0x1D57D, "M", "r"), + (0x1D57E, "M", "s"), + (0x1D57F, "M", "t"), + (0x1D580, "M", "u"), + (0x1D581, "M", "v"), + (0x1D582, "M", "w"), + (0x1D583, "M", "x"), + (0x1D584, "M", "y"), + (0x1D585, "M", "z"), + (0x1D586, "M", "a"), + (0x1D587, "M", "b"), + (0x1D588, "M", "c"), + (0x1D589, "M", "d"), + (0x1D58A, "M", "e"), + (0x1D58B, "M", "f"), + (0x1D58C, "M", "g"), + (0x1D58D, "M", "h"), + (0x1D58E, "M", "i"), + (0x1D58F, "M", "j"), + (0x1D590, "M", "k"), + (0x1D591, "M", "l"), + (0x1D592, "M", "m"), + (0x1D593, "M", "n"), + (0x1D594, "M", "o"), + (0x1D595, "M", "p"), + (0x1D596, "M", "q"), + (0x1D597, "M", "r"), + (0x1D598, "M", "s"), + (0x1D599, "M", "t"), + (0x1D59A, "M", "u"), + (0x1D59B, "M", "v"), + (0x1D59C, "M", "w"), + (0x1D59D, "M", "x"), + (0x1D59E, "M", "y"), + (0x1D59F, "M", "z"), + (0x1D5A0, "M", "a"), + (0x1D5A1, "M", "b"), + (0x1D5A2, "M", "c"), + (0x1D5A3, "M", "d"), + (0x1D5A4, "M", "e"), + (0x1D5A5, "M", "f"), + (0x1D5A6, "M", "g"), + (0x1D5A7, "M", "h"), + (0x1D5A8, "M", "i"), + (0x1D5A9, "M", "j"), + (0x1D5AA, "M", "k"), + (0x1D5AB, "M", "l"), + (0x1D5AC, "M", "m"), + (0x1D5AD, "M", "n"), + (0x1D5AE, "M", "o"), + (0x1D5AF, "M", "p"), + (0x1D5B0, "M", "q"), + (0x1D5B1, "M", "r"), + (0x1D5B2, "M", "s"), + (0x1D5B3, "M", "t"), + (0x1D5B4, "M", "u"), + (0x1D5B5, "M", "v"), + (0x1D5B6, "M", "w"), + (0x1D5B7, "M", "x"), + (0x1D5B8, "M", "y"), + (0x1D5B9, "M", "z"), + (0x1D5BA, "M", "a"), + ] + + +def _seg_65() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1D5BB, "M", "b"), + (0x1D5BC, "M", "c"), + (0x1D5BD, "M", "d"), + (0x1D5BE, "M", "e"), + (0x1D5BF, "M", "f"), + (0x1D5C0, "M", "g"), + (0x1D5C1, "M", "h"), + (0x1D5C2, "M", "i"), + (0x1D5C3, "M", "j"), + (0x1D5C4, "M", "k"), + (0x1D5C5, "M", "l"), + (0x1D5C6, "M", "m"), + (0x1D5C7, "M", "n"), + (0x1D5C8, "M", "o"), + (0x1D5C9, "M", "p"), + (0x1D5CA, "M", "q"), + (0x1D5CB, "M", "r"), + (0x1D5CC, "M", "s"), + (0x1D5CD, "M", "t"), + (0x1D5CE, "M", "u"), + (0x1D5CF, "M", "v"), + (0x1D5D0, "M", "w"), + (0x1D5D1, "M", "x"), + (0x1D5D2, "M", "y"), + (0x1D5D3, "M", "z"), + (0x1D5D4, "M", "a"), + (0x1D5D5, "M", "b"), + (0x1D5D6, "M", "c"), + (0x1D5D7, "M", "d"), + (0x1D5D8, "M", "e"), + (0x1D5D9, "M", "f"), + (0x1D5DA, "M", "g"), + (0x1D5DB, "M", "h"), + (0x1D5DC, "M", "i"), + (0x1D5DD, "M", "j"), + (0x1D5DE, "M", "k"), + (0x1D5DF, "M", "l"), + (0x1D5E0, "M", "m"), + (0x1D5E1, "M", "n"), + (0x1D5E2, "M", "o"), + (0x1D5E3, "M", "p"), + (0x1D5E4, "M", "q"), + (0x1D5E5, "M", "r"), + (0x1D5E6, "M", "s"), + (0x1D5E7, "M", "t"), + (0x1D5E8, "M", "u"), + (0x1D5E9, "M", "v"), + (0x1D5EA, "M", "w"), + (0x1D5EB, "M", "x"), + (0x1D5EC, "M", "y"), + (0x1D5ED, "M", "z"), + (0x1D5EE, "M", "a"), + (0x1D5EF, "M", "b"), + (0x1D5F0, "M", "c"), + (0x1D5F1, "M", "d"), + (0x1D5F2, "M", "e"), + (0x1D5F3, "M", "f"), + (0x1D5F4, "M", "g"), + (0x1D5F5, "M", "h"), + (0x1D5F6, "M", "i"), + (0x1D5F7, "M", "j"), + (0x1D5F8, "M", "k"), + (0x1D5F9, "M", "l"), + (0x1D5FA, "M", "m"), + (0x1D5FB, "M", "n"), + (0x1D5FC, "M", "o"), + (0x1D5FD, "M", "p"), + (0x1D5FE, "M", "q"), + (0x1D5FF, "M", "r"), + (0x1D600, "M", "s"), + (0x1D601, "M", "t"), + (0x1D602, "M", "u"), + (0x1D603, "M", "v"), + (0x1D604, "M", "w"), + (0x1D605, "M", "x"), + (0x1D606, "M", "y"), + (0x1D607, "M", "z"), + (0x1D608, "M", "a"), + (0x1D609, "M", "b"), + (0x1D60A, "M", "c"), + (0x1D60B, "M", "d"), + (0x1D60C, "M", "e"), + (0x1D60D, "M", "f"), + (0x1D60E, "M", "g"), + (0x1D60F, "M", "h"), + (0x1D610, "M", "i"), + (0x1D611, "M", "j"), + (0x1D612, "M", "k"), + (0x1D613, "M", "l"), + (0x1D614, "M", "m"), + (0x1D615, "M", "n"), + (0x1D616, "M", "o"), + (0x1D617, "M", "p"), + (0x1D618, "M", "q"), + (0x1D619, "M", "r"), + (0x1D61A, "M", "s"), + (0x1D61B, "M", "t"), + (0x1D61C, "M", "u"), + (0x1D61D, "M", "v"), + (0x1D61E, "M", "w"), + ] + + +def _seg_66() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1D61F, "M", "x"), + (0x1D620, "M", "y"), + (0x1D621, "M", "z"), + (0x1D622, "M", "a"), + (0x1D623, "M", "b"), + (0x1D624, "M", "c"), + (0x1D625, "M", "d"), + (0x1D626, "M", "e"), + (0x1D627, "M", "f"), + (0x1D628, "M", "g"), + (0x1D629, "M", "h"), + (0x1D62A, "M", "i"), + (0x1D62B, "M", "j"), + (0x1D62C, "M", "k"), + (0x1D62D, "M", "l"), + (0x1D62E, "M", "m"), + (0x1D62F, "M", "n"), + (0x1D630, "M", "o"), + (0x1D631, "M", "p"), + (0x1D632, "M", "q"), + (0x1D633, "M", "r"), + (0x1D634, "M", "s"), + (0x1D635, "M", "t"), + (0x1D636, "M", "u"), + (0x1D637, "M", "v"), + (0x1D638, "M", "w"), + (0x1D639, "M", "x"), + (0x1D63A, "M", "y"), + (0x1D63B, "M", "z"), + (0x1D63C, "M", "a"), + (0x1D63D, "M", "b"), + (0x1D63E, "M", "c"), + (0x1D63F, "M", "d"), + (0x1D640, "M", "e"), + (0x1D641, "M", "f"), + (0x1D642, "M", "g"), + (0x1D643, "M", "h"), + (0x1D644, "M", "i"), + (0x1D645, "M", "j"), + (0x1D646, "M", "k"), + (0x1D647, "M", "l"), + (0x1D648, "M", "m"), + (0x1D649, "M", "n"), + (0x1D64A, "M", "o"), + (0x1D64B, "M", "p"), + (0x1D64C, "M", "q"), + (0x1D64D, "M", "r"), + (0x1D64E, "M", "s"), + (0x1D64F, "M", "t"), + (0x1D650, "M", "u"), + (0x1D651, "M", "v"), + (0x1D652, "M", "w"), + (0x1D653, "M", "x"), + (0x1D654, "M", "y"), + (0x1D655, "M", "z"), + (0x1D656, "M", "a"), + (0x1D657, "M", "b"), + (0x1D658, "M", "c"), + (0x1D659, "M", "d"), + (0x1D65A, "M", "e"), + (0x1D65B, "M", "f"), + (0x1D65C, "M", "g"), + (0x1D65D, "M", "h"), + (0x1D65E, "M", "i"), + (0x1D65F, "M", "j"), + (0x1D660, "M", "k"), + (0x1D661, "M", "l"), + (0x1D662, "M", "m"), + (0x1D663, "M", "n"), + (0x1D664, "M", "o"), + (0x1D665, "M", "p"), + (0x1D666, "M", "q"), + (0x1D667, "M", "r"), + (0x1D668, "M", "s"), + (0x1D669, "M", "t"), + (0x1D66A, "M", "u"), + (0x1D66B, "M", "v"), + (0x1D66C, "M", "w"), + (0x1D66D, "M", "x"), + (0x1D66E, "M", "y"), + (0x1D66F, "M", "z"), + (0x1D670, "M", "a"), + (0x1D671, "M", "b"), + (0x1D672, "M", "c"), + (0x1D673, "M", "d"), + (0x1D674, "M", "e"), + (0x1D675, "M", "f"), + (0x1D676, "M", "g"), + (0x1D677, "M", "h"), + (0x1D678, "M", "i"), + (0x1D679, "M", "j"), + (0x1D67A, "M", "k"), + (0x1D67B, "M", "l"), + (0x1D67C, "M", "m"), + (0x1D67D, "M", "n"), + (0x1D67E, "M", "o"), + (0x1D67F, "M", "p"), + (0x1D680, "M", "q"), + (0x1D681, "M", "r"), + (0x1D682, "M", "s"), + ] + + +def _seg_67() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1D683, "M", "t"), + (0x1D684, "M", "u"), + (0x1D685, "M", "v"), + (0x1D686, "M", "w"), + (0x1D687, "M", "x"), + (0x1D688, "M", "y"), + (0x1D689, "M", "z"), + (0x1D68A, "M", "a"), + (0x1D68B, "M", "b"), + (0x1D68C, "M", "c"), + (0x1D68D, "M", "d"), + (0x1D68E, "M", "e"), + (0x1D68F, "M", "f"), + (0x1D690, "M", "g"), + (0x1D691, "M", "h"), + (0x1D692, "M", "i"), + (0x1D693, "M", "j"), + (0x1D694, "M", "k"), + (0x1D695, "M", "l"), + (0x1D696, "M", "m"), + (0x1D697, "M", "n"), + (0x1D698, "M", "o"), + (0x1D699, "M", "p"), + (0x1D69A, "M", "q"), + (0x1D69B, "M", "r"), + (0x1D69C, "M", "s"), + (0x1D69D, "M", "t"), + (0x1D69E, "M", "u"), + (0x1D69F, "M", "v"), + (0x1D6A0, "M", "w"), + (0x1D6A1, "M", "x"), + (0x1D6A2, "M", "y"), + (0x1D6A3, "M", "z"), + (0x1D6A4, "M", "ı"), + (0x1D6A5, "M", "ȷ"), + (0x1D6A6, "X"), + (0x1D6A8, "M", "α"), + (0x1D6A9, "M", "β"), + (0x1D6AA, "M", "γ"), + (0x1D6AB, "M", "δ"), + (0x1D6AC, "M", "ε"), + (0x1D6AD, "M", "ζ"), + (0x1D6AE, "M", "η"), + (0x1D6AF, "M", "θ"), + (0x1D6B0, "M", "ι"), + (0x1D6B1, "M", "κ"), + (0x1D6B2, "M", "λ"), + (0x1D6B3, "M", "μ"), + (0x1D6B4, "M", "ν"), + (0x1D6B5, "M", "ξ"), + (0x1D6B6, "M", "ο"), + (0x1D6B7, "M", "π"), + (0x1D6B8, "M", "ρ"), + (0x1D6B9, "M", "θ"), + (0x1D6BA, "M", "σ"), + (0x1D6BB, "M", "τ"), + (0x1D6BC, "M", "υ"), + (0x1D6BD, "M", "φ"), + (0x1D6BE, "M", "χ"), + (0x1D6BF, "M", "ψ"), + (0x1D6C0, "M", "ω"), + (0x1D6C1, "M", "∇"), + (0x1D6C2, "M", "α"), + (0x1D6C3, "M", "β"), + (0x1D6C4, "M", "γ"), + (0x1D6C5, "M", "δ"), + (0x1D6C6, "M", "ε"), + (0x1D6C7, "M", "ζ"), + (0x1D6C8, "M", "η"), + (0x1D6C9, "M", "θ"), + (0x1D6CA, "M", "ι"), + (0x1D6CB, "M", "κ"), + (0x1D6CC, "M", "λ"), + (0x1D6CD, "M", "μ"), + (0x1D6CE, "M", "ν"), + (0x1D6CF, "M", "ξ"), + (0x1D6D0, "M", "ο"), + (0x1D6D1, "M", "π"), + (0x1D6D2, "M", "ρ"), + (0x1D6D3, "M", "σ"), + (0x1D6D5, "M", "τ"), + (0x1D6D6, "M", "υ"), + (0x1D6D7, "M", "φ"), + (0x1D6D8, "M", "χ"), + (0x1D6D9, "M", "ψ"), + (0x1D6DA, "M", "ω"), + (0x1D6DB, "M", "∂"), + (0x1D6DC, "M", "ε"), + (0x1D6DD, "M", "θ"), + (0x1D6DE, "M", "κ"), + (0x1D6DF, "M", "φ"), + (0x1D6E0, "M", "ρ"), + (0x1D6E1, "M", "π"), + (0x1D6E2, "M", "α"), + (0x1D6E3, "M", "β"), + (0x1D6E4, "M", "γ"), + (0x1D6E5, "M", "δ"), + (0x1D6E6, "M", "ε"), + (0x1D6E7, "M", "ζ"), + (0x1D6E8, "M", "η"), + ] + + +def _seg_68() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1D6E9, "M", "θ"), + (0x1D6EA, "M", "ι"), + (0x1D6EB, "M", "κ"), + (0x1D6EC, "M", "λ"), + (0x1D6ED, "M", "μ"), + (0x1D6EE, "M", "ν"), + (0x1D6EF, "M", "ξ"), + (0x1D6F0, "M", "ο"), + (0x1D6F1, "M", "π"), + (0x1D6F2, "M", "ρ"), + (0x1D6F3, "M", "θ"), + (0x1D6F4, "M", "σ"), + (0x1D6F5, "M", "τ"), + (0x1D6F6, "M", "υ"), + (0x1D6F7, "M", "φ"), + (0x1D6F8, "M", "χ"), + (0x1D6F9, "M", "ψ"), + (0x1D6FA, "M", "ω"), + (0x1D6FB, "M", "∇"), + (0x1D6FC, "M", "α"), + (0x1D6FD, "M", "β"), + (0x1D6FE, "M", "γ"), + (0x1D6FF, "M", "δ"), + (0x1D700, "M", "ε"), + (0x1D701, "M", "ζ"), + (0x1D702, "M", "η"), + (0x1D703, "M", "θ"), + (0x1D704, "M", "ι"), + (0x1D705, "M", "κ"), + (0x1D706, "M", "λ"), + (0x1D707, "M", "μ"), + (0x1D708, "M", "ν"), + (0x1D709, "M", "ξ"), + (0x1D70A, "M", "ο"), + (0x1D70B, "M", "π"), + (0x1D70C, "M", "ρ"), + (0x1D70D, "M", "σ"), + (0x1D70F, "M", "τ"), + (0x1D710, "M", "υ"), + (0x1D711, "M", "φ"), + (0x1D712, "M", "χ"), + (0x1D713, "M", "ψ"), + (0x1D714, "M", "ω"), + (0x1D715, "M", "∂"), + (0x1D716, "M", "ε"), + (0x1D717, "M", "θ"), + (0x1D718, "M", "κ"), + (0x1D719, "M", "φ"), + (0x1D71A, "M", "ρ"), + (0x1D71B, "M", "π"), + (0x1D71C, "M", "α"), + (0x1D71D, "M", "β"), + (0x1D71E, "M", "γ"), + (0x1D71F, "M", "δ"), + (0x1D720, "M", "ε"), + (0x1D721, "M", "ζ"), + (0x1D722, "M", "η"), + (0x1D723, "M", "θ"), + (0x1D724, "M", "ι"), + (0x1D725, "M", "κ"), + (0x1D726, "M", "λ"), + (0x1D727, "M", "μ"), + (0x1D728, "M", "ν"), + (0x1D729, "M", "ξ"), + (0x1D72A, "M", "ο"), + (0x1D72B, "M", "π"), + (0x1D72C, "M", "ρ"), + (0x1D72D, "M", "θ"), + (0x1D72E, "M", "σ"), + (0x1D72F, "M", "τ"), + (0x1D730, "M", "υ"), + (0x1D731, "M", "φ"), + (0x1D732, "M", "χ"), + (0x1D733, "M", "ψ"), + (0x1D734, "M", "ω"), + (0x1D735, "M", "∇"), + (0x1D736, "M", "α"), + (0x1D737, "M", "β"), + (0x1D738, "M", "γ"), + (0x1D739, "M", "δ"), + (0x1D73A, "M", "ε"), + (0x1D73B, "M", "ζ"), + (0x1D73C, "M", "η"), + (0x1D73D, "M", "θ"), + (0x1D73E, "M", "ι"), + (0x1D73F, "M", "κ"), + (0x1D740, "M", "λ"), + (0x1D741, "M", "μ"), + (0x1D742, "M", "ν"), + (0x1D743, "M", "ξ"), + (0x1D744, "M", "ο"), + (0x1D745, "M", "π"), + (0x1D746, "M", "ρ"), + (0x1D747, "M", "σ"), + (0x1D749, "M", "τ"), + (0x1D74A, "M", "υ"), + (0x1D74B, "M", "φ"), + (0x1D74C, "M", "χ"), + (0x1D74D, "M", "ψ"), + (0x1D74E, "M", "ω"), + ] + + +def _seg_69() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1D74F, "M", "∂"), + (0x1D750, "M", "ε"), + (0x1D751, "M", "θ"), + (0x1D752, "M", "κ"), + (0x1D753, "M", "φ"), + (0x1D754, "M", "ρ"), + (0x1D755, "M", "π"), + (0x1D756, "M", "α"), + (0x1D757, "M", "β"), + (0x1D758, "M", "γ"), + (0x1D759, "M", "δ"), + (0x1D75A, "M", "ε"), + (0x1D75B, "M", "ζ"), + (0x1D75C, "M", "η"), + (0x1D75D, "M", "θ"), + (0x1D75E, "M", "ι"), + (0x1D75F, "M", "κ"), + (0x1D760, "M", "λ"), + (0x1D761, "M", "μ"), + (0x1D762, "M", "ν"), + (0x1D763, "M", "ξ"), + (0x1D764, "M", "ο"), + (0x1D765, "M", "π"), + (0x1D766, "M", "ρ"), + (0x1D767, "M", "θ"), + (0x1D768, "M", "σ"), + (0x1D769, "M", "τ"), + (0x1D76A, "M", "υ"), + (0x1D76B, "M", "φ"), + (0x1D76C, "M", "χ"), + (0x1D76D, "M", "ψ"), + (0x1D76E, "M", "ω"), + (0x1D76F, "M", "∇"), + (0x1D770, "M", "α"), + (0x1D771, "M", "β"), + (0x1D772, "M", "γ"), + (0x1D773, "M", "δ"), + (0x1D774, "M", "ε"), + (0x1D775, "M", "ζ"), + (0x1D776, "M", "η"), + (0x1D777, "M", "θ"), + (0x1D778, "M", "ι"), + (0x1D779, "M", "κ"), + (0x1D77A, "M", "λ"), + (0x1D77B, "M", "μ"), + (0x1D77C, "M", "ν"), + (0x1D77D, "M", "ξ"), + (0x1D77E, "M", "ο"), + (0x1D77F, "M", "π"), + (0x1D780, "M", "ρ"), + (0x1D781, "M", "σ"), + (0x1D783, "M", "τ"), + (0x1D784, "M", "υ"), + (0x1D785, "M", "φ"), + (0x1D786, "M", "χ"), + (0x1D787, "M", "ψ"), + (0x1D788, "M", "ω"), + (0x1D789, "M", "∂"), + (0x1D78A, "M", "ε"), + (0x1D78B, "M", "θ"), + (0x1D78C, "M", "κ"), + (0x1D78D, "M", "φ"), + (0x1D78E, "M", "ρ"), + (0x1D78F, "M", "π"), + (0x1D790, "M", "α"), + (0x1D791, "M", "β"), + (0x1D792, "M", "γ"), + (0x1D793, "M", "δ"), + (0x1D794, "M", "ε"), + (0x1D795, "M", "ζ"), + (0x1D796, "M", "η"), + (0x1D797, "M", "θ"), + (0x1D798, "M", "ι"), + (0x1D799, "M", "κ"), + (0x1D79A, "M", "λ"), + (0x1D79B, "M", "μ"), + (0x1D79C, "M", "ν"), + (0x1D79D, "M", "ξ"), + (0x1D79E, "M", "ο"), + (0x1D79F, "M", "π"), + (0x1D7A0, "M", "ρ"), + (0x1D7A1, "M", "θ"), + (0x1D7A2, "M", "σ"), + (0x1D7A3, "M", "τ"), + (0x1D7A4, "M", "υ"), + (0x1D7A5, "M", "φ"), + (0x1D7A6, "M", "χ"), + (0x1D7A7, "M", "ψ"), + (0x1D7A8, "M", "ω"), + (0x1D7A9, "M", "∇"), + (0x1D7AA, "M", "α"), + (0x1D7AB, "M", "β"), + (0x1D7AC, "M", "γ"), + (0x1D7AD, "M", "δ"), + (0x1D7AE, "M", "ε"), + (0x1D7AF, "M", "ζ"), + (0x1D7B0, "M", "η"), + (0x1D7B1, "M", "θ"), + (0x1D7B2, "M", "ι"), + (0x1D7B3, "M", "κ"), + ] + + +def _seg_70() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1D7B4, "M", "λ"), + (0x1D7B5, "M", "μ"), + (0x1D7B6, "M", "ν"), + (0x1D7B7, "M", "ξ"), + (0x1D7B8, "M", "ο"), + (0x1D7B9, "M", "π"), + (0x1D7BA, "M", "ρ"), + (0x1D7BB, "M", "σ"), + (0x1D7BD, "M", "τ"), + (0x1D7BE, "M", "υ"), + (0x1D7BF, "M", "φ"), + (0x1D7C0, "M", "χ"), + (0x1D7C1, "M", "ψ"), + (0x1D7C2, "M", "ω"), + (0x1D7C3, "M", "∂"), + (0x1D7C4, "M", "ε"), + (0x1D7C5, "M", "θ"), + (0x1D7C6, "M", "κ"), + (0x1D7C7, "M", "φ"), + (0x1D7C8, "M", "ρ"), + (0x1D7C9, "M", "π"), + (0x1D7CA, "M", "ϝ"), + (0x1D7CC, "X"), + (0x1D7CE, "M", "0"), + (0x1D7CF, "M", "1"), + (0x1D7D0, "M", "2"), + (0x1D7D1, "M", "3"), + (0x1D7D2, "M", "4"), + (0x1D7D3, "M", "5"), + (0x1D7D4, "M", "6"), + (0x1D7D5, "M", "7"), + (0x1D7D6, "M", "8"), + (0x1D7D7, "M", "9"), + (0x1D7D8, "M", "0"), + (0x1D7D9, "M", "1"), + (0x1D7DA, "M", "2"), + (0x1D7DB, "M", "3"), + (0x1D7DC, "M", "4"), + (0x1D7DD, "M", "5"), + (0x1D7DE, "M", "6"), + (0x1D7DF, "M", "7"), + (0x1D7E0, "M", "8"), + (0x1D7E1, "M", "9"), + (0x1D7E2, "M", "0"), + (0x1D7E3, "M", "1"), + (0x1D7E4, "M", "2"), + (0x1D7E5, "M", "3"), + (0x1D7E6, "M", "4"), + (0x1D7E7, "M", "5"), + (0x1D7E8, "M", "6"), + (0x1D7E9, "M", "7"), + (0x1D7EA, "M", "8"), + (0x1D7EB, "M", "9"), + (0x1D7EC, "M", "0"), + (0x1D7ED, "M", "1"), + (0x1D7EE, "M", "2"), + (0x1D7EF, "M", "3"), + (0x1D7F0, "M", "4"), + (0x1D7F1, "M", "5"), + (0x1D7F2, "M", "6"), + (0x1D7F3, "M", "7"), + (0x1D7F4, "M", "8"), + (0x1D7F5, "M", "9"), + (0x1D7F6, "M", "0"), + (0x1D7F7, "M", "1"), + (0x1D7F8, "M", "2"), + (0x1D7F9, "M", "3"), + (0x1D7FA, "M", "4"), + (0x1D7FB, "M", "5"), + (0x1D7FC, "M", "6"), + (0x1D7FD, "M", "7"), + (0x1D7FE, "M", "8"), + (0x1D7FF, "M", "9"), + (0x1D800, "V"), + (0x1DA8C, "X"), + (0x1DA9B, "V"), + (0x1DAA0, "X"), + (0x1DAA1, "V"), + (0x1DAB0, "X"), + (0x1DF00, "V"), + (0x1DF1F, "X"), + (0x1DF25, "V"), + (0x1DF2B, "X"), + (0x1E000, "V"), + (0x1E007, "X"), + (0x1E008, "V"), + (0x1E019, "X"), + (0x1E01B, "V"), + (0x1E022, "X"), + (0x1E023, "V"), + (0x1E025, "X"), + (0x1E026, "V"), + (0x1E02B, "X"), + (0x1E030, "M", "а"), + (0x1E031, "M", "б"), + (0x1E032, "M", "в"), + (0x1E033, "M", "г"), + (0x1E034, "M", "д"), + (0x1E035, "M", "е"), + (0x1E036, "M", "ж"), + ] + + +def _seg_71() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1E037, "M", "з"), + (0x1E038, "M", "и"), + (0x1E039, "M", "к"), + (0x1E03A, "M", "л"), + (0x1E03B, "M", "м"), + (0x1E03C, "M", "о"), + (0x1E03D, "M", "п"), + (0x1E03E, "M", "р"), + (0x1E03F, "M", "с"), + (0x1E040, "M", "т"), + (0x1E041, "M", "у"), + (0x1E042, "M", "ф"), + (0x1E043, "M", "х"), + (0x1E044, "M", "ц"), + (0x1E045, "M", "ч"), + (0x1E046, "M", "ш"), + (0x1E047, "M", "ы"), + (0x1E048, "M", "э"), + (0x1E049, "M", "ю"), + (0x1E04A, "M", "ꚉ"), + (0x1E04B, "M", "ә"), + (0x1E04C, "M", "і"), + (0x1E04D, "M", "ј"), + (0x1E04E, "M", "ө"), + (0x1E04F, "M", "ү"), + (0x1E050, "M", "ӏ"), + (0x1E051, "M", "а"), + (0x1E052, "M", "б"), + (0x1E053, "M", "в"), + (0x1E054, "M", "г"), + (0x1E055, "M", "д"), + (0x1E056, "M", "е"), + (0x1E057, "M", "ж"), + (0x1E058, "M", "з"), + (0x1E059, "M", "и"), + (0x1E05A, "M", "к"), + (0x1E05B, "M", "л"), + (0x1E05C, "M", "о"), + (0x1E05D, "M", "п"), + (0x1E05E, "M", "с"), + (0x1E05F, "M", "у"), + (0x1E060, "M", "ф"), + (0x1E061, "M", "х"), + (0x1E062, "M", "ц"), + (0x1E063, "M", "ч"), + (0x1E064, "M", "ш"), + (0x1E065, "M", "ъ"), + (0x1E066, "M", "ы"), + (0x1E067, "M", "ґ"), + (0x1E068, "M", "і"), + (0x1E069, "M", "ѕ"), + (0x1E06A, "M", "џ"), + (0x1E06B, "M", "ҫ"), + (0x1E06C, "M", "ꙑ"), + (0x1E06D, "M", "ұ"), + (0x1E06E, "X"), + (0x1E08F, "V"), + (0x1E090, "X"), + (0x1E100, "V"), + (0x1E12D, "X"), + (0x1E130, "V"), + (0x1E13E, "X"), + (0x1E140, "V"), + (0x1E14A, "X"), + (0x1E14E, "V"), + (0x1E150, "X"), + (0x1E290, "V"), + (0x1E2AF, "X"), + (0x1E2C0, "V"), + (0x1E2FA, "X"), + (0x1E2FF, "V"), + (0x1E300, "X"), + (0x1E4D0, "V"), + (0x1E4FA, "X"), + (0x1E7E0, "V"), + (0x1E7E7, "X"), + (0x1E7E8, "V"), + (0x1E7EC, "X"), + (0x1E7ED, "V"), + (0x1E7EF, "X"), + (0x1E7F0, "V"), + (0x1E7FF, "X"), + (0x1E800, "V"), + (0x1E8C5, "X"), + (0x1E8C7, "V"), + (0x1E8D7, "X"), + (0x1E900, "M", "𞤢"), + (0x1E901, "M", "𞤣"), + (0x1E902, "M", "𞤤"), + (0x1E903, "M", "𞤥"), + (0x1E904, "M", "𞤦"), + (0x1E905, "M", "𞤧"), + (0x1E906, "M", "𞤨"), + (0x1E907, "M", "𞤩"), + (0x1E908, "M", "𞤪"), + (0x1E909, "M", "𞤫"), + (0x1E90A, "M", "𞤬"), + (0x1E90B, "M", "𞤭"), + (0x1E90C, "M", "𞤮"), + (0x1E90D, "M", "𞤯"), + ] + + +def _seg_72() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1E90E, "M", "𞤰"), + (0x1E90F, "M", "𞤱"), + (0x1E910, "M", "𞤲"), + (0x1E911, "M", "𞤳"), + (0x1E912, "M", "𞤴"), + (0x1E913, "M", "𞤵"), + (0x1E914, "M", "𞤶"), + (0x1E915, "M", "𞤷"), + (0x1E916, "M", "𞤸"), + (0x1E917, "M", "𞤹"), + (0x1E918, "M", "𞤺"), + (0x1E919, "M", "𞤻"), + (0x1E91A, "M", "𞤼"), + (0x1E91B, "M", "𞤽"), + (0x1E91C, "M", "𞤾"), + (0x1E91D, "M", "𞤿"), + (0x1E91E, "M", "𞥀"), + (0x1E91F, "M", "𞥁"), + (0x1E920, "M", "𞥂"), + (0x1E921, "M", "𞥃"), + (0x1E922, "V"), + (0x1E94C, "X"), + (0x1E950, "V"), + (0x1E95A, "X"), + (0x1E95E, "V"), + (0x1E960, "X"), + (0x1EC71, "V"), + (0x1ECB5, "X"), + (0x1ED01, "V"), + (0x1ED3E, "X"), + (0x1EE00, "M", "ا"), + (0x1EE01, "M", "ب"), + (0x1EE02, "M", "ج"), + (0x1EE03, "M", "د"), + (0x1EE04, "X"), + (0x1EE05, "M", "و"), + (0x1EE06, "M", "ز"), + (0x1EE07, "M", "ح"), + (0x1EE08, "M", "ط"), + (0x1EE09, "M", "ي"), + (0x1EE0A, "M", "ك"), + (0x1EE0B, "M", "ل"), + (0x1EE0C, "M", "م"), + (0x1EE0D, "M", "ن"), + (0x1EE0E, "M", "س"), + (0x1EE0F, "M", "ع"), + (0x1EE10, "M", "ف"), + (0x1EE11, "M", "ص"), + (0x1EE12, "M", "ق"), + (0x1EE13, "M", "ر"), + (0x1EE14, "M", "ش"), + (0x1EE15, "M", "ت"), + (0x1EE16, "M", "ث"), + (0x1EE17, "M", "خ"), + (0x1EE18, "M", "ذ"), + (0x1EE19, "M", "ض"), + (0x1EE1A, "M", "ظ"), + (0x1EE1B, "M", "غ"), + (0x1EE1C, "M", "ٮ"), + (0x1EE1D, "M", "ں"), + (0x1EE1E, "M", "ڡ"), + (0x1EE1F, "M", "ٯ"), + (0x1EE20, "X"), + (0x1EE21, "M", "ب"), + (0x1EE22, "M", "ج"), + (0x1EE23, "X"), + (0x1EE24, "M", "ه"), + (0x1EE25, "X"), + (0x1EE27, "M", "ح"), + (0x1EE28, "X"), + (0x1EE29, "M", "ي"), + (0x1EE2A, "M", "ك"), + (0x1EE2B, "M", "ل"), + (0x1EE2C, "M", "م"), + (0x1EE2D, "M", "ن"), + (0x1EE2E, "M", "س"), + (0x1EE2F, "M", "ع"), + (0x1EE30, "M", "ف"), + (0x1EE31, "M", "ص"), + (0x1EE32, "M", "ق"), + (0x1EE33, "X"), + (0x1EE34, "M", "ش"), + (0x1EE35, "M", "ت"), + (0x1EE36, "M", "ث"), + (0x1EE37, "M", "خ"), + (0x1EE38, "X"), + (0x1EE39, "M", "ض"), + (0x1EE3A, "X"), + (0x1EE3B, "M", "غ"), + (0x1EE3C, "X"), + (0x1EE42, "M", "ج"), + (0x1EE43, "X"), + (0x1EE47, "M", "ح"), + (0x1EE48, "X"), + (0x1EE49, "M", "ي"), + (0x1EE4A, "X"), + (0x1EE4B, "M", "ل"), + (0x1EE4C, "X"), + (0x1EE4D, "M", "ن"), + (0x1EE4E, "M", "س"), + ] + + +def _seg_73() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1EE4F, "M", "ع"), + (0x1EE50, "X"), + (0x1EE51, "M", "ص"), + (0x1EE52, "M", "ق"), + (0x1EE53, "X"), + (0x1EE54, "M", "ش"), + (0x1EE55, "X"), + (0x1EE57, "M", "خ"), + (0x1EE58, "X"), + (0x1EE59, "M", "ض"), + (0x1EE5A, "X"), + (0x1EE5B, "M", "غ"), + (0x1EE5C, "X"), + (0x1EE5D, "M", "ں"), + (0x1EE5E, "X"), + (0x1EE5F, "M", "ٯ"), + (0x1EE60, "X"), + (0x1EE61, "M", "ب"), + (0x1EE62, "M", "ج"), + (0x1EE63, "X"), + (0x1EE64, "M", "ه"), + (0x1EE65, "X"), + (0x1EE67, "M", "ح"), + (0x1EE68, "M", "ط"), + (0x1EE69, "M", "ي"), + (0x1EE6A, "M", "ك"), + (0x1EE6B, "X"), + (0x1EE6C, "M", "م"), + (0x1EE6D, "M", "ن"), + (0x1EE6E, "M", "س"), + (0x1EE6F, "M", "ع"), + (0x1EE70, "M", "ف"), + (0x1EE71, "M", "ص"), + (0x1EE72, "M", "ق"), + (0x1EE73, "X"), + (0x1EE74, "M", "ش"), + (0x1EE75, "M", "ت"), + (0x1EE76, "M", "ث"), + (0x1EE77, "M", "خ"), + (0x1EE78, "X"), + (0x1EE79, "M", "ض"), + (0x1EE7A, "M", "ظ"), + (0x1EE7B, "M", "غ"), + (0x1EE7C, "M", "ٮ"), + (0x1EE7D, "X"), + (0x1EE7E, "M", "ڡ"), + (0x1EE7F, "X"), + (0x1EE80, "M", "ا"), + (0x1EE81, "M", "ب"), + (0x1EE82, "M", "ج"), + (0x1EE83, "M", "د"), + (0x1EE84, "M", "ه"), + (0x1EE85, "M", "و"), + (0x1EE86, "M", "ز"), + (0x1EE87, "M", "ح"), + (0x1EE88, "M", "ط"), + (0x1EE89, "M", "ي"), + (0x1EE8A, "X"), + (0x1EE8B, "M", "ل"), + (0x1EE8C, "M", "م"), + (0x1EE8D, "M", "ن"), + (0x1EE8E, "M", "س"), + (0x1EE8F, "M", "ع"), + (0x1EE90, "M", "ف"), + (0x1EE91, "M", "ص"), + (0x1EE92, "M", "ق"), + (0x1EE93, "M", "ر"), + (0x1EE94, "M", "ش"), + (0x1EE95, "M", "ت"), + (0x1EE96, "M", "ث"), + (0x1EE97, "M", "خ"), + (0x1EE98, "M", "ذ"), + (0x1EE99, "M", "ض"), + (0x1EE9A, "M", "ظ"), + (0x1EE9B, "M", "غ"), + (0x1EE9C, "X"), + (0x1EEA1, "M", "ب"), + (0x1EEA2, "M", "ج"), + (0x1EEA3, "M", "د"), + (0x1EEA4, "X"), + (0x1EEA5, "M", "و"), + (0x1EEA6, "M", "ز"), + (0x1EEA7, "M", "ح"), + (0x1EEA8, "M", "ط"), + (0x1EEA9, "M", "ي"), + (0x1EEAA, "X"), + (0x1EEAB, "M", "ل"), + (0x1EEAC, "M", "م"), + (0x1EEAD, "M", "ن"), + (0x1EEAE, "M", "س"), + (0x1EEAF, "M", "ع"), + (0x1EEB0, "M", "ف"), + (0x1EEB1, "M", "ص"), + (0x1EEB2, "M", "ق"), + (0x1EEB3, "M", "ر"), + (0x1EEB4, "M", "ش"), + (0x1EEB5, "M", "ت"), + (0x1EEB6, "M", "ث"), + (0x1EEB7, "M", "خ"), + (0x1EEB8, "M", "ذ"), + ] + + +def _seg_74() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1EEB9, "M", "ض"), + (0x1EEBA, "M", "ظ"), + (0x1EEBB, "M", "غ"), + (0x1EEBC, "X"), + (0x1EEF0, "V"), + (0x1EEF2, "X"), + (0x1F000, "V"), + (0x1F02C, "X"), + (0x1F030, "V"), + (0x1F094, "X"), + (0x1F0A0, "V"), + (0x1F0AF, "X"), + (0x1F0B1, "V"), + (0x1F0C0, "X"), + (0x1F0C1, "V"), + (0x1F0D0, "X"), + (0x1F0D1, "V"), + (0x1F0F6, "X"), + (0x1F101, "3", "0,"), + (0x1F102, "3", "1,"), + (0x1F103, "3", "2,"), + (0x1F104, "3", "3,"), + (0x1F105, "3", "4,"), + (0x1F106, "3", "5,"), + (0x1F107, "3", "6,"), + (0x1F108, "3", "7,"), + (0x1F109, "3", "8,"), + (0x1F10A, "3", "9,"), + (0x1F10B, "V"), + (0x1F110, "3", "(a)"), + (0x1F111, "3", "(b)"), + (0x1F112, "3", "(c)"), + (0x1F113, "3", "(d)"), + (0x1F114, "3", "(e)"), + (0x1F115, "3", "(f)"), + (0x1F116, "3", "(g)"), + (0x1F117, "3", "(h)"), + (0x1F118, "3", "(i)"), + (0x1F119, "3", "(j)"), + (0x1F11A, "3", "(k)"), + (0x1F11B, "3", "(l)"), + (0x1F11C, "3", "(m)"), + (0x1F11D, "3", "(n)"), + (0x1F11E, "3", "(o)"), + (0x1F11F, "3", "(p)"), + (0x1F120, "3", "(q)"), + (0x1F121, "3", "(r)"), + (0x1F122, "3", "(s)"), + (0x1F123, "3", "(t)"), + (0x1F124, "3", "(u)"), + (0x1F125, "3", "(v)"), + (0x1F126, "3", "(w)"), + (0x1F127, "3", "(x)"), + (0x1F128, "3", "(y)"), + (0x1F129, "3", "(z)"), + (0x1F12A, "M", "〔s〕"), + (0x1F12B, "M", "c"), + (0x1F12C, "M", "r"), + (0x1F12D, "M", "cd"), + (0x1F12E, "M", "wz"), + (0x1F12F, "V"), + (0x1F130, "M", "a"), + (0x1F131, "M", "b"), + (0x1F132, "M", "c"), + (0x1F133, "M", "d"), + (0x1F134, "M", "e"), + (0x1F135, "M", "f"), + (0x1F136, "M", "g"), + (0x1F137, "M", "h"), + (0x1F138, "M", "i"), + (0x1F139, "M", "j"), + (0x1F13A, "M", "k"), + (0x1F13B, "M", "l"), + (0x1F13C, "M", "m"), + (0x1F13D, "M", "n"), + (0x1F13E, "M", "o"), + (0x1F13F, "M", "p"), + (0x1F140, "M", "q"), + (0x1F141, "M", "r"), + (0x1F142, "M", "s"), + (0x1F143, "M", "t"), + (0x1F144, "M", "u"), + (0x1F145, "M", "v"), + (0x1F146, "M", "w"), + (0x1F147, "M", "x"), + (0x1F148, "M", "y"), + (0x1F149, "M", "z"), + (0x1F14A, "M", "hv"), + (0x1F14B, "M", "mv"), + (0x1F14C, "M", "sd"), + (0x1F14D, "M", "ss"), + (0x1F14E, "M", "ppv"), + (0x1F14F, "M", "wc"), + (0x1F150, "V"), + (0x1F16A, "M", "mc"), + (0x1F16B, "M", "md"), + (0x1F16C, "M", "mr"), + (0x1F16D, "V"), + (0x1F190, "M", "dj"), + (0x1F191, "V"), + ] + + +def _seg_75() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1F1AE, "X"), + (0x1F1E6, "V"), + (0x1F200, "M", "ほか"), + (0x1F201, "M", "ココ"), + (0x1F202, "M", "サ"), + (0x1F203, "X"), + (0x1F210, "M", "手"), + (0x1F211, "M", "字"), + (0x1F212, "M", "双"), + (0x1F213, "M", "デ"), + (0x1F214, "M", "二"), + (0x1F215, "M", "多"), + (0x1F216, "M", "解"), + (0x1F217, "M", "天"), + (0x1F218, "M", "交"), + (0x1F219, "M", "映"), + (0x1F21A, "M", "無"), + (0x1F21B, "M", "料"), + (0x1F21C, "M", "前"), + (0x1F21D, "M", "後"), + (0x1F21E, "M", "再"), + (0x1F21F, "M", "新"), + (0x1F220, "M", "初"), + (0x1F221, "M", "終"), + (0x1F222, "M", "生"), + (0x1F223, "M", "販"), + (0x1F224, "M", "声"), + (0x1F225, "M", "吹"), + (0x1F226, "M", "演"), + (0x1F227, "M", "投"), + (0x1F228, "M", "捕"), + (0x1F229, "M", "一"), + (0x1F22A, "M", "三"), + (0x1F22B, "M", "遊"), + (0x1F22C, "M", "左"), + (0x1F22D, "M", "中"), + (0x1F22E, "M", "右"), + (0x1F22F, "M", "指"), + (0x1F230, "M", "走"), + (0x1F231, "M", "打"), + (0x1F232, "M", "禁"), + (0x1F233, "M", "空"), + (0x1F234, "M", "合"), + (0x1F235, "M", "満"), + (0x1F236, "M", "有"), + (0x1F237, "M", "月"), + (0x1F238, "M", "申"), + (0x1F239, "M", "割"), + (0x1F23A, "M", "営"), + (0x1F23B, "M", "配"), + (0x1F23C, "X"), + (0x1F240, "M", "〔本〕"), + (0x1F241, "M", "〔三〕"), + (0x1F242, "M", "〔二〕"), + (0x1F243, "M", "〔安〕"), + (0x1F244, "M", "〔点〕"), + (0x1F245, "M", "〔打〕"), + (0x1F246, "M", "〔盗〕"), + (0x1F247, "M", "〔勝〕"), + (0x1F248, "M", "〔敗〕"), + (0x1F249, "X"), + (0x1F250, "M", "得"), + (0x1F251, "M", "可"), + (0x1F252, "X"), + (0x1F260, "V"), + (0x1F266, "X"), + (0x1F300, "V"), + (0x1F6D8, "X"), + (0x1F6DC, "V"), + (0x1F6ED, "X"), + (0x1F6F0, "V"), + (0x1F6FD, "X"), + (0x1F700, "V"), + (0x1F777, "X"), + (0x1F77B, "V"), + (0x1F7DA, "X"), + (0x1F7E0, "V"), + (0x1F7EC, "X"), + (0x1F7F0, "V"), + (0x1F7F1, "X"), + (0x1F800, "V"), + (0x1F80C, "X"), + (0x1F810, "V"), + (0x1F848, "X"), + (0x1F850, "V"), + (0x1F85A, "X"), + (0x1F860, "V"), + (0x1F888, "X"), + (0x1F890, "V"), + (0x1F8AE, "X"), + (0x1F8B0, "V"), + (0x1F8B2, "X"), + (0x1F900, "V"), + (0x1FA54, "X"), + (0x1FA60, "V"), + (0x1FA6E, "X"), + (0x1FA70, "V"), + (0x1FA7D, "X"), + (0x1FA80, "V"), + (0x1FA89, "X"), + ] + + +def _seg_76() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x1FA90, "V"), + (0x1FABE, "X"), + (0x1FABF, "V"), + (0x1FAC6, "X"), + (0x1FACE, "V"), + (0x1FADC, "X"), + (0x1FAE0, "V"), + (0x1FAE9, "X"), + (0x1FAF0, "V"), + (0x1FAF9, "X"), + (0x1FB00, "V"), + (0x1FB93, "X"), + (0x1FB94, "V"), + (0x1FBCB, "X"), + (0x1FBF0, "M", "0"), + (0x1FBF1, "M", "1"), + (0x1FBF2, "M", "2"), + (0x1FBF3, "M", "3"), + (0x1FBF4, "M", "4"), + (0x1FBF5, "M", "5"), + (0x1FBF6, "M", "6"), + (0x1FBF7, "M", "7"), + (0x1FBF8, "M", "8"), + (0x1FBF9, "M", "9"), + (0x1FBFA, "X"), + (0x20000, "V"), + (0x2A6E0, "X"), + (0x2A700, "V"), + (0x2B73A, "X"), + (0x2B740, "V"), + (0x2B81E, "X"), + (0x2B820, "V"), + (0x2CEA2, "X"), + (0x2CEB0, "V"), + (0x2EBE1, "X"), + (0x2EBF0, "V"), + (0x2EE5E, "X"), + (0x2F800, "M", "丽"), + (0x2F801, "M", "丸"), + (0x2F802, "M", "乁"), + (0x2F803, "M", "𠄢"), + (0x2F804, "M", "你"), + (0x2F805, "M", "侮"), + (0x2F806, "M", "侻"), + (0x2F807, "M", "倂"), + (0x2F808, "M", "偺"), + (0x2F809, "M", "備"), + (0x2F80A, "M", "僧"), + (0x2F80B, "M", "像"), + (0x2F80C, "M", "㒞"), + (0x2F80D, "M", "𠘺"), + (0x2F80E, "M", "免"), + (0x2F80F, "M", "兔"), + (0x2F810, "M", "兤"), + (0x2F811, "M", "具"), + (0x2F812, "M", "𠔜"), + (0x2F813, "M", "㒹"), + (0x2F814, "M", "內"), + (0x2F815, "M", "再"), + (0x2F816, "M", "𠕋"), + (0x2F817, "M", "冗"), + (0x2F818, "M", "冤"), + (0x2F819, "M", "仌"), + (0x2F81A, "M", "冬"), + (0x2F81B, "M", "况"), + (0x2F81C, "M", "𩇟"), + (0x2F81D, "M", "凵"), + (0x2F81E, "M", "刃"), + (0x2F81F, "M", "㓟"), + (0x2F820, "M", "刻"), + (0x2F821, "M", "剆"), + (0x2F822, "M", "割"), + (0x2F823, "M", "剷"), + (0x2F824, "M", "㔕"), + (0x2F825, "M", "勇"), + (0x2F826, "M", "勉"), + (0x2F827, "M", "勤"), + (0x2F828, "M", "勺"), + (0x2F829, "M", "包"), + (0x2F82A, "M", "匆"), + (0x2F82B, "M", "北"), + (0x2F82C, "M", "卉"), + (0x2F82D, "M", "卑"), + (0x2F82E, "M", "博"), + (0x2F82F, "M", "即"), + (0x2F830, "M", "卽"), + (0x2F831, "M", "卿"), + (0x2F834, "M", "𠨬"), + (0x2F835, "M", "灰"), + (0x2F836, "M", "及"), + (0x2F837, "M", "叟"), + (0x2F838, "M", "𠭣"), + (0x2F839, "M", "叫"), + (0x2F83A, "M", "叱"), + (0x2F83B, "M", "吆"), + (0x2F83C, "M", "咞"), + (0x2F83D, "M", "吸"), + (0x2F83E, "M", "呈"), + (0x2F83F, "M", "周"), + (0x2F840, "M", "咢"), + ] + + +def _seg_77() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x2F841, "M", "哶"), + (0x2F842, "M", "唐"), + (0x2F843, "M", "啓"), + (0x2F844, "M", "啣"), + (0x2F845, "M", "善"), + (0x2F847, "M", "喙"), + (0x2F848, "M", "喫"), + (0x2F849, "M", "喳"), + (0x2F84A, "M", "嗂"), + (0x2F84B, "M", "圖"), + (0x2F84C, "M", "嘆"), + (0x2F84D, "M", "圗"), + (0x2F84E, "M", "噑"), + (0x2F84F, "M", "噴"), + (0x2F850, "M", "切"), + (0x2F851, "M", "壮"), + (0x2F852, "M", "城"), + (0x2F853, "M", "埴"), + (0x2F854, "M", "堍"), + (0x2F855, "M", "型"), + (0x2F856, "M", "堲"), + (0x2F857, "M", "報"), + (0x2F858, "M", "墬"), + (0x2F859, "M", "𡓤"), + (0x2F85A, "M", "売"), + (0x2F85B, "M", "壷"), + (0x2F85C, "M", "夆"), + (0x2F85D, "M", "多"), + (0x2F85E, "M", "夢"), + (0x2F85F, "M", "奢"), + (0x2F860, "M", "𡚨"), + (0x2F861, "M", "𡛪"), + (0x2F862, "M", "姬"), + (0x2F863, "M", "娛"), + (0x2F864, "M", "娧"), + (0x2F865, "M", "姘"), + (0x2F866, "M", "婦"), + (0x2F867, "M", "㛮"), + (0x2F868, "X"), + (0x2F869, "M", "嬈"), + (0x2F86A, "M", "嬾"), + (0x2F86C, "M", "𡧈"), + (0x2F86D, "M", "寃"), + (0x2F86E, "M", "寘"), + (0x2F86F, "M", "寧"), + (0x2F870, "M", "寳"), + (0x2F871, "M", "𡬘"), + (0x2F872, "M", "寿"), + (0x2F873, "M", "将"), + (0x2F874, "X"), + (0x2F875, "M", "尢"), + (0x2F876, "M", "㞁"), + (0x2F877, "M", "屠"), + (0x2F878, "M", "屮"), + (0x2F879, "M", "峀"), + (0x2F87A, "M", "岍"), + (0x2F87B, "M", "𡷤"), + (0x2F87C, "M", "嵃"), + (0x2F87D, "M", "𡷦"), + (0x2F87E, "M", "嵮"), + (0x2F87F, "M", "嵫"), + (0x2F880, "M", "嵼"), + (0x2F881, "M", "巡"), + (0x2F882, "M", "巢"), + (0x2F883, "M", "㠯"), + (0x2F884, "M", "巽"), + (0x2F885, "M", "帨"), + (0x2F886, "M", "帽"), + (0x2F887, "M", "幩"), + (0x2F888, "M", "㡢"), + (0x2F889, "M", "𢆃"), + (0x2F88A, "M", "㡼"), + (0x2F88B, "M", "庰"), + (0x2F88C, "M", "庳"), + (0x2F88D, "M", "庶"), + (0x2F88E, "M", "廊"), + (0x2F88F, "M", "𪎒"), + (0x2F890, "M", "廾"), + (0x2F891, "M", "𢌱"), + (0x2F893, "M", "舁"), + (0x2F894, "M", "弢"), + (0x2F896, "M", "㣇"), + (0x2F897, "M", "𣊸"), + (0x2F898, "M", "𦇚"), + (0x2F899, "M", "形"), + (0x2F89A, "M", "彫"), + (0x2F89B, "M", "㣣"), + (0x2F89C, "M", "徚"), + (0x2F89D, "M", "忍"), + (0x2F89E, "M", "志"), + (0x2F89F, "M", "忹"), + (0x2F8A0, "M", "悁"), + (0x2F8A1, "M", "㤺"), + (0x2F8A2, "M", "㤜"), + (0x2F8A3, "M", "悔"), + (0x2F8A4, "M", "𢛔"), + (0x2F8A5, "M", "惇"), + (0x2F8A6, "M", "慈"), + (0x2F8A7, "M", "慌"), + (0x2F8A8, "M", "慎"), + ] + + +def _seg_78() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x2F8A9, "M", "慌"), + (0x2F8AA, "M", "慺"), + (0x2F8AB, "M", "憎"), + (0x2F8AC, "M", "憲"), + (0x2F8AD, "M", "憤"), + (0x2F8AE, "M", "憯"), + (0x2F8AF, "M", "懞"), + (0x2F8B0, "M", "懲"), + (0x2F8B1, "M", "懶"), + (0x2F8B2, "M", "成"), + (0x2F8B3, "M", "戛"), + (0x2F8B4, "M", "扝"), + (0x2F8B5, "M", "抱"), + (0x2F8B6, "M", "拔"), + (0x2F8B7, "M", "捐"), + (0x2F8B8, "M", "𢬌"), + (0x2F8B9, "M", "挽"), + (0x2F8BA, "M", "拼"), + (0x2F8BB, "M", "捨"), + (0x2F8BC, "M", "掃"), + (0x2F8BD, "M", "揤"), + (0x2F8BE, "M", "𢯱"), + (0x2F8BF, "M", "搢"), + (0x2F8C0, "M", "揅"), + (0x2F8C1, "M", "掩"), + (0x2F8C2, "M", "㨮"), + (0x2F8C3, "M", "摩"), + (0x2F8C4, "M", "摾"), + (0x2F8C5, "M", "撝"), + (0x2F8C6, "M", "摷"), + (0x2F8C7, "M", "㩬"), + (0x2F8C8, "M", "敏"), + (0x2F8C9, "M", "敬"), + (0x2F8CA, "M", "𣀊"), + (0x2F8CB, "M", "旣"), + (0x2F8CC, "M", "書"), + (0x2F8CD, "M", "晉"), + (0x2F8CE, "M", "㬙"), + (0x2F8CF, "M", "暑"), + (0x2F8D0, "M", "㬈"), + (0x2F8D1, "M", "㫤"), + (0x2F8D2, "M", "冒"), + (0x2F8D3, "M", "冕"), + (0x2F8D4, "M", "最"), + (0x2F8D5, "M", "暜"), + (0x2F8D6, "M", "肭"), + (0x2F8D7, "M", "䏙"), + (0x2F8D8, "M", "朗"), + (0x2F8D9, "M", "望"), + (0x2F8DA, "M", "朡"), + (0x2F8DB, "M", "杞"), + (0x2F8DC, "M", "杓"), + (0x2F8DD, "M", "𣏃"), + (0x2F8DE, "M", "㭉"), + (0x2F8DF, "M", "柺"), + (0x2F8E0, "M", "枅"), + (0x2F8E1, "M", "桒"), + (0x2F8E2, "M", "梅"), + (0x2F8E3, "M", "𣑭"), + (0x2F8E4, "M", "梎"), + (0x2F8E5, "M", "栟"), + (0x2F8E6, "M", "椔"), + (0x2F8E7, "M", "㮝"), + (0x2F8E8, "M", "楂"), + (0x2F8E9, "M", "榣"), + (0x2F8EA, "M", "槪"), + (0x2F8EB, "M", "檨"), + (0x2F8EC, "M", "𣚣"), + (0x2F8ED, "M", "櫛"), + (0x2F8EE, "M", "㰘"), + (0x2F8EF, "M", "次"), + (0x2F8F0, "M", "𣢧"), + (0x2F8F1, "M", "歔"), + (0x2F8F2, "M", "㱎"), + (0x2F8F3, "M", "歲"), + (0x2F8F4, "M", "殟"), + (0x2F8F5, "M", "殺"), + (0x2F8F6, "M", "殻"), + (0x2F8F7, "M", "𣪍"), + (0x2F8F8, "M", "𡴋"), + (0x2F8F9, "M", "𣫺"), + (0x2F8FA, "M", "汎"), + (0x2F8FB, "M", "𣲼"), + (0x2F8FC, "M", "沿"), + (0x2F8FD, "M", "泍"), + (0x2F8FE, "M", "汧"), + (0x2F8FF, "M", "洖"), + (0x2F900, "M", "派"), + (0x2F901, "M", "海"), + (0x2F902, "M", "流"), + (0x2F903, "M", "浩"), + (0x2F904, "M", "浸"), + (0x2F905, "M", "涅"), + (0x2F906, "M", "𣴞"), + (0x2F907, "M", "洴"), + (0x2F908, "M", "港"), + (0x2F909, "M", "湮"), + (0x2F90A, "M", "㴳"), + (0x2F90B, "M", "滋"), + (0x2F90C, "M", "滇"), + ] + + +def _seg_79() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x2F90D, "M", "𣻑"), + (0x2F90E, "M", "淹"), + (0x2F90F, "M", "潮"), + (0x2F910, "M", "𣽞"), + (0x2F911, "M", "𣾎"), + (0x2F912, "M", "濆"), + (0x2F913, "M", "瀹"), + (0x2F914, "M", "瀞"), + (0x2F915, "M", "瀛"), + (0x2F916, "M", "㶖"), + (0x2F917, "M", "灊"), + (0x2F918, "M", "災"), + (0x2F919, "M", "灷"), + (0x2F91A, "M", "炭"), + (0x2F91B, "M", "𠔥"), + (0x2F91C, "M", "煅"), + (0x2F91D, "M", "𤉣"), + (0x2F91E, "M", "熜"), + (0x2F91F, "X"), + (0x2F920, "M", "爨"), + (0x2F921, "M", "爵"), + (0x2F922, "M", "牐"), + (0x2F923, "M", "𤘈"), + (0x2F924, "M", "犀"), + (0x2F925, "M", "犕"), + (0x2F926, "M", "𤜵"), + (0x2F927, "M", "𤠔"), + (0x2F928, "M", "獺"), + (0x2F929, "M", "王"), + (0x2F92A, "M", "㺬"), + (0x2F92B, "M", "玥"), + (0x2F92C, "M", "㺸"), + (0x2F92E, "M", "瑇"), + (0x2F92F, "M", "瑜"), + (0x2F930, "M", "瑱"), + (0x2F931, "M", "璅"), + (0x2F932, "M", "瓊"), + (0x2F933, "M", "㼛"), + (0x2F934, "M", "甤"), + (0x2F935, "M", "𤰶"), + (0x2F936, "M", "甾"), + (0x2F937, "M", "𤲒"), + (0x2F938, "M", "異"), + (0x2F939, "M", "𢆟"), + (0x2F93A, "M", "瘐"), + (0x2F93B, "M", "𤾡"), + (0x2F93C, "M", "𤾸"), + (0x2F93D, "M", "𥁄"), + (0x2F93E, "M", "㿼"), + (0x2F93F, "M", "䀈"), + (0x2F940, "M", "直"), + (0x2F941, "M", "𥃳"), + (0x2F942, "M", "𥃲"), + (0x2F943, "M", "𥄙"), + (0x2F944, "M", "𥄳"), + (0x2F945, "M", "眞"), + (0x2F946, "M", "真"), + (0x2F948, "M", "睊"), + (0x2F949, "M", "䀹"), + (0x2F94A, "M", "瞋"), + (0x2F94B, "M", "䁆"), + (0x2F94C, "M", "䂖"), + (0x2F94D, "M", "𥐝"), + (0x2F94E, "M", "硎"), + (0x2F94F, "M", "碌"), + (0x2F950, "M", "磌"), + (0x2F951, "M", "䃣"), + (0x2F952, "M", "𥘦"), + (0x2F953, "M", "祖"), + (0x2F954, "M", "𥚚"), + (0x2F955, "M", "𥛅"), + (0x2F956, "M", "福"), + (0x2F957, "M", "秫"), + (0x2F958, "M", "䄯"), + (0x2F959, "M", "穀"), + (0x2F95A, "M", "穊"), + (0x2F95B, "M", "穏"), + (0x2F95C, "M", "𥥼"), + (0x2F95D, "M", "𥪧"), + (0x2F95F, "X"), + (0x2F960, "M", "䈂"), + (0x2F961, "M", "𥮫"), + (0x2F962, "M", "篆"), + (0x2F963, "M", "築"), + (0x2F964, "M", "䈧"), + (0x2F965, "M", "𥲀"), + (0x2F966, "M", "糒"), + (0x2F967, "M", "䊠"), + (0x2F968, "M", "糨"), + (0x2F969, "M", "糣"), + (0x2F96A, "M", "紀"), + (0x2F96B, "M", "𥾆"), + (0x2F96C, "M", "絣"), + (0x2F96D, "M", "䌁"), + (0x2F96E, "M", "緇"), + (0x2F96F, "M", "縂"), + (0x2F970, "M", "繅"), + (0x2F971, "M", "䌴"), + (0x2F972, "M", "𦈨"), + (0x2F973, "M", "𦉇"), + ] + + +def _seg_80() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x2F974, "M", "䍙"), + (0x2F975, "M", "𦋙"), + (0x2F976, "M", "罺"), + (0x2F977, "M", "𦌾"), + (0x2F978, "M", "羕"), + (0x2F979, "M", "翺"), + (0x2F97A, "M", "者"), + (0x2F97B, "M", "𦓚"), + (0x2F97C, "M", "𦔣"), + (0x2F97D, "M", "聠"), + (0x2F97E, "M", "𦖨"), + (0x2F97F, "M", "聰"), + (0x2F980, "M", "𣍟"), + (0x2F981, "M", "䏕"), + (0x2F982, "M", "育"), + (0x2F983, "M", "脃"), + (0x2F984, "M", "䐋"), + (0x2F985, "M", "脾"), + (0x2F986, "M", "媵"), + (0x2F987, "M", "𦞧"), + (0x2F988, "M", "𦞵"), + (0x2F989, "M", "𣎓"), + (0x2F98A, "M", "𣎜"), + (0x2F98B, "M", "舁"), + (0x2F98C, "M", "舄"), + (0x2F98D, "M", "辞"), + (0x2F98E, "M", "䑫"), + (0x2F98F, "M", "芑"), + (0x2F990, "M", "芋"), + (0x2F991, "M", "芝"), + (0x2F992, "M", "劳"), + (0x2F993, "M", "花"), + (0x2F994, "M", "芳"), + (0x2F995, "M", "芽"), + (0x2F996, "M", "苦"), + (0x2F997, "M", "𦬼"), + (0x2F998, "M", "若"), + (0x2F999, "M", "茝"), + (0x2F99A, "M", "荣"), + (0x2F99B, "M", "莭"), + (0x2F99C, "M", "茣"), + (0x2F99D, "M", "莽"), + (0x2F99E, "M", "菧"), + (0x2F99F, "M", "著"), + (0x2F9A0, "M", "荓"), + (0x2F9A1, "M", "菊"), + (0x2F9A2, "M", "菌"), + (0x2F9A3, "M", "菜"), + (0x2F9A4, "M", "𦰶"), + (0x2F9A5, "M", "𦵫"), + (0x2F9A6, "M", "𦳕"), + (0x2F9A7, "M", "䔫"), + (0x2F9A8, "M", "蓱"), + (0x2F9A9, "M", "蓳"), + (0x2F9AA, "M", "蔖"), + (0x2F9AB, "M", "𧏊"), + (0x2F9AC, "M", "蕤"), + (0x2F9AD, "M", "𦼬"), + (0x2F9AE, "M", "䕝"), + (0x2F9AF, "M", "䕡"), + (0x2F9B0, "M", "𦾱"), + (0x2F9B1, "M", "𧃒"), + (0x2F9B2, "M", "䕫"), + (0x2F9B3, "M", "虐"), + (0x2F9B4, "M", "虜"), + (0x2F9B5, "M", "虧"), + (0x2F9B6, "M", "虩"), + (0x2F9B7, "M", "蚩"), + (0x2F9B8, "M", "蚈"), + (0x2F9B9, "M", "蜎"), + (0x2F9BA, "M", "蛢"), + (0x2F9BB, "M", "蝹"), + (0x2F9BC, "M", "蜨"), + (0x2F9BD, "M", "蝫"), + (0x2F9BE, "M", "螆"), + (0x2F9BF, "X"), + (0x2F9C0, "M", "蟡"), + (0x2F9C1, "M", "蠁"), + (0x2F9C2, "M", "䗹"), + (0x2F9C3, "M", "衠"), + (0x2F9C4, "M", "衣"), + (0x2F9C5, "M", "𧙧"), + (0x2F9C6, "M", "裗"), + (0x2F9C7, "M", "裞"), + (0x2F9C8, "M", "䘵"), + (0x2F9C9, "M", "裺"), + (0x2F9CA, "M", "㒻"), + (0x2F9CB, "M", "𧢮"), + (0x2F9CC, "M", "𧥦"), + (0x2F9CD, "M", "䚾"), + (0x2F9CE, "M", "䛇"), + (0x2F9CF, "M", "誠"), + (0x2F9D0, "M", "諭"), + (0x2F9D1, "M", "變"), + (0x2F9D2, "M", "豕"), + (0x2F9D3, "M", "𧲨"), + (0x2F9D4, "M", "貫"), + (0x2F9D5, "M", "賁"), + (0x2F9D6, "M", "贛"), + (0x2F9D7, "M", "起"), + ] + + +def _seg_81() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: + return [ + (0x2F9D8, "M", "𧼯"), + (0x2F9D9, "M", "𠠄"), + (0x2F9DA, "M", "跋"), + (0x2F9DB, "M", "趼"), + (0x2F9DC, "M", "跰"), + (0x2F9DD, "M", "𠣞"), + (0x2F9DE, "M", "軔"), + (0x2F9DF, "M", "輸"), + (0x2F9E0, "M", "𨗒"), + (0x2F9E1, "M", "𨗭"), + (0x2F9E2, "M", "邔"), + (0x2F9E3, "M", "郱"), + (0x2F9E4, "M", "鄑"), + (0x2F9E5, "M", "𨜮"), + (0x2F9E6, "M", "鄛"), + (0x2F9E7, "M", "鈸"), + (0x2F9E8, "M", "鋗"), + (0x2F9E9, "M", "鋘"), + (0x2F9EA, "M", "鉼"), + (0x2F9EB, "M", "鏹"), + (0x2F9EC, "M", "鐕"), + (0x2F9ED, "M", "𨯺"), + (0x2F9EE, "M", "開"), + (0x2F9EF, "M", "䦕"), + (0x2F9F0, "M", "閷"), + (0x2F9F1, "M", "𨵷"), + (0x2F9F2, "M", "䧦"), + (0x2F9F3, "M", "雃"), + (0x2F9F4, "M", "嶲"), + (0x2F9F5, "M", "霣"), + (0x2F9F6, "M", "𩅅"), + (0x2F9F7, "M", "𩈚"), + (0x2F9F8, "M", "䩮"), + (0x2F9F9, "M", "䩶"), + (0x2F9FA, "M", "韠"), + (0x2F9FB, "M", "𩐊"), + (0x2F9FC, "M", "䪲"), + (0x2F9FD, "M", "𩒖"), + (0x2F9FE, "M", "頋"), + (0x2FA00, "M", "頩"), + (0x2FA01, "M", "𩖶"), + (0x2FA02, "M", "飢"), + (0x2FA03, "M", "䬳"), + (0x2FA04, "M", "餩"), + (0x2FA05, "M", "馧"), + (0x2FA06, "M", "駂"), + (0x2FA07, "M", "駾"), + (0x2FA08, "M", "䯎"), + (0x2FA09, "M", "𩬰"), + (0x2FA0A, "M", "鬒"), + (0x2FA0B, "M", "鱀"), + (0x2FA0C, "M", "鳽"), + (0x2FA0D, "M", "䳎"), + (0x2FA0E, "M", "䳭"), + (0x2FA0F, "M", "鵧"), + (0x2FA10, "M", "𪃎"), + (0x2FA11, "M", "䳸"), + (0x2FA12, "M", "𪄅"), + (0x2FA13, "M", "𪈎"), + (0x2FA14, "M", "𪊑"), + (0x2FA15, "M", "麻"), + (0x2FA16, "M", "䵖"), + (0x2FA17, "M", "黹"), + (0x2FA18, "M", "黾"), + (0x2FA19, "M", "鼅"), + (0x2FA1A, "M", "鼏"), + (0x2FA1B, "M", "鼖"), + (0x2FA1C, "M", "鼻"), + (0x2FA1D, "M", "𪘀"), + (0x2FA1E, "X"), + (0x30000, "V"), + (0x3134B, "X"), + (0x31350, "V"), + (0x323B0, "X"), + (0xE0100, "I"), + (0xE01F0, "X"), + ] + + +uts46data = tuple( + _seg_0() + + _seg_1() + + _seg_2() + + _seg_3() + + _seg_4() + + _seg_5() + + _seg_6() + + _seg_7() + + _seg_8() + + _seg_9() + + _seg_10() + + _seg_11() + + _seg_12() + + _seg_13() + + _seg_14() + + _seg_15() + + _seg_16() + + _seg_17() + + _seg_18() + + _seg_19() + + _seg_20() + + _seg_21() + + _seg_22() + + _seg_23() + + _seg_24() + + _seg_25() + + _seg_26() + + _seg_27() + + _seg_28() + + _seg_29() + + _seg_30() + + _seg_31() + + _seg_32() + + _seg_33() + + _seg_34() + + _seg_35() + + _seg_36() + + _seg_37() + + _seg_38() + + _seg_39() + + _seg_40() + + _seg_41() + + _seg_42() + + _seg_43() + + _seg_44() + + _seg_45() + + _seg_46() + + _seg_47() + + _seg_48() + + _seg_49() + + _seg_50() + + _seg_51() + + _seg_52() + + _seg_53() + + _seg_54() + + _seg_55() + + _seg_56() + + _seg_57() + + _seg_58() + + _seg_59() + + _seg_60() + + _seg_61() + + _seg_62() + + _seg_63() + + _seg_64() + + _seg_65() + + _seg_66() + + _seg_67() + + _seg_68() + + _seg_69() + + _seg_70() + + _seg_71() + + _seg_72() + + _seg_73() + + _seg_74() + + _seg_75() + + _seg_76() + + _seg_77() + + _seg_78() + + _seg_79() + + _seg_80() + + _seg_81() +) # type: Tuple[Union[Tuple[int, str], Tuple[int, str, str]], ...] diff --git a/backend/venv/Lib/site-packages/itsdangerous-2.2.0.dist-info/INSTALLER b/backend/venv/Lib/site-packages/itsdangerous-2.2.0.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/backend/venv/Lib/site-packages/itsdangerous-2.2.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/backend/venv/Lib/site-packages/itsdangerous-2.2.0.dist-info/LICENSE.txt b/backend/venv/Lib/site-packages/itsdangerous-2.2.0.dist-info/LICENSE.txt new file mode 100644 index 0000000..7b190ca --- /dev/null +++ b/backend/venv/Lib/site-packages/itsdangerous-2.2.0.dist-info/LICENSE.txt @@ -0,0 +1,28 @@ +Copyright 2011 Pallets + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/backend/venv/Lib/site-packages/itsdangerous-2.2.0.dist-info/METADATA b/backend/venv/Lib/site-packages/itsdangerous-2.2.0.dist-info/METADATA new file mode 100644 index 0000000..ddf5464 --- /dev/null +++ b/backend/venv/Lib/site-packages/itsdangerous-2.2.0.dist-info/METADATA @@ -0,0 +1,60 @@ +Metadata-Version: 2.1 +Name: itsdangerous +Version: 2.2.0 +Summary: Safely pass data to untrusted environments and back. +Maintainer-email: Pallets +Requires-Python: >=3.8 +Description-Content-Type: text/markdown +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Typing :: Typed +Project-URL: Changes, https://itsdangerous.palletsprojects.com/changes/ +Project-URL: Chat, https://discord.gg/pallets +Project-URL: Documentation, https://itsdangerous.palletsprojects.com/ +Project-URL: Donate, https://palletsprojects.com/donate +Project-URL: Source, https://github.com/pallets/itsdangerous/ + +# ItsDangerous + +... so better sign this + +Various helpers to pass data to untrusted environments and to get it +back safe and sound. Data is cryptographically signed to ensure that a +token has not been tampered with. + +It's possible to customize how data is serialized. Data is compressed as +needed. A timestamp can be added and verified automatically while +loading a token. + + +## A Simple Example + +Here's how you could generate a token for transmitting a user's id and +name between web requests. + +```python +from itsdangerous import URLSafeSerializer +auth_s = URLSafeSerializer("secret key", "auth") +token = auth_s.dumps({"id": 5, "name": "itsdangerous"}) + +print(token) +# eyJpZCI6NSwibmFtZSI6Iml0c2Rhbmdlcm91cyJ9.6YP6T0BaO67XP--9UzTrmurXSmg + +data = auth_s.loads(token) +print(data["name"]) +# itsdangerous +``` + + +## Donate + +The Pallets organization develops and supports ItsDangerous and other +popular packages. In order to grow the community of contributors and +users, and allow the maintainers to devote more time to the projects, +[please donate today][]. + +[please donate today]: https://palletsprojects.com/donate + diff --git a/backend/venv/Lib/site-packages/itsdangerous-2.2.0.dist-info/RECORD b/backend/venv/Lib/site-packages/itsdangerous-2.2.0.dist-info/RECORD new file mode 100644 index 0000000..1394876 --- /dev/null +++ b/backend/venv/Lib/site-packages/itsdangerous-2.2.0.dist-info/RECORD @@ -0,0 +1,22 @@ +itsdangerous-2.2.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +itsdangerous-2.2.0.dist-info/LICENSE.txt,sha256=Y68JiRtr6K0aQlLtQ68PTvun_JSOIoNnvtfzxa4LCdc,1475 +itsdangerous-2.2.0.dist-info/METADATA,sha256=0rk0-1ZwihuU5DnwJVwPWoEI4yWOyCexih3JyZHblhE,1924 +itsdangerous-2.2.0.dist-info/RECORD,, +itsdangerous-2.2.0.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81 +itsdangerous/__init__.py,sha256=4SK75sCe29xbRgQE1ZQtMHnKUuZYAf3bSpZOrff1IAY,1427 +itsdangerous/__pycache__/__init__.cpython-312.pyc,, +itsdangerous/__pycache__/_json.cpython-312.pyc,, +itsdangerous/__pycache__/encoding.cpython-312.pyc,, +itsdangerous/__pycache__/exc.cpython-312.pyc,, +itsdangerous/__pycache__/serializer.cpython-312.pyc,, +itsdangerous/__pycache__/signer.cpython-312.pyc,, +itsdangerous/__pycache__/timed.cpython-312.pyc,, +itsdangerous/__pycache__/url_safe.cpython-312.pyc,, +itsdangerous/_json.py,sha256=wPQGmge2yZ9328EHKF6gadGeyGYCJQKxtU-iLKE6UnA,473 +itsdangerous/encoding.py,sha256=wwTz5q_3zLcaAdunk6_vSoStwGqYWe307Zl_U87aRFM,1409 +itsdangerous/exc.py,sha256=Rr3exo0MRFEcPZltwecyK16VV1bE2K9_F1-d-ljcUn4,3201 +itsdangerous/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +itsdangerous/serializer.py,sha256=PmdwADLqkSyQLZ0jOKAgDsAW4k_H0TlA71Ei3z0C5aI,15601 +itsdangerous/signer.py,sha256=YO0CV7NBvHA6j549REHJFUjUojw2pHqwcUpQnU7yNYQ,9647 +itsdangerous/timed.py,sha256=6RvDMqNumGMxf0-HlpaZdN9PUQQmRvrQGplKhxuivUs,8083 +itsdangerous/url_safe.py,sha256=az4e5fXi_vs-YbWj8YZwn4wiVKfeD--GEKRT5Ueu4P4,2505 diff --git a/backend/venv/Lib/site-packages/itsdangerous-2.2.0.dist-info/WHEEL b/backend/venv/Lib/site-packages/itsdangerous-2.2.0.dist-info/WHEEL new file mode 100644 index 0000000..3b5e64b --- /dev/null +++ b/backend/venv/Lib/site-packages/itsdangerous-2.2.0.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: flit 3.9.0 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/backend/venv/Lib/site-packages/itsdangerous/__init__.py b/backend/venv/Lib/site-packages/itsdangerous/__init__.py new file mode 100644 index 0000000..ea55256 --- /dev/null +++ b/backend/venv/Lib/site-packages/itsdangerous/__init__.py @@ -0,0 +1,38 @@ +from __future__ import annotations + +import typing as t + +from .encoding import base64_decode as base64_decode +from .encoding import base64_encode as base64_encode +from .encoding import want_bytes as want_bytes +from .exc import BadData as BadData +from .exc import BadHeader as BadHeader +from .exc import BadPayload as BadPayload +from .exc import BadSignature as BadSignature +from .exc import BadTimeSignature as BadTimeSignature +from .exc import SignatureExpired as SignatureExpired +from .serializer import Serializer as Serializer +from .signer import HMACAlgorithm as HMACAlgorithm +from .signer import NoneAlgorithm as NoneAlgorithm +from .signer import Signer as Signer +from .timed import TimedSerializer as TimedSerializer +from .timed import TimestampSigner as TimestampSigner +from .url_safe import URLSafeSerializer as URLSafeSerializer +from .url_safe import URLSafeTimedSerializer as URLSafeTimedSerializer + + +def __getattr__(name: str) -> t.Any: + if name == "__version__": + import importlib.metadata + import warnings + + warnings.warn( + "The '__version__' attribute is deprecated and will be removed in" + " ItsDangerous 2.3. Use feature detection or" + " 'importlib.metadata.version(\"itsdangerous\")' instead.", + DeprecationWarning, + stacklevel=2, + ) + return importlib.metadata.version("itsdangerous") + + raise AttributeError(name) diff --git a/backend/venv/Lib/site-packages/itsdangerous/__pycache__/__init__.cpython-312.pyc b/backend/venv/Lib/site-packages/itsdangerous/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7e1d3906acc208e05e1f5be6aaa82bbbf756991c GIT binary patch literal 1641 zcmZXU&ube;6vt=vW3^goC0YKRnq=*!b@mW7IB_9uD7bdo6kI1n358{08EMAy+WSMy zj^xPLP)ZN&sfQktYi}*-f6`0R91=DN3TY^T9t`%O^wc+F$;j!jy#2iI&c1y!@6G;Z z7&?OS`k%kHe#|2DN;t!jIsxVAZ-9r0AfosvP;5mJobpq4nxsj_&jeXJ3tF0FfmK_T ztODokoaCIZ1$jF!Sp(K>U2-0{U>79oz(u<#xd3d~hU6k}$u3DY{BlsSE0Rn8SWvaA zlFPv3_PFE<@Ps`fdCZ>-rtB%nRp4oRTJpF*6U^GPk|%)A+2??#$mF*f`<-6Ontmge zZYfCthhfAq_o6V~c%z(%Mgzz6!)q>~&4^H#H56z#5cFLfa<|drG=|5yPcd1;90TS7 zZ&6Gr14jqv4(|C8Cg2spt9z{w^9~b1E8ySr0(wR}b#6XrdyIWikQc@0(fj}L?Im&R1rhYEsOBv%3#Kzu7gQ|!=i zKs%u{Ldwx2fQM)w+GpnyLhNIbBFIMvio7casr}TpnETcsX|4_>lKD0J7-ET`pnYXq zJK<5gT^RLFn5d5j8PyRthR^rWQ2j=+avMp(b-R?sP-E9+qUra3y0=Bm#SwYY#GEs) z(c#qeVw2D|qfN{yF>y%DUC;N;1~nNCqAqA&Xnw)tH5|4mi#oBnRJ&R;@5j{Kq_Vp3 zKBrC5RA$7?MK5SajQd`r7Eq1}bV_ZI&!q*A$7C31!CHjSF^B%Cy%Bke>O--bJ3j4F zKPiq*wsJ}J|A7;27qid{TXB*RlvLLSOMzs*I(d|6!!(lIAdjT9GF<*m#v*2=lT3&M zn&eME!R8>LSk%Zg&40I7KXPEfEOwTzEG_Lgw?n$dye@UtXuQLtwsZG({m#0xOX<$C z!=kwDFFOrb2n~tTrD4}u_Zm*@aeBE8DsIu(8C~25uIq&!cimdMC(74?eS-v{eD6U5 zGa{2Zn6J@`T;aQe-*a;>wfUFY^dDN~2jhF=FqJYsSB_O=TzD}(b67z6sbi$(^}`aX z%swyAKP}HcFI!K`*3Y$PwoGqk0ze!=bvQGA3<1TW!M7Tl61^jqB066Hr&hd z+Dh27<`Ug?H#_1GLpowV5|#Jbu;q!u6HWdiz+s}}nP_m9lcDH?CKFxF^1_IpG7}BW zio%H2g;Jj$bXF3A8q1T+%3?}Im@y$|xj5FWDui(%XdULeF&tqwA+$+h#6JCk*!zMn zf=RR+K}0$}{e)cwSDc!770h8;QItMfc!jF3(Y3y~YJK!>A1(Hg)kl~6XjxuY`e;dB S7l+D?KKkrfEh!h|NB#r0+sZNk literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/itsdangerous/__pycache__/_json.cpython-312.pyc b/backend/venv/Lib/site-packages/itsdangerous/__pycache__/_json.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5c35583ab169a1173f5a76d62f4f742ef276ea79 GIT binary patch literal 1195 zcmZ`&OKTKC5bmB=#!WOBqnLv*_=3^6hQug{2%;#6Y{VeKGBEURcXnqVGh=se!X|sj zAr~)tOpYErDETQ~6a{ru2t*NYF*ztXSv|A6QNf0({<^xVtLm$om;3kU5Uj7izEwY9 zgf`Wow~P$noeKa~5k(X?P!kt1R#stcop!M$kEYw+WwZ!yQz{G4sgbFBqASUe;D?4Yma{aP*UobAb$%)Cy zx;GQD8$6h2-VG+|GK#%>GqZQ^cngfxr#&8txH0XONV(2J>dmuo-n$c&JOP=XgUsus z!h{z{K}lF)P_8(iM$gA>ZbP`mkw2Nqr)j8ui-RDR(U;-TCrgi()-JsnKJm&vu>(r< z7ZoNb1{D?a09H{4*ZO2A+iX!xwO-fp|7`TV$-qc3^@&R}zF=?wAD+@g;)e@_| zKzKz6)kDYOiUmFb;vb4qp97#57eOqe4g0`5d+fD6ww8Z>>a9KTzJDHno_lLgedqy`DiwV)bEj;n?y zh8p~gdrP+CAgm- literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/itsdangerous/__pycache__/encoding.cpython-312.pyc b/backend/venv/Lib/site-packages/itsdangerous/__pycache__/encoding.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..95850187a6fca567b64c0a89746bac202f549518 GIT binary patch literal 2695 zcma(SOKclObjG{hINmsMlIBw&uuV#XTauPE4WX1mOB)qbQfOK}#>H$rlhp2ZZDz(v zV-ge)2RIQ#r3N8HFGxW}0*On-3C>(>87b9Lq)JtVdW#4LR4%-k^(J-8fw6by&3kX= z{oni&i$xKPTYvv?_WdwIH{~W6x)0#>=P*K-5J3bx=sZqhEa8w7N`};`B{j9`NnNes zq(L;II}PU}$p}V`h%`6Cy!j(7B>Z7G*+}BV_)t$qVQqlbq*|^!5Wcy7fdK!&=01SF zKqT^|mg@=jn=5I&0vgMaYzZN%=Pb3Un@DtnrWjof4RQ-}#CcHWP_ z67q4$PSQ%6z@jeFMq;pb&xI20wGt|?# zV4gwUOrB66VeUoLChJZEnz20NTqV!*=uV%b5!R(`&m?r^8PAwh!o1cZbL5fqIMY7SM*q3?&Q=4e?T zWi7y7=WLmY%Go~xQ15JlN$6YcO3l$SCyBo4_DvU?h=fZ9LM6DX1j;Tz3lSR`o&(Cg zWAp3;>O&$D(1mJpayJ#)j#%pg7Seb%h!F&B9)A!b4GZ`^Jd0=11?>$qixZL3iCP#5 zmE{3pgb)m-qwE=rw*nLI4##3_zdQ=v#7k$-siayMw13_koJcTKj zeZ;ya7yJvD1*C`I;}oWiTv+M4+Wl+n@Z#7tJ^B&3$d^Yxdw0pX{7R*BN2R&HqW3S3 zt?63$!1b1n)t3HBOaF>dZP{Ip?Ed?DQ^&;O^}A3;BqB_f@>V( ztWjzbPuDuD?G(=1lN4^8@NZTLG%}p73DV^|$ok|NJ!5m=E4m7mkc!E)QLg?5DL49E zJ96NBo)jH=kUa-<+0OY7FhLbz{5$HsiDJLi{%yBV_gVxUID*$S1IMm4wE649+x&Ik zs9JA?qw8UyueXKqQ|s|4KCt!>>grkT+*#?|S?<`iGWOj|-@LT)?A5+<`@z-rqm}lf zKTTKL$IB>wBi^%QT#9`fTPD?b-(u`qyk|AuTZ#8duyYAtGCnoRU87eAR`-ur_K#QN SCl+Jt2F8PbMKFF+8TBvqa%0*6 literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/itsdangerous/__pycache__/exc.cpython-312.pyc b/backend/venv/Lib/site-packages/itsdangerous/__pycache__/exc.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3ec8dc8aadecbecf0ed7aeaff812dc340c884899 GIT binary patch literal 3955 zcmbVP-HRL76~80RNTXfthaEd>H~ttm-E0+SWoNNl5TR}phkg(?Ax!R)N&?(Wp1 z8TH=L+Pmn%g@vx6p@vf2$3E5=`j7M_g%sSOfkG&yZ?acmji35EcSfU+2$y!&I`_`G zckahIzu!5>f1aD0VR-)e{9il2EHm~cy$l{B>1aoPMCT!MnXCD%rPVc!`Z+&W&!f%z zdP}eC8q2XCGFLxfuECAR`Q+PrL1_!n7I`7l7M0e7w#18>)>PUVXlJ>ZX-i65hIVdb z?u^pTL%T4t?(AN!viNV>x}wFiP7s8V6M11E*YR$;PQ)Xx#hc055}6)UJ9-Q6zrr;+ zt7|T+=Ufff(+}B}=H?E{b=@`G{DEFK4%uC;Ubw|7g}C^x4XaBb!JD%jO}lMYbImTU<(K zn`2Cu+}{$jSRgLhcGGvHv~5Y-TGqW6{JmP^rxFKktX*AOyWRLO;5UW0%NsYjyd8z@ z#>XGt`sjnk9nNoGZ-`K~{p*cQr+J$PZey1RyNwUL&4%=r6)@l4)ssVM;Kzw^zPJW)K}K} z209N}m;Icy6VELsOsFcFx-}Zmhe`U>60~JpgaIO9+xrW{6Dh?>nn<(nu_p_!{HA-q z`^+%KYzHL9!#2mEhpx;*q6$QL2QKSLd?D+wEn$r#Qt8&h`cx-CMIdwcW zsfqFI(UYEb^aeU#W6zL3b9FEYyfMHVBQC=rx4iAZ!R`3|@{l}^B?oHD4Y{;HV5{Xs z&7EqKurzq6uN*W5&iN^D2E<3^itr3bC1)oh9C!|yc`v?lre0ABzG&uBr;ydJ_$T1Q34)g z_&7UhkPIUg%$64*fRTQgmFClk^oNzt%{P0e*twNM{jcVkG$5?6R|*q25%jU3?e`Z3 zIV}Z^xJW~j$hbsG65qm4eg{GkJZG4I<)!5(E0=qvMPub3Cr=q3?1* z2{5oWHd@YI8)1KABT1dg`#N8G`U_y06$8*pYv4Utt+!k|TE z(c)Ayw9;}S4E#N1m>s9x=7Ci81d^@?hV3KwCdI^#v&&((bVXHPY*VDY<3&4Ej;Iwf zm%OCRSi6>Rkib89G7i2A%>)OH|IWcKcxvYdi|wTeRv(Geh2-4vd?>taFK~RD3lR!X zg!1V~*nX2tLxlm8I$&im!B-7mM!?YP**b_S={%NRS=ndk~7S1_*nK2z&AMCzr4EW*3YbinC}_ z&Qi~0C(idu)SF>vE5|hJDT7ErOsh@@@&A;WgF!lD(DRH87AMdP$wr}3r?FjR?CyBN>Hn8@(6`wpjIEk zA4{oaGd|FnIF?FqG%UK+8j2TTv)K^{SC-omUa)P^*{H>qG74!R3@lXkH7ANhZDX)h z0!f4&wbIKf^bG3o3H9-tTA}|xC5;0ASUEFf1JQJX3$G0QnUR5Gnxqo=YsJhs{*!WQ zw3<;{(SN9>=c6i(kZ9mHEI12>dAw*CH=Z$w1g$iwQl@%$t3$;i3R^N%T!{ACa7C;| zf-V!6GF~Ostg3}5Q6({5@k#AUARk8j*nB6cqrWGpYM?|We+JRZYnt{2`{tMIkt<$T4%{n4;WAn7|>+EfCBqRjM7PE9YDZPZ2f0oB6r9< zVB6>W-reyi$*$YAC;RT*yZ65D`@Zk{`#t`1RaJ$6>t|p5+r(#22*SV8i+z>xg1GTr zQ4p>Ps-TK#VM-hpMJjvJo+F3-X~Q^Wzuq_>1mE}Aa6H0EL9KjUP^$o~r-+qZ(i#afXWXW8 zf&ZyBYUp*}a5L*4M*nK`f7I?(d~WK$Yt9p`{W*P(ius_D$z)B%Ol331;LovuR9P{r zWX#0aoT(Y~_Kc#QRp!!JMa5es-iA^aGm1H*Yj_VQrj$!s;*vIJB+@CvM3tYuYkIyi zac)S{Q%X8Duc=W_UK-2JWYm0_s*Ni%X|&XX7%xef*q22Uabp*1t_hkjEULn=NA;;9 zW(qD*J$U-&yitF?I&pSDF%@SBJxRSS2n--rO5E@asR6pc$9U?DWWsFASYMGcv1bmyV3+Sz|hV zWMoW9UeYq^$Ym{adE`uLY{W>J+QDhmDi<|lBxM?^lDVkq*%_l7pgAG**z{apB4Qfz zk1DW@>u70a^WS zG_eM}bzG0&Z7}N7>+sY`?DKwI!)j;lNoK4+Glx&ak2)=pPPnp0Q7IotBr?jBmPq6) z5{ap-I+LbyWg_v)jFRSG^ag6*OgF-pjm0q3L-a~F`e@LwuM0o*J$^SJNXK|H`j{jR zwJ!+;w!}}Pa7{3sZwtbtC8Ty!dZvW;trjK`mtD3H4uS3Gj~t)Sl9vp5c0w~JG+kEY z;;P9PHL$b-iI7e0Ra4ID@>nXP=yS2CH(!x5QW?WkGD(fiE$=lKDXh&K~%jWVA_?DtCOpdj$EYUhQ1Ox@WJtwV9&CzhtVR5M$YBv-+u%z z7iH!p=;2|n=7YxdXnxfTwGC}G98i6Dlj!ZDFkG(s@m9vZRZP;#Z@O$9(OuoEhF_OJ>ngQPt$y9-%q@iVYA-@j_o+2#7gjseT4>N}wO!q>)}f{b zrB1aTrCOAtY6D7jC>>BEDAkujA$aN|Y9qchpiP&$1Eol58}*>tgxW^dHde&IE~(vW zGrsTG)T>9`iQ1;QK(sesG301VC0;HF{cb^=)s<-jvKddN6~l;+e$}mKV+J!lF>ZlI zWiwkLz z0av~Z9LMKmv@>zjc;5-d$m}=eF-^}}!c-bi#%8iJX9hXN(S($LAQs*%nF(G0j6c+Z%6HXV}(Qsd*Au4PQLO`C>mI7~+6h-PIKjs=FCNf{H) zTBS0mwmTC%XjCI64{4elSF_3ZXg4a8+O%nmGBD#9K9#|Jig`P-0&j$`9Akr&IY%=h zs^Hz8J>wD}W-VfTTG15{fHfeWCoc1Kbvh84i9x8N#UZmPb0Q`mCw2l687{<=8#GzLASiL7z1D<0@UL2v#*-E!WN5BdJ2X~lWA0} zPZ3ot50m+#Gk4Aafwm)R$&ij{#^wHu3`avt5*Z-{4o{C-?9AC>bd<9)Uj~{w zv3yoFWLgrNDIM_xk}$lC#lRliRfN&yf=s>RifQVQ82-s+L?IBf6RG5cEf3TS^5uv_ zDe0VfBreS=`b8rypVsDPv$`tdZDtBA$@))2$&g0?o`oC%ONVSkT*s;7@;h2O1n8>i zAQRSMh?TJhOluKh++#3P@F_TaS_Yd691hLaMS(3d=PWPTUR2U!An(`=V)h*aVKFJ+4XQp9Avf~aSqobX? zH>qiwiUlP)I{Hw&yO|K+9|k)Xvo)ne9x)+57l&=iAY*QIi}wX;Tg!2Eh*y@wsd$b?{3xHQ{3vxJ|ZH(Vky z3xg>uj0IflN{C|q(3~?#GplofyVtlm#5~VpxC{AOdtHi3Y`)T*o7T<`F+?upLrx1; zG5fnipm zl3fd48ydd*omz=OqV&k7Yf)N|(9#)W!T+jgctm7EP>Z;VUkhbd8cfQ|unRbClLoNI zT`XHDL*GiLwa*37!E;VvLK+R}G;}^#lutvaY3VV#b<(YkZj}7cqjYn4IPW8EqaUD3 zVrS0czp9{oh@Qsxa6?9=U5FmLU9r-6e98AoV8?neyd2zlr>^C?x>DD+G*Ivh4NXhF zH_O+94a>onwWgNUrk-3=&(fFH;{&J<-|39sj<0l{px(RJgEdP}t~E5RHgx71I+sqY zw;w>8;9B<+A9p|Vp@-TuuLpN72ixxKZo4tC+TNdQ?_b&d%yQ+fLO`f$DM&(j)hB@# zjC%N4@#DTP{Rn-29BAd-=kO8`r}QM_J{g5;Shq<$H(#nq2|47jJo9gnG2tPE+=&3$ zj3W3Y2MV4&SqRH{cCE-L^ANZ(tl%0?mMvSD%uY=sS{h5GDLfj7VMh!DBdL}88@3}d zs~|8ZyHs>vfBwI?km-FK2;xE6NmnXNKZy7F2A4uDBK9BDl-Lp~wL++_Uk&fhg?HcZ ziNr3lu;p&y}X_sRj8GCW)?_u0>y_YQeMUH65rf=|y5`!Kcd$ z-bqI;i`^H*Nh=9gtP`;HVM~qu9D>wu-@n+RO)wpKZ5Q;qMaiTrIlENvg7ksU&RH%< zuX$8)QTnPhE6xh9dS4c1#i*pzf_=_VdYP@amZ8vFwc<3}<(bJODdUfTK82Klv+8!V z5G!W`7*NlDuL6S-tKtF?XcLsH+QG9G8{==NA82+SG3U%90T49 zVayqp#Y=1;FfyOZ=%|GZMzL}ZN_tkAGr*h<6f31+GxXp+X~rBscx-;?ILl|y94IVh zNZ4~5(~=6Xgexg)uTtuOXp~JNNn{~}z{9fr< zmmIl2`~tmAcyz5;?qd zvf!&IZ}>?#vevk7wegW$<0Cguet+=2!P`eyx{j|j4lGv>tk>;Xt=pfg+kdlcrLJeW zvgeCC;T@j~QhCFj+Fb>YSaWoJw|uwER~LfPt8XZj`>GoLyWqw5dqxY;`RhIXEy72Y z)pTzu?|;nuQAeo%u=k_G63T4L1C7{4(#2$Z30694~+v#%qtg{n*mLdboMXeCzk$ z`2FjLS9d;=!@uzJx7wG(&);reji1TkU-pq*LabTs&R+X%DgWpQ87_3tuo# zuavVxwX31lT&VTBxe{vsIMBYnW7q1AgP-g;xb)neaMSh9?+knrj;=NBx$0lrx%=J6 z-+BD)z@3_%*Pr{2_DN0GTH7PJYWZs5osM<#=O4*6J#y8*-nw_SHTFqs>}thNBCXfw zbCIWR`IaM3-S(rjQvK9tUSW6lXLUkT?7x`3eeIdLXBtE&@&u+uSM%@i;xSLPnpI&4pjCRr( zMg}2OQ<_rftEBTvtqiupN*RduZiaHS9o;Sg_qCN}$eUQse>^f$#xUZ5pR2 z$f2@aJ_rocxRZ%!u z)wWvInXBr&*|<{GyW~Nnxf>t9)^+qYb~Z#`VIRL)hhTV0ZK0v-}K zPM|=$zJ0aw!hf)pgEwg6nQ+A*0@2W zl8o(3l|72eimNp{D#S;|A+z=t=r&6QM;ZzW8*|R857J4XS)H^19rb{vWDYQ`Ojd5{bMJ z5OJe`LW$@)BC-fqg9#XxVe?gt2w^YUA;=QqLSfsOPTE$4ol)!sN+KUKB>044lsD52|L^Qjj#+Jj{tQ3*T5l>i+$m7Aa|4ao{Q6FFj~gNk_1OTiCf;!4T4TCKwdQS zz9c0m$`}LWMT6U=v-B}Usf&aYgmJs%MQCMEUt$ehj62wgq7sp%(8u@^amO^;LS!q2 zs>Z9Y{L%AEBGNibp>+y*qPa-)X8XTHx|dEAJl?8(YmGZs8#{B2oi`)jZ+Wlf)+;N~ z$5tBSA6Lhbt7+^3jBxc^<8O@r*~pD2S3-xD1Bbr2TPD=Yp9>;7?`i+@5F#5C?-`94 z^xM1pWzR=)dH)gVqo}99NBXEoLb=3<_|T3CI%z1D+1XCe#qA8r`{+RzxX}`K7PCa% zLe8i#DwB}2BG2AfLJmii1*JZC%j$bxE`eVGL@s{B_%?l!hyy)Kq>n1j6Mac$uL$em zy0_-vn7_W~-HvxU{<8DNz)Co}9Efg}J!i%p=y(4am(EIg3{$+%#7O(lCO+S2w?lG= zIZ2nLipmRN+H}^0SC4~uI1qtOI5}Y-&?AqHLjMwDG?AT^=dv@p!_$s!)Me}xU&0O} z5+GZGL2Fl#2}pt^O1c~fR;(UH>Vh^;L4LAxlQXpU4^Y-;TMO%`hN7H;o@HU7>-fM} zHjDiy%8|fSreHsl%oDY;H4Y6ZICXM0D34pI9|xff=>u!Ol<&upXuSkdq)g_zs@mAh zMWi;!JcDd>umOXBEb^rc=)=Y*BDw6d1DqcMv~xx<1?g zAR$8wfKi!IDIS!VP9-nF)D&qSwKmoW(c(@iOFUwq6kBUY90ZV=sZB8cCudX{*Af)l zMJ@`>57-DFV?nq(_cC~n>9VNj#NY|| zf28i1-Qk%wGDju(H-{DSK^oECFsx%QmQ-4mI(cTBQ*pY6%J~+TkFu5RULlV8Cfb2x z>V?Y2E+6&kz3pO zxlo0MFhp~2%q@rIJB@qS!+V#*2i7_|m#fFVz+n&*$ zOLXIzRK}9AQRgg1`)w*qpbX zlCXNPlqy4;rlyla$@3!4RP0MO8Y6*y)@?=zHwY0;$rFOod z$f(%pu}_;IhA+Y_t`37kxxi?^^_@J`dqFdH>ILgGi)%fpN8U#WqYG*EdqEecyBeOw zH`i|%Xfi;8Il%^f+JuDlo!N<*t>5p}vZUF0a?9+aF;NdhxPl>}Z|X8Z5Eu`ooD!Ss zWxPHJ4fefRZ=qhTbfe#HQeu-{1bfZHAJV5K9 z65VK6qu>>UKM+3i^h$w3S`_+@F8dmI}TtlT=nsFUU){LpH{XsL{p1RGy<(Y0j!{%RqhG3$${hOJnOFAvGk*Hu1lNG@~ zdkW>O$Qg(gIR~*KXCYQ39@?m3#Su~Phd%fCq;{fis6ZvG!Wr?bSnxJW4Qq|N`18PX z?73bZ+K^DcaZHlVig!b0(x7;^wqAN#yxSF&YVS7tr2Xh0f3n~WOMPoK=uOY|NBQ&A zAbT<>sK2|{BOL%EQ1fc3hc%}sHOF(keCLLQXQ4~zIlOlC@j`Hy)V3as6eK*Y$x|sH zL=G0psZ=4f9$~G(Qx&^5s;KTs2EI&sl!2!wfyWcz?@D-bWk4zb=74OCzMpQS@aEf0 zEp`qE15eHzoY1R>7@)R^}W=eSyQrC`M_Bm$ISvs{>!#@sw+E5KO##d znKs;{Ci8(Oc(nYa{tdK+|0ozg#0|c=D1IvJ{h84EQz7_Mq4sBj{Hd_>Q=#Qkq3u(l zdEM*#`ctnx^;6$otWtgJ)kD|fZ^zdHk?YF47vH&fBYE@4jmcbV@9o|n9{u~HANKu7 z`Y@h*eDJQR7O;TbMYTYIwUGdE|Frp;{kK5>kfC>_Fv>#3Iw_|GMog;!-c8$1LoqNR1o^>N0*(nRj`f2Zo7k!+v3uWJkkCojh`$zn& zT!(VQNCPW-l7Z>qNRa0o+!;=;f1i`RA2|#vMnbI4hdRF!`p9Y4Zj+njX1U>g*GMC4 z51>6*(cV6arVVE!Zq*N-cOL`)m(uTg_jml7L zT+)=|M`KcQW=a}YbaZSmt7IjfmX(SMC1qB4XQh-L8=un^4bA>nC3!e8nUeI3s>BWQ zjoe%zzairHT~6Ufc$ph<$ovSnCObg2AiHHJo~}6|TvrOwG>Oz?e{wRdCiJQ4?BsA} zJf4&^P0_^ZjHZi;>6xT5t)z4@I<4qa(XmNIk7?H1$3#6X&Zz0@30d)qNOp@jsiYK@ ztzMkSq~gQ|DVfmcBCKEBWILmq$i{DeV>=^TCtk7ik@Zz))CN)z=drQ$sk zX_eJXCax*M|$R*Iqs@?HmmCS zoWqi7>p2XO&c1#{Q4}~CMUoyU2Os}VL=Vzp@t~ihOFeon>1Q0ja3_|Ds-LbnJdd&B!RZ*a>9R zsO|KAx5`A4{Rn#uTB)JjMWxrVcC~{>2;=E=GVCsSVzHDot;Av_Z!9*QmNQ8z`(v@6 zWTd3oQWuNK>3A&0_@TC8_C{AG5=KeX(qt@X>y@OY7@He*lZ>Gr9GQ;Y7RZ%!`K~1o1KW$Nc_gj$jg#_8Hi)V>EIMWaar62zHlgY zvhx&r%5}0wcER?0hv*h;jx>}obxJKvn|Pj1UMTGti9x% z)+S5!#@eArVKxXvl$IgP3g~eYBjOI8m1a4W@lhyw6F6sJQ!1_i6X>d8T|J-? z;^5VkIIK*JfE}+@Nq#UkEnQQnMT;d982Ac?4B$^A4FK)p<~)rb_We@(hu0R959^*^ z4eeZv7DIdU!F_qpzJKjLQ1nH99bJ?@IRD{Ke*XGWwBU>6g~)$=?u#%f`c300A&!ac z1lCdFH|`<-U#KDhO2`GptlmUbOk) zviP9X8u0Yv8IZTb(Gf<1a;qG`GbHbjgLrP6s|&Z4+ytQj-T#37?`I|)>K$x_UQZep zTN4=&+E0cf1q(#lkU_#}at92+#ZUpW5d;+(#1^6b$&`&N7!{u)L@Y)#Tkbk5>=R_^t5Og3Nbwa6Ug2U+egOA>x>^OeiY(G@6vuHERxxh3PYp3Wm#&5h(ObLYuOI4D65R_oEn_I$AzBe}sABbOSs={hO%%{r0t0Np zj*45@1!8Fn7(Yzz&%&FFhyyUn#6(65!Dfudv};@R{pBZ;aEHW%c9lI5s0W0DtC0$peV-{SfCL41yxMojdc4H%-cw5zORiOebAL!Bc$LYNU_GalATR;Y! zAO?^Tv|nd$)-!3Ydet*Yj#5M*S`B3*B0P245jYd(4rCCMunve#3qeRYA8<^V&%vLKV`gZ%~u5^#*EW}rP;G!=a|E5Vm63`p$#JuOJ|u{G8z>RM_#bU^~*9= zX&qG3F(jYXVTE!QXAr?LXksT`PupXwPv)Pyu>Joy@Qh z5#))sj*15@(^lD@ZWkuh|nloepZY6icUZIEbfg@z!g?p(f=f2gVw_2UB67rU}B%3OC&W*8tt9gzKJBPA=eF;)yhLdb9 z508@K38q!XGcJ*`O6bh7MKuIWmtc12z#A&Vwgrf|A-)$8`-cb4ofDIa4ut@NhvSBp z{Y;hbI}m$mpAqA%cui!3Fm+|XE<##CQNs-kFP3~|W=4@dA2*yDeUjYQJi$ z-ExoGytcT^a~SmuPLq#bD>5V3F{&Lo_~berIhJIPH7~Ac>ZSjLc+*)DjrfI#Qd~+V z4R?&8a07DV1ks@bf-@tGsPNK}p;Siea1zrAggses5eh#I=SEEcc%;NB0Dy>i0kEf{ zJ6>n`fiw}pz!V`RpaIK@u(&1;n*l9NGSN<<0a0RyKB?RwJY~~E9vg6;L~bG?qy(*I z)2bX1&zT@_E}gMlNHS1Kz#+wSTkT1V^G)+=CKw_LZTH5CSr8i4aC3r7mUyL02ntR1 zk%v-NF*M0wg%?3;jx-;vq%uurv4+m8c>nhSO`6^Sn>2AXbOa;dmMSo;WpdOZNJYtQ zxIO9serSX|G-g3rU=Dil81)fS0Pxvems8hL=~?62u3{sNeSyg()yb?ZGlC^vFA0cP z>qf|jnM7tLU!-mn_fwD4$|o@p;1$bL?uU9t zS}zq_uWUFS&9K@ISZy~KXf)?J{dq&*YUB31y?1&Sqjs3Gad3WM#UH$Ve&PIw`rWxZ za}WKUD^1()M(;%b_Eg@#r%VTpUuoKv_wRbt*q-k=S!_i6sV9w)02YCx{Kj9QP#X<1 z14CTjk}MSubyidH)CvLv)AF_&bn5lilx1wqu1@;?CpX6CO|i=mvn!ZNC75NzR>`

A9xH}A=UpoZ9;X-5#lRi}j8RT4q?QAH zg+SlEBM)4~!0~zKYOrH*xESordpe)N?h(xURCbdEsYD9sONm*tr`-Em+MN0@7Piuo zSZvS2=j_5Jf&)b`zyPRZ$gB$o;!;)ERiM+K^_i@pAAh7S&m*hiNU#~Qc;n6u0y{m+ zT}KODM;}}+cAYE)Pv$)*4IWgA4=ENVa*t5Bi$H1lt{b=4CXT%6sBn!cuud5#fJZg( zj5U6cdk5$mcM;rGA6~O1mBkItQ%!4ql|bK?1UHNB*UhzP{0E15Zq6a#g0s6KuHM6` zPM&)kwX@s}=iA&YA9iM+zfyVsPP{ZiUxZglLmMuXA6Ae(2 zL1_xk`nJ`^Jxk7FW6%5mZr!)Fo9E!s&aS1S%iTu`-ADeg^XUBf73ivicMdM~6&nxC z53B{7Zoj+m?s70v2uAK{4_^E9$nS$c{Gzpey`F172Ja-)^4(@D7i#-6$Je)g(X?aT ziRWXDXn)Vw-_8BDyT1RR^S2QmdDWGheO>kM==#(HRP*@c`0KpdRu(JyDaY&=@VpE` z>auN@%OU&fW1V#lrNwLz4p0WMb>IgkOR9kPWxaHS4S7Qk`@Wxj^?|G0x*2IMnU-V- zP+2n&&GDDN>o zL8uZY;ttb9r%@nH1YKb2A5_>0Cd;hFd9Que9TjIi^+pP@OYkQ_Sf)w^GuD}(IEj{x z8ymZ%W)wu{5))o_NRg3FC~FDj2BQBIu*1%3#>{2tcIh-UxCCNV+A~X=kD*+p%{>-D zcEG`^z&#zO^`buxyho^STk(f(Us$-X=zr*cZl$U9yVYR(mSalZ&3oILxxcFyoqx}Z z_~1k(4sH;aB11z%VL#J7k6#4f6LZF$6P|HtJRUg*+$kXh|6{bh^F$@PAbN*|P#!l{ zkEYKtvj2fc>%tP%n#-zTe4`Z-7$MUP4z ze8Y#YIP^J#W@ZxDz(s@ zfa^Y-7j`ZV6oo?wZ}dc0+V`wH7hc)hw{qandT_t%*jn?2br+t1vBA#uIx2a%K-+pf zmAqVA_qvZter`w4dIOaLT=VlAG;)2E=iGrmI|NtHh7+ZADsB4rxL(?Lm3O(iHUdu9 zsSR(?)w0p$cfG-Hc6eNE#zKgExF)nHa5aoa`I{{kEk-S~g9&{qV34KItcE zab~>LIx3MuEjg7NadtS3FTZ-Ip^vitl)XY3+lnqK+1pd{oH9Nyds&@91D!1`jSQxe z=fC2*zUFp+$pyaTd|z^nUvqoE;=0*?@hfiEU)&A+S^is&@=ejrH|3jqHaR>u8(qA( n84B?otOn2Zy>9;CO6bhG6VEkQXv2l)UmD+a@UYF4GlKpb#MrG| literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/itsdangerous/__pycache__/timed.cpython-312.pyc b/backend/venv/Lib/site-packages/itsdangerous/__pycache__/timed.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c245e18ff1fd02d6c05ad9665426189dfd967d79 GIT binary patch literal 8744 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 NcaOaI3FC1;{1cn~qL%;w literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/itsdangerous/_json.py b/backend/venv/Lib/site-packages/itsdangerous/_json.py new file mode 100644 index 0000000..fc23fea --- /dev/null +++ b/backend/venv/Lib/site-packages/itsdangerous/_json.py @@ -0,0 +1,18 @@ +from __future__ import annotations + +import json as _json +import typing as t + + +class _CompactJSON: + """Wrapper around json module that strips whitespace.""" + + @staticmethod + def loads(payload: str | bytes) -> t.Any: + return _json.loads(payload) + + @staticmethod + def dumps(obj: t.Any, **kwargs: t.Any) -> str: + kwargs.setdefault("ensure_ascii", False) + kwargs.setdefault("separators", (",", ":")) + return _json.dumps(obj, **kwargs) diff --git a/backend/venv/Lib/site-packages/itsdangerous/encoding.py b/backend/venv/Lib/site-packages/itsdangerous/encoding.py new file mode 100644 index 0000000..f5ca80f --- /dev/null +++ b/backend/venv/Lib/site-packages/itsdangerous/encoding.py @@ -0,0 +1,54 @@ +from __future__ import annotations + +import base64 +import string +import struct +import typing as t + +from .exc import BadData + + +def want_bytes( + s: str | bytes, encoding: str = "utf-8", errors: str = "strict" +) -> bytes: + if isinstance(s, str): + s = s.encode(encoding, errors) + + return s + + +def base64_encode(string: str | bytes) -> bytes: + """Base64 encode a string of bytes or text. The resulting bytes are + safe to use in URLs. + """ + string = want_bytes(string) + return base64.urlsafe_b64encode(string).rstrip(b"=") + + +def base64_decode(string: str | bytes) -> bytes: + """Base64 decode a URL-safe string of bytes or text. The result is + bytes. + """ + string = want_bytes(string, encoding="ascii", errors="ignore") + string += b"=" * (-len(string) % 4) + + try: + return base64.urlsafe_b64decode(string) + except (TypeError, ValueError) as e: + raise BadData("Invalid base64-encoded data") from e + + +# The alphabet used by base64.urlsafe_* +_base64_alphabet = f"{string.ascii_letters}{string.digits}-_=".encode("ascii") + +_int64_struct = struct.Struct(">Q") +_int_to_bytes = _int64_struct.pack +_bytes_to_int = t.cast("t.Callable[[bytes], tuple[int]]", _int64_struct.unpack) + + +def int_to_bytes(num: int) -> bytes: + return _int_to_bytes(num).lstrip(b"\x00") + + +def bytes_to_int(bytestr: bytes) -> int: + return _bytes_to_int(bytestr.rjust(8, b"\x00"))[0] diff --git a/backend/venv/Lib/site-packages/itsdangerous/exc.py b/backend/venv/Lib/site-packages/itsdangerous/exc.py new file mode 100644 index 0000000..a75adcd --- /dev/null +++ b/backend/venv/Lib/site-packages/itsdangerous/exc.py @@ -0,0 +1,106 @@ +from __future__ import annotations + +import typing as t +from datetime import datetime + + +class BadData(Exception): + """Raised if bad data of any sort was encountered. This is the base + for all exceptions that ItsDangerous defines. + + .. versionadded:: 0.15 + """ + + def __init__(self, message: str): + super().__init__(message) + self.message = message + + def __str__(self) -> str: + return self.message + + +class BadSignature(BadData): + """Raised if a signature does not match.""" + + def __init__(self, message: str, payload: t.Any | None = None): + super().__init__(message) + + #: The payload that failed the signature test. In some + #: situations you might still want to inspect this, even if + #: you know it was tampered with. + #: + #: .. versionadded:: 0.14 + self.payload: t.Any | None = payload + + +class BadTimeSignature(BadSignature): + """Raised if a time-based signature is invalid. This is a subclass + of :class:`BadSignature`. + """ + + def __init__( + self, + message: str, + payload: t.Any | None = None, + date_signed: datetime | None = None, + ): + super().__init__(message, payload) + + #: If the signature expired this exposes the date of when the + #: signature was created. This can be helpful in order to + #: tell the user how long a link has been gone stale. + #: + #: .. versionchanged:: 2.0 + #: The datetime value is timezone-aware rather than naive. + #: + #: .. versionadded:: 0.14 + self.date_signed = date_signed + + +class SignatureExpired(BadTimeSignature): + """Raised if a signature timestamp is older than ``max_age``. This + is a subclass of :exc:`BadTimeSignature`. + """ + + +class BadHeader(BadSignature): + """Raised if a signed header is invalid in some form. This only + happens for serializers that have a header that goes with the + signature. + + .. versionadded:: 0.24 + """ + + def __init__( + self, + message: str, + payload: t.Any | None = None, + header: t.Any | None = None, + original_error: Exception | None = None, + ): + super().__init__(message, payload) + + #: If the header is actually available but just malformed it + #: might be stored here. + self.header: t.Any | None = header + + #: If available, the error that indicates why the payload was + #: not valid. This might be ``None``. + self.original_error: Exception | None = original_error + + +class BadPayload(BadData): + """Raised if a payload is invalid. This could happen if the payload + is loaded despite an invalid signature, or if there is a mismatch + between the serializer and deserializer. The original exception + that occurred during loading is stored on as :attr:`original_error`. + + .. versionadded:: 0.15 + """ + + def __init__(self, message: str, original_error: Exception | None = None): + super().__init__(message) + + #: If available, the error that indicates why the payload was + #: not valid. This might be ``None``. + self.original_error: Exception | None = original_error diff --git a/backend/venv/Lib/site-packages/itsdangerous/py.typed b/backend/venv/Lib/site-packages/itsdangerous/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/backend/venv/Lib/site-packages/itsdangerous/serializer.py b/backend/venv/Lib/site-packages/itsdangerous/serializer.py new file mode 100644 index 0000000..5ddf387 --- /dev/null +++ b/backend/venv/Lib/site-packages/itsdangerous/serializer.py @@ -0,0 +1,406 @@ +from __future__ import annotations + +import collections.abc as cabc +import json +import typing as t + +from .encoding import want_bytes +from .exc import BadPayload +from .exc import BadSignature +from .signer import _make_keys_list +from .signer import Signer + +if t.TYPE_CHECKING: + import typing_extensions as te + + # This should be either be str or bytes. To avoid having to specify the + # bound type, it falls back to a union if structural matching fails. + _TSerialized = te.TypeVar( + "_TSerialized", bound=t.Union[str, bytes], default=t.Union[str, bytes] + ) +else: + # Still available at runtime on Python < 3.13, but without the default. + _TSerialized = t.TypeVar("_TSerialized", bound=t.Union[str, bytes]) + + +class _PDataSerializer(t.Protocol[_TSerialized]): + def loads(self, payload: _TSerialized, /) -> t.Any: ... + # A signature with additional arguments is not handled correctly by type + # checkers right now, so an overload is used below for serializers that + # don't match this strict protocol. + def dumps(self, obj: t.Any, /) -> _TSerialized: ... + + +# Use TypeIs once it's available in typing_extensions or 3.13. +def is_text_serializer( + serializer: _PDataSerializer[t.Any], +) -> te.TypeGuard[_PDataSerializer[str]]: + """Checks whether a serializer generates text or binary.""" + return isinstance(serializer.dumps({}), str) + + +class Serializer(t.Generic[_TSerialized]): + """A serializer wraps a :class:`~itsdangerous.signer.Signer` to + enable serializing and securely signing data other than bytes. It + can unsign to verify that the data hasn't been changed. + + The serializer provides :meth:`dumps` and :meth:`loads`, similar to + :mod:`json`, and by default uses :mod:`json` internally to serialize + the data to bytes. + + The secret key should be a random string of ``bytes`` and should not + be saved to code or version control. Different salts should be used + to distinguish signing in different contexts. See :doc:`/concepts` + for information about the security of the secret key and salt. + + :param secret_key: The secret key to sign and verify with. Can be a + list of keys, oldest to newest, to support key rotation. + :param salt: Extra key to combine with ``secret_key`` to distinguish + signatures in different contexts. + :param serializer: An object that provides ``dumps`` and ``loads`` + methods for serializing data to a string. Defaults to + :attr:`default_serializer`, which defaults to :mod:`json`. + :param serializer_kwargs: Keyword arguments to pass when calling + ``serializer.dumps``. + :param signer: A ``Signer`` class to instantiate when signing data. + Defaults to :attr:`default_signer`, which defaults to + :class:`~itsdangerous.signer.Signer`. + :param signer_kwargs: Keyword arguments to pass when instantiating + the ``Signer`` class. + :param fallback_signers: List of signer parameters to try when + unsigning with the default signer fails. Each item can be a dict + of ``signer_kwargs``, a ``Signer`` class, or a tuple of + ``(signer, signer_kwargs)``. Defaults to + :attr:`default_fallback_signers`. + + .. versionchanged:: 2.0 + Added support for key rotation by passing a list to + ``secret_key``. + + .. versionchanged:: 2.0 + Removed the default SHA-512 fallback signer from + ``default_fallback_signers``. + + .. versionchanged:: 1.1 + Added support for ``fallback_signers`` and configured a default + SHA-512 fallback. This fallback is for users who used the yanked + 1.0.0 release which defaulted to SHA-512. + + .. versionchanged:: 0.14 + The ``signer`` and ``signer_kwargs`` parameters were added to + the constructor. + """ + + #: The default serialization module to use to serialize data to a + #: string internally. The default is :mod:`json`, but can be changed + #: to any object that provides ``dumps`` and ``loads`` methods. + default_serializer: _PDataSerializer[t.Any] = json + + #: The default ``Signer`` class to instantiate when signing data. + #: The default is :class:`itsdangerous.signer.Signer`. + default_signer: type[Signer] = Signer + + #: The default fallback signers to try when unsigning fails. + default_fallback_signers: list[ + dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] + ] = [] + + # Serializer[str] if no data serializer is provided, or if it returns str. + @t.overload + def __init__( + self: Serializer[str], + secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], + salt: str | bytes | None = b"itsdangerous", + serializer: None | _PDataSerializer[str] = None, + serializer_kwargs: dict[str, t.Any] | None = None, + signer: type[Signer] | None = None, + signer_kwargs: dict[str, t.Any] | None = None, + fallback_signers: list[ + dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] + ] + | None = None, + ): ... + + # Serializer[bytes] with a bytes data serializer positional argument. + @t.overload + def __init__( + self: Serializer[bytes], + secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], + salt: str | bytes | None, + serializer: _PDataSerializer[bytes], + serializer_kwargs: dict[str, t.Any] | None = None, + signer: type[Signer] | None = None, + signer_kwargs: dict[str, t.Any] | None = None, + fallback_signers: list[ + dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] + ] + | None = None, + ): ... + + # Serializer[bytes] with a bytes data serializer keyword argument. + @t.overload + def __init__( + self: Serializer[bytes], + secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], + salt: str | bytes | None = b"itsdangerous", + *, + serializer: _PDataSerializer[bytes], + serializer_kwargs: dict[str, t.Any] | None = None, + signer: type[Signer] | None = None, + signer_kwargs: dict[str, t.Any] | None = None, + fallback_signers: list[ + dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] + ] + | None = None, + ): ... + + # Fall back with a positional argument. If the strict signature of + # _PDataSerializer doesn't match, fall back to a union, requiring the user + # to specify the type. + @t.overload + def __init__( + self, + secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], + salt: str | bytes | None, + serializer: t.Any, + serializer_kwargs: dict[str, t.Any] | None = None, + signer: type[Signer] | None = None, + signer_kwargs: dict[str, t.Any] | None = None, + fallback_signers: list[ + dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] + ] + | None = None, + ): ... + + # Fall back with a keyword argument. + @t.overload + def __init__( + self, + secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], + salt: str | bytes | None = b"itsdangerous", + *, + serializer: t.Any, + serializer_kwargs: dict[str, t.Any] | None = None, + signer: type[Signer] | None = None, + signer_kwargs: dict[str, t.Any] | None = None, + fallback_signers: list[ + dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] + ] + | None = None, + ): ... + + def __init__( + self, + secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], + salt: str | bytes | None = b"itsdangerous", + serializer: t.Any | None = None, + serializer_kwargs: dict[str, t.Any] | None = None, + signer: type[Signer] | None = None, + signer_kwargs: dict[str, t.Any] | None = None, + fallback_signers: list[ + dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] + ] + | None = None, + ): + #: The list of secret keys to try for verifying signatures, from + #: oldest to newest. The newest (last) key is used for signing. + #: + #: This allows a key rotation system to keep a list of allowed + #: keys and remove expired ones. + self.secret_keys: list[bytes] = _make_keys_list(secret_key) + + if salt is not None: + salt = want_bytes(salt) + # if salt is None then the signer's default is used + + self.salt = salt + + if serializer is None: + serializer = self.default_serializer + + self.serializer: _PDataSerializer[_TSerialized] = serializer + self.is_text_serializer: bool = is_text_serializer(serializer) + + if signer is None: + signer = self.default_signer + + self.signer: type[Signer] = signer + self.signer_kwargs: dict[str, t.Any] = signer_kwargs or {} + + if fallback_signers is None: + fallback_signers = list(self.default_fallback_signers) + + self.fallback_signers: list[ + dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] + ] = fallback_signers + self.serializer_kwargs: dict[str, t.Any] = serializer_kwargs or {} + + @property + def secret_key(self) -> bytes: + """The newest (last) entry in the :attr:`secret_keys` list. This + is for compatibility from before key rotation support was added. + """ + return self.secret_keys[-1] + + def load_payload( + self, payload: bytes, serializer: _PDataSerializer[t.Any] | None = None + ) -> t.Any: + """Loads the encoded object. This function raises + :class:`.BadPayload` if the payload is not valid. The + ``serializer`` parameter can be used to override the serializer + stored on the class. The encoded ``payload`` should always be + bytes. + """ + if serializer is None: + use_serializer = self.serializer + is_text = self.is_text_serializer + else: + use_serializer = serializer + is_text = is_text_serializer(serializer) + + try: + if is_text: + return use_serializer.loads(payload.decode("utf-8")) # type: ignore[arg-type] + + return use_serializer.loads(payload) # type: ignore[arg-type] + except Exception as e: + raise BadPayload( + "Could not load the payload because an exception" + " occurred on unserializing the data.", + original_error=e, + ) from e + + def dump_payload(self, obj: t.Any) -> bytes: + """Dumps the encoded object. The return value is always bytes. + If the internal serializer returns text, the value will be + encoded as UTF-8. + """ + return want_bytes(self.serializer.dumps(obj, **self.serializer_kwargs)) + + def make_signer(self, salt: str | bytes | None = None) -> Signer: + """Creates a new instance of the signer to be used. The default + implementation uses the :class:`.Signer` base class. + """ + if salt is None: + salt = self.salt + + return self.signer(self.secret_keys, salt=salt, **self.signer_kwargs) + + def iter_unsigners(self, salt: str | bytes | None = None) -> cabc.Iterator[Signer]: + """Iterates over all signers to be tried for unsigning. Starts + with the configured signer, then constructs each signer + specified in ``fallback_signers``. + """ + if salt is None: + salt = self.salt + + yield self.make_signer(salt) + + for fallback in self.fallback_signers: + if isinstance(fallback, dict): + kwargs = fallback + fallback = self.signer + elif isinstance(fallback, tuple): + fallback, kwargs = fallback + else: + kwargs = self.signer_kwargs + + for secret_key in self.secret_keys: + yield fallback(secret_key, salt=salt, **kwargs) + + def dumps(self, obj: t.Any, salt: str | bytes | None = None) -> _TSerialized: + """Returns a signed string serialized with the internal + serializer. The return value can be either a byte or unicode + string depending on the format of the internal serializer. + """ + payload = want_bytes(self.dump_payload(obj)) + rv = self.make_signer(salt).sign(payload) + + if self.is_text_serializer: + return rv.decode("utf-8") # type: ignore[return-value] + + return rv # type: ignore[return-value] + + def dump(self, obj: t.Any, f: t.IO[t.Any], salt: str | bytes | None = None) -> None: + """Like :meth:`dumps` but dumps into a file. The file handle has + to be compatible with what the internal serializer expects. + """ + f.write(self.dumps(obj, salt)) + + def loads( + self, s: str | bytes, salt: str | bytes | None = None, **kwargs: t.Any + ) -> t.Any: + """Reverse of :meth:`dumps`. Raises :exc:`.BadSignature` if the + signature validation fails. + """ + s = want_bytes(s) + last_exception = None + + for signer in self.iter_unsigners(salt): + try: + return self.load_payload(signer.unsign(s)) + except BadSignature as err: + last_exception = err + + raise t.cast(BadSignature, last_exception) + + def load(self, f: t.IO[t.Any], salt: str | bytes | None = None) -> t.Any: + """Like :meth:`loads` but loads from a file.""" + return self.loads(f.read(), salt) + + def loads_unsafe( + self, s: str | bytes, salt: str | bytes | None = None + ) -> tuple[bool, t.Any]: + """Like :meth:`loads` but without verifying the signature. This + is potentially very dangerous to use depending on how your + serializer works. The return value is ``(signature_valid, + payload)`` instead of just the payload. The first item will be a + boolean that indicates if the signature is valid. This function + never fails. + + Use it for debugging only and if you know that your serializer + module is not exploitable (for example, do not use it with a + pickle serializer). + + .. versionadded:: 0.15 + """ + return self._loads_unsafe_impl(s, salt) + + def _loads_unsafe_impl( + self, + s: str | bytes, + salt: str | bytes | None, + load_kwargs: dict[str, t.Any] | None = None, + load_payload_kwargs: dict[str, t.Any] | None = None, + ) -> tuple[bool, t.Any]: + """Low level helper function to implement :meth:`loads_unsafe` + in serializer subclasses. + """ + if load_kwargs is None: + load_kwargs = {} + + try: + return True, self.loads(s, salt=salt, **load_kwargs) + except BadSignature as e: + if e.payload is None: + return False, None + + if load_payload_kwargs is None: + load_payload_kwargs = {} + + try: + return ( + False, + self.load_payload(e.payload, **load_payload_kwargs), + ) + except BadPayload: + return False, None + + def load_unsafe( + self, f: t.IO[t.Any], salt: str | bytes | None = None + ) -> tuple[bool, t.Any]: + """Like :meth:`loads_unsafe` but loads from a file. + + .. versionadded:: 0.15 + """ + return self.loads_unsafe(f.read(), salt=salt) diff --git a/backend/venv/Lib/site-packages/itsdangerous/signer.py b/backend/venv/Lib/site-packages/itsdangerous/signer.py new file mode 100644 index 0000000..e324dc0 --- /dev/null +++ b/backend/venv/Lib/site-packages/itsdangerous/signer.py @@ -0,0 +1,266 @@ +from __future__ import annotations + +import collections.abc as cabc +import hashlib +import hmac +import typing as t + +from .encoding import _base64_alphabet +from .encoding import base64_decode +from .encoding import base64_encode +from .encoding import want_bytes +from .exc import BadSignature + + +class SigningAlgorithm: + """Subclasses must implement :meth:`get_signature` to provide + signature generation functionality. + """ + + def get_signature(self, key: bytes, value: bytes) -> bytes: + """Returns the signature for the given key and value.""" + raise NotImplementedError() + + def verify_signature(self, key: bytes, value: bytes, sig: bytes) -> bool: + """Verifies the given signature matches the expected + signature. + """ + return hmac.compare_digest(sig, self.get_signature(key, value)) + + +class NoneAlgorithm(SigningAlgorithm): + """Provides an algorithm that does not perform any signing and + returns an empty signature. + """ + + def get_signature(self, key: bytes, value: bytes) -> bytes: + return b"" + + +def _lazy_sha1(string: bytes = b"") -> t.Any: + """Don't access ``hashlib.sha1`` until runtime. FIPS builds may not include + SHA-1, in which case the import and use as a default would fail before the + developer can configure something else. + """ + return hashlib.sha1(string) + + +class HMACAlgorithm(SigningAlgorithm): + """Provides signature generation using HMACs.""" + + #: The digest method to use with the MAC algorithm. This defaults to + #: SHA1, but can be changed to any other function in the hashlib + #: module. + default_digest_method: t.Any = staticmethod(_lazy_sha1) + + def __init__(self, digest_method: t.Any = None): + if digest_method is None: + digest_method = self.default_digest_method + + self.digest_method: t.Any = digest_method + + def get_signature(self, key: bytes, value: bytes) -> bytes: + mac = hmac.new(key, msg=value, digestmod=self.digest_method) + return mac.digest() + + +def _make_keys_list( + secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], +) -> list[bytes]: + if isinstance(secret_key, (str, bytes)): + return [want_bytes(secret_key)] + + return [want_bytes(s) for s in secret_key] # pyright: ignore + + +class Signer: + """A signer securely signs bytes, then unsigns them to verify that + the value hasn't been changed. + + The secret key should be a random string of ``bytes`` and should not + be saved to code or version control. Different salts should be used + to distinguish signing in different contexts. See :doc:`/concepts` + for information about the security of the secret key and salt. + + :param secret_key: The secret key to sign and verify with. Can be a + list of keys, oldest to newest, to support key rotation. + :param salt: Extra key to combine with ``secret_key`` to distinguish + signatures in different contexts. + :param sep: Separator between the signature and value. + :param key_derivation: How to derive the signing key from the secret + key and salt. Possible values are ``concat``, ``django-concat``, + or ``hmac``. Defaults to :attr:`default_key_derivation`, which + defaults to ``django-concat``. + :param digest_method: Hash function to use when generating the HMAC + signature. Defaults to :attr:`default_digest_method`, which + defaults to :func:`hashlib.sha1`. Note that the security of the + hash alone doesn't apply when used intermediately in HMAC. + :param algorithm: A :class:`SigningAlgorithm` instance to use + instead of building a default :class:`HMACAlgorithm` with the + ``digest_method``. + + .. versionchanged:: 2.0 + Added support for key rotation by passing a list to + ``secret_key``. + + .. versionchanged:: 0.18 + ``algorithm`` was added as an argument to the class constructor. + + .. versionchanged:: 0.14 + ``key_derivation`` and ``digest_method`` were added as arguments + to the class constructor. + """ + + #: The default digest method to use for the signer. The default is + #: :func:`hashlib.sha1`, but can be changed to any :mod:`hashlib` or + #: compatible object. Note that the security of the hash alone + #: doesn't apply when used intermediately in HMAC. + #: + #: .. versionadded:: 0.14 + default_digest_method: t.Any = staticmethod(_lazy_sha1) + + #: The default scheme to use to derive the signing key from the + #: secret key and salt. The default is ``django-concat``. Possible + #: values are ``concat``, ``django-concat``, and ``hmac``. + #: + #: .. versionadded:: 0.14 + default_key_derivation: str = "django-concat" + + def __init__( + self, + secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], + salt: str | bytes | None = b"itsdangerous.Signer", + sep: str | bytes = b".", + key_derivation: str | None = None, + digest_method: t.Any | None = None, + algorithm: SigningAlgorithm | None = None, + ): + #: The list of secret keys to try for verifying signatures, from + #: oldest to newest. The newest (last) key is used for signing. + #: + #: This allows a key rotation system to keep a list of allowed + #: keys and remove expired ones. + self.secret_keys: list[bytes] = _make_keys_list(secret_key) + self.sep: bytes = want_bytes(sep) + + if self.sep in _base64_alphabet: + raise ValueError( + "The given separator cannot be used because it may be" + " contained in the signature itself. ASCII letters," + " digits, and '-_=' must not be used." + ) + + if salt is not None: + salt = want_bytes(salt) + else: + salt = b"itsdangerous.Signer" + + self.salt = salt + + if key_derivation is None: + key_derivation = self.default_key_derivation + + self.key_derivation: str = key_derivation + + if digest_method is None: + digest_method = self.default_digest_method + + self.digest_method: t.Any = digest_method + + if algorithm is None: + algorithm = HMACAlgorithm(self.digest_method) + + self.algorithm: SigningAlgorithm = algorithm + + @property + def secret_key(self) -> bytes: + """The newest (last) entry in the :attr:`secret_keys` list. This + is for compatibility from before key rotation support was added. + """ + return self.secret_keys[-1] + + def derive_key(self, secret_key: str | bytes | None = None) -> bytes: + """This method is called to derive the key. The default key + derivation choices can be overridden here. Key derivation is not + intended to be used as a security method to make a complex key + out of a short password. Instead you should use large random + secret keys. + + :param secret_key: A specific secret key to derive from. + Defaults to the last item in :attr:`secret_keys`. + + .. versionchanged:: 2.0 + Added the ``secret_key`` parameter. + """ + if secret_key is None: + secret_key = self.secret_keys[-1] + else: + secret_key = want_bytes(secret_key) + + if self.key_derivation == "concat": + return t.cast(bytes, self.digest_method(self.salt + secret_key).digest()) + elif self.key_derivation == "django-concat": + return t.cast( + bytes, self.digest_method(self.salt + b"signer" + secret_key).digest() + ) + elif self.key_derivation == "hmac": + mac = hmac.new(secret_key, digestmod=self.digest_method) + mac.update(self.salt) + return mac.digest() + elif self.key_derivation == "none": + return secret_key + else: + raise TypeError("Unknown key derivation method") + + def get_signature(self, value: str | bytes) -> bytes: + """Returns the signature for the given value.""" + value = want_bytes(value) + key = self.derive_key() + sig = self.algorithm.get_signature(key, value) + return base64_encode(sig) + + def sign(self, value: str | bytes) -> bytes: + """Signs the given string.""" + value = want_bytes(value) + return value + self.sep + self.get_signature(value) + + def verify_signature(self, value: str | bytes, sig: str | bytes) -> bool: + """Verifies the signature for the given value.""" + try: + sig = base64_decode(sig) + except Exception: + return False + + value = want_bytes(value) + + for secret_key in reversed(self.secret_keys): + key = self.derive_key(secret_key) + + if self.algorithm.verify_signature(key, value, sig): + return True + + return False + + def unsign(self, signed_value: str | bytes) -> bytes: + """Unsigns the given string.""" + signed_value = want_bytes(signed_value) + + if self.sep not in signed_value: + raise BadSignature(f"No {self.sep!r} found in value") + + value, sig = signed_value.rsplit(self.sep, 1) + + if self.verify_signature(value, sig): + return value + + raise BadSignature(f"Signature {sig!r} does not match", payload=value) + + def validate(self, signed_value: str | bytes) -> bool: + """Only validates the given signed value. Returns ``True`` if + the signature exists and is valid. + """ + try: + self.unsign(signed_value) + return True + except BadSignature: + return False diff --git a/backend/venv/Lib/site-packages/itsdangerous/timed.py b/backend/venv/Lib/site-packages/itsdangerous/timed.py new file mode 100644 index 0000000..7384375 --- /dev/null +++ b/backend/venv/Lib/site-packages/itsdangerous/timed.py @@ -0,0 +1,228 @@ +from __future__ import annotations + +import collections.abc as cabc +import time +import typing as t +from datetime import datetime +from datetime import timezone + +from .encoding import base64_decode +from .encoding import base64_encode +from .encoding import bytes_to_int +from .encoding import int_to_bytes +from .encoding import want_bytes +from .exc import BadSignature +from .exc import BadTimeSignature +from .exc import SignatureExpired +from .serializer import _TSerialized +from .serializer import Serializer +from .signer import Signer + + +class TimestampSigner(Signer): + """Works like the regular :class:`.Signer` but also records the time + of the signing and can be used to expire signatures. The + :meth:`unsign` method can raise :exc:`.SignatureExpired` if the + unsigning failed because the signature is expired. + """ + + def get_timestamp(self) -> int: + """Returns the current timestamp. The function must return an + integer. + """ + return int(time.time()) + + def timestamp_to_datetime(self, ts: int) -> datetime: + """Convert the timestamp from :meth:`get_timestamp` into an + aware :class`datetime.datetime` in UTC. + + .. versionchanged:: 2.0 + The timestamp is returned as a timezone-aware ``datetime`` + in UTC rather than a naive ``datetime`` assumed to be UTC. + """ + return datetime.fromtimestamp(ts, tz=timezone.utc) + + def sign(self, value: str | bytes) -> bytes: + """Signs the given string and also attaches time information.""" + value = want_bytes(value) + timestamp = base64_encode(int_to_bytes(self.get_timestamp())) + sep = want_bytes(self.sep) + value = value + sep + timestamp + return value + sep + self.get_signature(value) + + # Ignore overlapping signatures check, return_timestamp is the only + # parameter that affects the return type. + + @t.overload + def unsign( # type: ignore[overload-overlap] + self, + signed_value: str | bytes, + max_age: int | None = None, + return_timestamp: t.Literal[False] = False, + ) -> bytes: ... + + @t.overload + def unsign( + self, + signed_value: str | bytes, + max_age: int | None = None, + return_timestamp: t.Literal[True] = True, + ) -> tuple[bytes, datetime]: ... + + def unsign( + self, + signed_value: str | bytes, + max_age: int | None = None, + return_timestamp: bool = False, + ) -> tuple[bytes, datetime] | bytes: + """Works like the regular :meth:`.Signer.unsign` but can also + validate the time. See the base docstring of the class for + the general behavior. If ``return_timestamp`` is ``True`` the + timestamp of the signature will be returned as an aware + :class:`datetime.datetime` object in UTC. + + .. versionchanged:: 2.0 + The timestamp is returned as a timezone-aware ``datetime`` + in UTC rather than a naive ``datetime`` assumed to be UTC. + """ + try: + result = super().unsign(signed_value) + sig_error = None + except BadSignature as e: + sig_error = e + result = e.payload or b"" + + sep = want_bytes(self.sep) + + # If there is no timestamp in the result there is something + # seriously wrong. In case there was a signature error, we raise + # that one directly, otherwise we have a weird situation in + # which we shouldn't have come except someone uses a time-based + # serializer on non-timestamp data, so catch that. + if sep not in result: + if sig_error: + raise sig_error + + raise BadTimeSignature("timestamp missing", payload=result) + + value, ts_bytes = result.rsplit(sep, 1) + ts_int: int | None = None + ts_dt: datetime | None = None + + try: + ts_int = bytes_to_int(base64_decode(ts_bytes)) + except Exception: + pass + + # Signature is *not* okay. Raise a proper error now that we have + # split the value and the timestamp. + if sig_error is not None: + if ts_int is not None: + try: + ts_dt = self.timestamp_to_datetime(ts_int) + except (ValueError, OSError, OverflowError) as exc: + # Windows raises OSError + # 32-bit raises OverflowError + raise BadTimeSignature( + "Malformed timestamp", payload=value + ) from exc + + raise BadTimeSignature(str(sig_error), payload=value, date_signed=ts_dt) + + # Signature was okay but the timestamp is actually not there or + # malformed. Should not happen, but we handle it anyway. + if ts_int is None: + raise BadTimeSignature("Malformed timestamp", payload=value) + + # Check timestamp is not older than max_age + if max_age is not None: + age = self.get_timestamp() - ts_int + + if age > max_age: + raise SignatureExpired( + f"Signature age {age} > {max_age} seconds", + payload=value, + date_signed=self.timestamp_to_datetime(ts_int), + ) + + if age < 0: + raise SignatureExpired( + f"Signature age {age} < 0 seconds", + payload=value, + date_signed=self.timestamp_to_datetime(ts_int), + ) + + if return_timestamp: + return value, self.timestamp_to_datetime(ts_int) + + return value + + def validate(self, signed_value: str | bytes, max_age: int | None = None) -> bool: + """Only validates the given signed value. Returns ``True`` if + the signature exists and is valid.""" + try: + self.unsign(signed_value, max_age=max_age) + return True + except BadSignature: + return False + + +class TimedSerializer(Serializer[_TSerialized]): + """Uses :class:`TimestampSigner` instead of the default + :class:`.Signer`. + """ + + default_signer: type[TimestampSigner] = TimestampSigner + + def iter_unsigners( + self, salt: str | bytes | None = None + ) -> cabc.Iterator[TimestampSigner]: + return t.cast("cabc.Iterator[TimestampSigner]", super().iter_unsigners(salt)) + + # TODO: Signature is incompatible because parameters were added + # before salt. + + def loads( # type: ignore[override] + self, + s: str | bytes, + max_age: int | None = None, + return_timestamp: bool = False, + salt: str | bytes | None = None, + ) -> t.Any: + """Reverse of :meth:`dumps`, raises :exc:`.BadSignature` if the + signature validation fails. If a ``max_age`` is provided it will + ensure the signature is not older than that time in seconds. In + case the signature is outdated, :exc:`.SignatureExpired` is + raised. All arguments are forwarded to the signer's + :meth:`~TimestampSigner.unsign` method. + """ + s = want_bytes(s) + last_exception = None + + for signer in self.iter_unsigners(salt): + try: + base64d, timestamp = signer.unsign( + s, max_age=max_age, return_timestamp=True + ) + payload = self.load_payload(base64d) + + if return_timestamp: + return payload, timestamp + + return payload + except SignatureExpired: + # The signature was unsigned successfully but was + # expired. Do not try the next signer. + raise + except BadSignature as err: + last_exception = err + + raise t.cast(BadSignature, last_exception) + + def loads_unsafe( # type: ignore[override] + self, + s: str | bytes, + max_age: int | None = None, + salt: str | bytes | None = None, + ) -> tuple[bool, t.Any]: + return self._loads_unsafe_impl(s, salt, load_kwargs={"max_age": max_age}) diff --git a/backend/venv/Lib/site-packages/itsdangerous/url_safe.py b/backend/venv/Lib/site-packages/itsdangerous/url_safe.py new file mode 100644 index 0000000..56a0793 --- /dev/null +++ b/backend/venv/Lib/site-packages/itsdangerous/url_safe.py @@ -0,0 +1,83 @@ +from __future__ import annotations + +import typing as t +import zlib + +from ._json import _CompactJSON +from .encoding import base64_decode +from .encoding import base64_encode +from .exc import BadPayload +from .serializer import _PDataSerializer +from .serializer import Serializer +from .timed import TimedSerializer + + +class URLSafeSerializerMixin(Serializer[str]): + """Mixed in with a regular serializer it will attempt to zlib + compress the string to make it shorter if necessary. It will also + base64 encode the string so that it can safely be placed in a URL. + """ + + default_serializer: _PDataSerializer[str] = _CompactJSON + + def load_payload( + self, + payload: bytes, + *args: t.Any, + serializer: t.Any | None = None, + **kwargs: t.Any, + ) -> t.Any: + decompress = False + + if payload.startswith(b"."): + payload = payload[1:] + decompress = True + + try: + json = base64_decode(payload) + except Exception as e: + raise BadPayload( + "Could not base64 decode the payload because of an exception", + original_error=e, + ) from e + + if decompress: + try: + json = zlib.decompress(json) + except Exception as e: + raise BadPayload( + "Could not zlib decompress the payload before decoding the payload", + original_error=e, + ) from e + + return super().load_payload(json, *args, **kwargs) + + def dump_payload(self, obj: t.Any) -> bytes: + json = super().dump_payload(obj) + is_compressed = False + compressed = zlib.compress(json) + + if len(compressed) < (len(json) - 1): + json = compressed + is_compressed = True + + base64d = base64_encode(json) + + if is_compressed: + base64d = b"." + base64d + + return base64d + + +class URLSafeSerializer(URLSafeSerializerMixin, Serializer[str]): + """Works like :class:`.Serializer` but dumps and loads into a URL + safe string consisting of the upper and lowercase character of the + alphabet as well as ``'_'``, ``'-'`` and ``'.'``. + """ + + +class URLSafeTimedSerializer(URLSafeSerializerMixin, TimedSerializer[str]): + """Works like :class:`.TimedSerializer` but dumps and loads into a + URL safe string consisting of the upper and lowercase character of + the alphabet as well as ``'_'``, ``'-'`` and ``'.'``. + """ diff --git a/backend/venv/Lib/site-packages/jinja2-3.1.6.dist-info/INSTALLER b/backend/venv/Lib/site-packages/jinja2-3.1.6.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/backend/venv/Lib/site-packages/jinja2-3.1.6.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/backend/venv/Lib/site-packages/jinja2-3.1.6.dist-info/METADATA b/backend/venv/Lib/site-packages/jinja2-3.1.6.dist-info/METADATA new file mode 100644 index 0000000..ffef2ff --- /dev/null +++ b/backend/venv/Lib/site-packages/jinja2-3.1.6.dist-info/METADATA @@ -0,0 +1,84 @@ +Metadata-Version: 2.4 +Name: Jinja2 +Version: 3.1.6 +Summary: A very fast and expressive template engine. +Maintainer-email: Pallets +Requires-Python: >=3.7 +Description-Content-Type: text/markdown +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Text Processing :: Markup :: HTML +Classifier: Typing :: Typed +License-File: LICENSE.txt +Requires-Dist: MarkupSafe>=2.0 +Requires-Dist: Babel>=2.7 ; extra == "i18n" +Project-URL: Changes, https://jinja.palletsprojects.com/changes/ +Project-URL: Chat, https://discord.gg/pallets +Project-URL: Documentation, https://jinja.palletsprojects.com/ +Project-URL: Donate, https://palletsprojects.com/donate +Project-URL: Source, https://github.com/pallets/jinja/ +Provides-Extra: i18n + +# Jinja + +Jinja is a fast, expressive, extensible templating engine. Special +placeholders in the template allow writing code similar to Python +syntax. Then the template is passed data to render the final document. + +It includes: + +- Template inheritance and inclusion. +- Define and import macros within templates. +- HTML templates can use autoescaping to prevent XSS from untrusted + user input. +- A sandboxed environment can safely render untrusted templates. +- AsyncIO support for generating templates and calling async + functions. +- I18N support with Babel. +- Templates are compiled to optimized Python code just-in-time and + cached, or can be compiled ahead-of-time. +- Exceptions point to the correct line in templates to make debugging + easier. +- Extensible filters, tests, functions, and even syntax. + +Jinja's philosophy is that while application logic belongs in Python if +possible, it shouldn't make the template designer's job difficult by +restricting functionality too much. + + +## In A Nutshell + +```jinja +{% extends "base.html" %} +{% block title %}Members{% endblock %} +{% block content %} +

+{% endblock %} +``` + +## Donate + +The Pallets organization develops and supports Jinja and other popular +packages. In order to grow the community of contributors and users, and +allow the maintainers to devote more time to the projects, [please +donate today][]. + +[please donate today]: https://palletsprojects.com/donate + +## Contributing + +See our [detailed contributing documentation][contrib] for many ways to +contribute, including reporting issues, requesting features, asking or answering +questions, and making PRs. + +[contrib]: https://palletsprojects.com/contributing/ + diff --git a/backend/venv/Lib/site-packages/jinja2-3.1.6.dist-info/RECORD b/backend/venv/Lib/site-packages/jinja2-3.1.6.dist-info/RECORD new file mode 100644 index 0000000..0ca35a7 --- /dev/null +++ b/backend/venv/Lib/site-packages/jinja2-3.1.6.dist-info/RECORD @@ -0,0 +1,57 @@ +jinja2-3.1.6.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +jinja2-3.1.6.dist-info/METADATA,sha256=aMVUj7Z8QTKhOJjZsx7FDGvqKr3ZFdkh8hQ1XDpkmcg,2871 +jinja2-3.1.6.dist-info/RECORD,, +jinja2-3.1.6.dist-info/WHEEL,sha256=_2ozNFCLWc93bK4WKHCO-eDUENDlo-dgc9cU3qokYO4,82 +jinja2-3.1.6.dist-info/entry_points.txt,sha256=OL85gYU1eD8cuPlikifFngXpeBjaxl6rIJ8KkC_3r-I,58 +jinja2-3.1.6.dist-info/licenses/LICENSE.txt,sha256=O0nc7kEF6ze6wQ-vG-JgQI_oXSUrjp3y4JefweCUQ3s,1475 +jinja2/__init__.py,sha256=xxepO9i7DHsqkQrgBEduLtfoz2QCuT6_gbL4XSN1hbU,1928 +jinja2/__pycache__/__init__.cpython-312.pyc,, +jinja2/__pycache__/_identifier.cpython-312.pyc,, +jinja2/__pycache__/async_utils.cpython-312.pyc,, +jinja2/__pycache__/bccache.cpython-312.pyc,, +jinja2/__pycache__/compiler.cpython-312.pyc,, +jinja2/__pycache__/constants.cpython-312.pyc,, +jinja2/__pycache__/debug.cpython-312.pyc,, +jinja2/__pycache__/defaults.cpython-312.pyc,, +jinja2/__pycache__/environment.cpython-312.pyc,, +jinja2/__pycache__/exceptions.cpython-312.pyc,, +jinja2/__pycache__/ext.cpython-312.pyc,, +jinja2/__pycache__/filters.cpython-312.pyc,, +jinja2/__pycache__/idtracking.cpython-312.pyc,, +jinja2/__pycache__/lexer.cpython-312.pyc,, +jinja2/__pycache__/loaders.cpython-312.pyc,, +jinja2/__pycache__/meta.cpython-312.pyc,, +jinja2/__pycache__/nativetypes.cpython-312.pyc,, +jinja2/__pycache__/nodes.cpython-312.pyc,, +jinja2/__pycache__/optimizer.cpython-312.pyc,, +jinja2/__pycache__/parser.cpython-312.pyc,, +jinja2/__pycache__/runtime.cpython-312.pyc,, +jinja2/__pycache__/sandbox.cpython-312.pyc,, +jinja2/__pycache__/tests.cpython-312.pyc,, +jinja2/__pycache__/utils.cpython-312.pyc,, +jinja2/__pycache__/visitor.cpython-312.pyc,, +jinja2/_identifier.py,sha256=_zYctNKzRqlk_murTNlzrju1FFJL7Va_Ijqqd7ii2lU,1958 +jinja2/async_utils.py,sha256=vK-PdsuorOMnWSnEkT3iUJRIkTnYgO2T6MnGxDgHI5o,2834 +jinja2/bccache.py,sha256=gh0qs9rulnXo0PhX5jTJy2UHzI8wFnQ63o_vw7nhzRg,14061 +jinja2/compiler.py,sha256=9RpCQl5X88BHllJiPsHPh295Hh0uApvwFJNQuutULeM,74131 +jinja2/constants.py,sha256=GMoFydBF_kdpaRKPoM5cl5MviquVRLVyZtfp5-16jg0,1433 +jinja2/debug.py,sha256=CnHqCDHd-BVGvti_8ZsTolnXNhA3ECsY-6n_2pwU8Hw,6297 +jinja2/defaults.py,sha256=boBcSw78h-lp20YbaXSJsqkAI2uN_mD_TtCydpeq5wU,1267 +jinja2/environment.py,sha256=9nhrP7Ch-NbGX00wvyr4yy-uhNHq2OCc60ggGrni_fk,61513 +jinja2/exceptions.py,sha256=ioHeHrWwCWNaXX1inHmHVblvc4haO7AXsjCp3GfWvx0,5071 +jinja2/ext.py,sha256=5PF5eHfh8mXAIxXHHRB2xXbXohi8pE3nHSOxa66uS7E,31875 +jinja2/filters.py,sha256=PQ_Egd9n9jSgtnGQYyF4K5j2nYwhUIulhPnyimkdr-k,55212 +jinja2/idtracking.py,sha256=-ll5lIp73pML3ErUYiIJj7tdmWxcH_IlDv3yA_hiZYo,10555 +jinja2/lexer.py,sha256=LYiYio6br-Tep9nPcupWXsPEtjluw3p1mU-lNBVRUfk,29786 +jinja2/loaders.py,sha256=wIrnxjvcbqh5VwW28NSkfotiDq8qNCxIOSFbGUiSLB4,24055 +jinja2/meta.py,sha256=OTDPkaFvU2Hgvx-6akz7154F8BIWaRmvJcBFvwopHww,4397 +jinja2/nativetypes.py,sha256=7GIGALVJgdyL80oZJdQUaUfwSt5q2lSSZbXt0dNf_M4,4210 +jinja2/nodes.py,sha256=m1Duzcr6qhZI8JQ6VyJgUNinjAf5bQzijSmDnMsvUx8,34579 +jinja2/optimizer.py,sha256=rJnCRlQ7pZsEEmMhsQDgC_pKyDHxP5TPS6zVPGsgcu8,1651 +jinja2/parser.py,sha256=lLOFy3sEmHc5IaEHRiH1sQVnId2moUQzhyeJZTtdY30,40383 +jinja2/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +jinja2/runtime.py,sha256=gDk-GvdriJXqgsGbHgrcKTP0Yp6zPXzhzrIpCFH3jAU,34249 +jinja2/sandbox.py,sha256=Mw2aitlY2I8la7FYhcX2YG9BtUYcLnD0Gh3d29cDWrY,15009 +jinja2/tests.py,sha256=VLsBhVFnWg-PxSBz1MhRnNWgP1ovXk3neO1FLQMeC9Q,5926 +jinja2/utils.py,sha256=rRp3o9e7ZKS4fyrWRbELyLcpuGVTFcnooaOa1qx_FIk,24129 +jinja2/visitor.py,sha256=EcnL1PIwf_4RVCOMxsRNuR8AXHbS1qfAdMOE2ngKJz4,3557 diff --git a/backend/venv/Lib/site-packages/jinja2-3.1.6.dist-info/WHEEL b/backend/venv/Lib/site-packages/jinja2-3.1.6.dist-info/WHEEL new file mode 100644 index 0000000..23d2d7e --- /dev/null +++ b/backend/venv/Lib/site-packages/jinja2-3.1.6.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: flit 3.11.0 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/backend/venv/Lib/site-packages/jinja2-3.1.6.dist-info/entry_points.txt b/backend/venv/Lib/site-packages/jinja2-3.1.6.dist-info/entry_points.txt new file mode 100644 index 0000000..abc3eae --- /dev/null +++ b/backend/venv/Lib/site-packages/jinja2-3.1.6.dist-info/entry_points.txt @@ -0,0 +1,3 @@ +[babel.extractors] +jinja2=jinja2.ext:babel_extract[i18n] + diff --git a/backend/venv/Lib/site-packages/jinja2-3.1.6.dist-info/licenses/LICENSE.txt b/backend/venv/Lib/site-packages/jinja2-3.1.6.dist-info/licenses/LICENSE.txt new file mode 100644 index 0000000..c37cae4 --- /dev/null +++ b/backend/venv/Lib/site-packages/jinja2-3.1.6.dist-info/licenses/LICENSE.txt @@ -0,0 +1,28 @@ +Copyright 2007 Pallets + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/backend/venv/Lib/site-packages/jinja2/__init__.py b/backend/venv/Lib/site-packages/jinja2/__init__.py new file mode 100644 index 0000000..1a423a3 --- /dev/null +++ b/backend/venv/Lib/site-packages/jinja2/__init__.py @@ -0,0 +1,38 @@ +"""Jinja is a template engine written in pure Python. It provides a +non-XML syntax that supports inline expressions and an optional +sandboxed environment. +""" + +from .bccache import BytecodeCache as BytecodeCache +from .bccache import FileSystemBytecodeCache as FileSystemBytecodeCache +from .bccache import MemcachedBytecodeCache as MemcachedBytecodeCache +from .environment import Environment as Environment +from .environment import Template as Template +from .exceptions import TemplateAssertionError as TemplateAssertionError +from .exceptions import TemplateError as TemplateError +from .exceptions import TemplateNotFound as TemplateNotFound +from .exceptions import TemplateRuntimeError as TemplateRuntimeError +from .exceptions import TemplatesNotFound as TemplatesNotFound +from .exceptions import TemplateSyntaxError as TemplateSyntaxError +from .exceptions import UndefinedError as UndefinedError +from .loaders import BaseLoader as BaseLoader +from .loaders import ChoiceLoader as ChoiceLoader +from .loaders import DictLoader as DictLoader +from .loaders import FileSystemLoader as FileSystemLoader +from .loaders import FunctionLoader as FunctionLoader +from .loaders import ModuleLoader as ModuleLoader +from .loaders import PackageLoader as PackageLoader +from .loaders import PrefixLoader as PrefixLoader +from .runtime import ChainableUndefined as ChainableUndefined +from .runtime import DebugUndefined as DebugUndefined +from .runtime import make_logging_undefined as make_logging_undefined +from .runtime import StrictUndefined as StrictUndefined +from .runtime import Undefined as Undefined +from .utils import clear_caches as clear_caches +from .utils import is_undefined as is_undefined +from .utils import pass_context as pass_context +from .utils import pass_environment as pass_environment +from .utils import pass_eval_context as pass_eval_context +from .utils import select_autoescape as select_autoescape + +__version__ = "3.1.6" diff --git a/backend/venv/Lib/site-packages/jinja2/__pycache__/__init__.cpython-312.pyc b/backend/venv/Lib/site-packages/jinja2/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6991ee6c47f694f1822d3711f831045c0be9bdae GIT binary patch literal 1666 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 literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/jinja2/__pycache__/async_utils.cpython-312.pyc b/backend/venv/Lib/site-packages/jinja2/__pycache__/async_utils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b6e79b845ee09d249ec0a162956b281f7c88a507 GIT binary patch literal 4987 zcmb_fT~J%c72dsnk`R&r0WtfAGIgiTn-V-7C+S1axmQ16 zle+D6LAz&n&z{|T_B%iO2Zy7GK>6~{-(D}X6Y>}A-^-kb^6*ogTjm&z_!zeBdkPPquy9=La{ zxhw2c0-O(wQ-9f)$kgGdy8HM`fzHmhmqLNAt|RRo&$o4ScfqhY#=^tum#7QqSwo#+ zRSmEKpi75=3@M}GSSXT+YszU&r#+FZ(u}P+sPUNVcmvaLnJLmwWjbY@q)FOE{9MN- zb_uxL$o>Hcd5=z$X>nSbAzEJKAPT&zT*%)O3YEzSc}q%CEzdP5C&owX9w?jFTiMTdrGkC`pl&n37V6G24{&T6TG^ofIxe%&vKIQjCei2GfhmcN`Nm^s3FFn=kzEdlD;&+8&r zxekUMzo1i17b0O5>b^uGrdy+GD6EdhBUdQ{k3v)gjrZGu!~1(*Ru!i9HZ?Xio$7rd zt~|@4qe}0yih4>*4EMhDLRaUp-Z4cv)zZrn>Ts;3w=WzyrNrglQ6)awdo0@5t41~D zv0)eu4=8HyU^G4$ZfY<#3yo;em|8zP&Jf`fP3GWem_@^Jt^PnP5ediCr|V@Ul3-yi z!3smU<5uEXcR+Q9ta`T1jJ`Yip*;8OeCd_;Wnc4xuX)kak}hdk2L`gWnq`>z|EPH@ zD=4U*IbkEe$Pm5^k;_V<((Rz6C`-hLl(=Rnf#Kzw+Gpj+_P=VT8s+SQY75P@F8ErP zeFqnO2NykobV-1rLHK#SC=?n>$RjZ&6arTjiid}gDh`F-7zxMB9y&4bThW2IB3}g; z#Bd+oGBPZOHARja$NzIMW|uq&veajwx^sqnC6Usq+45gFQ-LpB-W5;v zY+&}##nTssFI**m_SDWbr#(&cdlx)S>5`@|+&kxlw7X$mT5va{iyMsF==M7p+Olr# zXNjRuqHmC)e=+c*^MUxdi62oL8ICDBuPPeDP@xye(f)pgDe;KH&^s{vLfvgxooV5r ztbO^dtQP02MjQeS>Lms3g~FP~R8U_*SLP7&p-==RtHTNrrlS8p32O8nJeXCZEpM|E z-uo#MtwH@GRNnzq-POx(--6pWcVf}~c*?p`+XR+@1V$CbC$t{~R^=A6Py-T*%RUjwQzUG^KOSZs2IGe3;ohLU&O_*|ql2|={CVJnKUK47LO^RU+ zFooVhMaKXTy3IW#dNQ4q6j!8$azmajLbfoXFpMXg+!@~VdHAjW9;%~+ZgOb_lhd-1 zfRItbDmAnuqihv5WD4uD{9Qz|<$3dAJvTx~VF$MJK2o`Y)bo&lz6qdxpPS)-B8sF7 zhE|5w=DKl+xa(_ zD)%f{_N=-}-Wk0xdNDHFvgoQ!TWfDwoXeK&3zqG(ElZZ#)r!iQo_Biytn7ZRV3R;AE2| zgyTjTCs!%vv9=I|YeSTu(*;$D^+R%y9WmhR&B7M~L^K}NLZOM;@7ujT$MPfCLPZFj zAuCn2DdDGC`?v?ln06RPMBfKT1VFI;K$@0B*#V$8UY{)#0%#}Cbc~LX)BLMsjG`GBU+))nAr21&_5+ZlJGvnAGA}rqi0ft8-EiqJW}qBmGipnx z%BE{WjiIdjY0TuoEL6n{Fw7yt@wS##w`W$k?7ZY$bni|V@4mC@s`;8w7%%h9z4-C* zE5{eh9=q{)y14nf3=hNqR51rQM+1aTl~<8jBre&W;(uMakH0BC#s8LvfetwAQ@}Ri z(CW=EOE9!`&Tw@T7EP(|0whAj$0V2Gdy{R)3eA-r#0q@{!%V|~is^oh1Zp3SVRZz4 zDlVNO>l_v9)+H*IXCy&vnJc|bpfMLA>$eYU^)JUklPAFW^_^FRV1(8Q0R#)ouZ1s}m!4;Qh*;TvXs$F#LN?Ui` za_zn@%)fHYx#((5TU+lnAhg@_@LTVJ>iZ*66M2V5xB(L3p2$T3!Hfd<41Je-yBOkt zWiQN6LK+z1s6ma9f=N*0)PRsi*hr_RH-Ws^@ao{$V^LLOF963$_^Ies4Isl8?%Xpk zF72pawl^%=8)oTSfwaBh&Y$cJX`$g8XueT>zrx!V&@N>Z{y-#-*&G2671HmW! zih89v>JzS5{nRh8qrl4Au|kJ7QMM5@@N7XOds#C~=@NvlXnep-<7}9MYViD0joi)1 z*L2Z%6B)UmnY%fM*&wI!ja`@82Qd^`&jvhljEK8;&`y^6|C`*)W$!D9ZWH_8@ibD-& z=?l-V!};faUsZR{LnApk-2HbgO;vYw^;cD2ef8D%D*l(MDzAX+voHSV;Qx9`5dIrI zn3vPIS@~O05T=EM&?_Xwge@iZiY&MF+E{MywXtwmB*Tr&oubbtb zUN3Tc$~Wxq^@{{kN>vS4_g1reM=CHJ>luvN-cZ7saHZ;o>wD`( z!6tl7NVwk=5*{Tqw53qnyt`@VcfE}XZ*Nn=XA>01&<^u$Ay=9b{+l-bJdW(4^;|H0BSxFIHE@=gsZa%Lo(%%o!}xqmFH#4`y+j>qCC*T%H0G8~al4JI`i z|8tr$kW0zQ0eLKwlLuqx6#1N@j(Ovm;gOVbUPk4SR4j`Rli6I1U}|zKoshGDMRk&R zi9$IuAjeWE6lXNW`bhI?sm!P*Co-dHg0IT4k&#p~&Oga!GV*XPJ{a+OPZofW4k{`j zly)zMqRc>6Ny`Hn^=vYIMjloAi-BqQB9`@1y<|F>O~z8maU~(6W7N@sq^f0QRe3F^ zXxWJOGn&Dku&7JgU~D^b*Fhjj>pp>7cPDUlYHURL42Tp^;5(E)msB(9VI`f7(}(8e zF>Y2~#Lcvz2v{cqtr5kZuqo1jl(4@k^*TJDR95Ctq=Zv(4po}~3c2EDlw?at1MY80Ijm%I**Lu}zDh=>R^gROSPV;Q zfbMB@YKW3LBn-HWOAX>lw`&!9g3@(V*@5Jua5vPT*5Z!A4tsTXG@6bLE77R#jYfwv ziCl{A{n6-axme10W7o2(?x5wRsWsG+nAP1UjAf_Wlj*G5Kp?57960qyC9+}38r*1| zNZu5d+*@aM-ga-D-L>G}ns*9^#iQaqyUo+M)VMm&^5!<4?|kwn9Y5}PKmOxq+4J41 zn)?pa7&(V2Oiifdge^Et_GyLMd=L@CU5=0t<@Ba(A{>ljEuaE|%~T zVG#c+<`Vs5j7yYpN~$#y(~PEwjifTM1o57MTsqD;AvhPoBYxY@daB8waKH!ntfCV8 z1<#G2)pEn~fSMU*&2T;pz{xXd41=1%c|=bf>27mast;v7B@32_jxE?8+)N7-;)D>z9ls`Qcp}cqt_eGy zEH*YF3{eYZ*G=PD1XJV7Q&L+{##j9lxYHe~g5_*-gVL8}+yD!kWs8D+*U9geVli8kyTBI9lvHN<(D+KSt8ztM3v==~_sXx)Q{ zZHi1v-}SKG>Eb}i_CQR5&B-93(VPqwcONh5%2Ew>WhL|Orcuw#FW4q*g|}ycG_~d{ z=S|F-d!;bMBg@xb~la3`{@a-cX`_?Y`gIA7TI(qrolE3!Xp;gm+r}oag_Pu8&-Alf} zmHn6Y&!AFEaizQ@c|yxg>#zB*`e$GGeqgfeyWL+b2b~1(zJk^((>L@ZQ@RI)M^kXceq#+8d=z|A3`^sCyK=)LrP~_zqzo&082K67 zU8HBcDITMpVpN5gCqo0sju{)ADgy;!HzPL{8YIYwRZ_R%UfoUwQUWbA>Qr}9Wg8dL zh~^9tlnZ9n?85??)f;41T6~H=JBkDh4kYvRrKfNE)-KnsxxMzOh1%V>{kxako-3|P zuD9KH+^d$|)mMC%d~bD4AD=otyL~ox$KAH<4qWkH^1pRz`qimdXT?w48#sq_LVUw! zUYSJppg~3=k7Sbt##NYp#_dH3otzy*!PtHR4-9liR=OUOn$#{m$;$r@sH}C+^J;Zdkh8>)~h}M)tZr96nAlnQ%aD#AhnW%_@nkx+@w@Wa81Nx|)jGD50HLB~?auA55lW>R9&) zHm|x3Hze7!L8;HuT_+`FS^#xSr6hu%_BxU`g?l!q!<`RGj{4c-c>&q`c9#8IW7$X9 z6)Ifu+Z^qAca0-7^V+rXtK)eAw{wXV%JLhXj^v2OOzeL!8uFu*z#M_;VV+^tu16qTzAP!pgmK`c@^la+d1(0^+aZp95-jc3T(S*;cXlv=xNQ7O}inZjUK+yhWNpcVTQKER=8DM1QE zRiY|U{YcncujXG#175CL6!kO+C;{l&A-(FLA%S(0nI!frJIp8mACQQjfmKCK!VJ?ftYil}`bsv_K32teL+sPyihU68 z4`#B1uzoO5kRPEd5Qq#UM-t!-6(uHjum(H&Ugz3)#MH+53h6U+l>^MYBlpL&WW0PV zWI~ZOn1D)U(t;HQQVX{qb#!pehepR_nhcCd!y_3ri~eK>3olup9V13iN+jeV$`Pik4M&4gE>DeB*7l4f^ANm~`S$gOIB zYgh)K9C&ct^bK9S|B=$64TK*Yd;fy|dIL1&)H~uzrEC=La((+@8bFp+B z>Ms_OW?CGX1kFj3NE&a;mM7NXNDNeIET5xfs4`SrCvVo!U@a{aJjhb#h%r^#9p4bK zw|#K3pjb1zDL8<&${7dX%ajZiG)sl9F+nV5(Ty>D=OFk&{`NRblTW5D6F)(qrgN`V1d7kMV?c#U=8s}D>QyBxu^gc#FTX`bDOs0msF%o>%@elH#Qd;kCG)@j=2eMcgz*;tTc(+c!5%*ej`j2^d4ZFZ?H4 zB}k?iY{G%KY=4w_3*xeUd?y!|`9$W@N%$*Zt@(!~0Ln3ymP>}l9r@Cc%MNVa zql**J?rBK6Q%MuE(4DyvG8pQfLFIfR2|K-IA|s_reTnKy1ioDTha?_lYb1(x%jvY_ zlv}@P7RKtxKdd$dl7B@pG;$==`*JYsJD%8Fi{^X zGTCwl3#LFFil{H6ap)|BWc5`_{)h?;uK5kzmn`=XVTykmHO-~tkCzg3g(^QFIO~x> zZwZ9nI?Pnr)`hxF3xUmxfnD=~T?>KTx81wB#NL96%q|-*HcwboKZ(~5(_>+ZwVOtR z3yz1Vdy+}N7o1tE1(Ub4D7x+1SYBGw?!T zgEKsiV9*EPQH-f)awLH>Y1d2J7hS`UsbeG=GB#!|eH5cWk^6e!0)WKJ>&h}##@7i^ zeUvm)LOM9i7;L{|IJB08N)uTyE~{)eBuk+Qj9V|fGD3)S18kcJu;L!0MAo97NMgmzB4munhle6uI#+7@bdPCA*oN_zav zQ+M1OmIC#YRS)i{M2qxW*@)z!Gi`A-W*oAOuX`Rl8100{1Xz|KzB9rEt-b(w4{l*z z7_lER>cX3!;8Ts9L`AlUnWs#{i`qqyNmvL6%M@*uI7wlCcppwu8B@GT-Buq%qB~wn zLjo+C(|&rDprlOC?xr$I&fus06B5$1S3}R<<8ZXh9?lEM=Ac<4%U3^8v{EfO{P}9( z*-rT5JPvuOt})N@=9YImu6NAEest!>nfKy1QuEDw*^9d#|B3?@^9?q~p1EdHxA(jU zHz%^ZyV}ukw|+z3fgCo|KyBVdcWxn6H@#_U)6B`K_PmEmyh2S~-bZ(S!5dtuqC43J z&Ax%)HP3b3r;IZI8e1Gc>v9=)D}RccQk5O5coo!Vsghw_VWA4}{W%j*<)Lspp>Vt4 z2Xw+CM~XZ=fr^JcOUxJO<}&b*Q;HeH0N0)zi`bUXIvk`S6`{g{l$P_7|RrZWXal)lkM zlz4I=327=us%R{iGQDkuo>4U=1x;5;fa#q`GrsjQgno*hpk~mp3LhqM#!~3iqb;PL zztq$HilLihOod7e6yO`~PeX{{5aFa`&<*{m6nc?s)5HdB!o*xnEHIsC7~@I8MuGuA z&w{kUIlD$0Eqmm%#=4=AQf-YIBRz$onK&^UL0|j&TBA{J#E3qjMHor6_K_u|ukQ)1 zug@Hlsvt6jG(x6x5}r8qKxi>~|I9Pb$S{LIlYa>LwY9cqhez63V_f8Eh4yVVYG~6; zl? zSUWLHuy*lc5F4#!sWp~4GE;}65AZCSyoD&bo;{y)PVoT`X2dsDg~7Hri+*4R+fxGY>0c`1i1FO69X@mRLA zZ5S;C_>)B*n}TN({ul$g=CT3zCS1gg}>&k%OaiU0MoNx}w57sF9-n1_lRWk8M z9$)Q5mcn}2HMGIJE98LRQg|}&ZW=2<-B$E9QDWKk=&v7*SLTl{ql}_){eQd^t(Xbv zqyYcAW#xw_Jq(4zF+?7gvMXzq4Ux=Ob}_7rZwRjf%6&QsWAl8jFyY6h`Bh!{vK5rilDU(BT`Y>rv*%A{Z27tN&!cogh?yz?P@ zV5IVP5ZRZ?ApS^uCQ<}s5o0sljLWs_@;0$%$BNw^s?H1cs%oyj+YqMc#0HZ~CdR9c zZG0=+n72Yz_5r}SFRMg)GF%r7*XeGOJV=t#NvWa-bXT`!G?kPx-31c`id47cJ*RS%Y04CLe0iW zCu}bM>MOf1?S3oq?Pr%lt0s>x2O8d1XZG9)wEV)~c=`CtpZ>w#*{!#0 zw@td1>l>$Eo_cxu^wjCujdQIF^*biL6m!wA3`j>V9eJzwhjs6+y}tI2KazL*DitrU zldlb49h@CsShr*H#NFWf#o)&I;Ksk&@T2gJ@XgI12X`$uu9=>gnwUMY*s^!NW$&HF zeaoT7>3viCW&?}z?s<9lLTJxVyMA`;gJU0uj{IwI&D&M58n1cmTHDpO*^Y(Pk;%Ya z|C&YrhI#*nANIeSyq^5Q*^m9(%V69I?OBHL2rk^26N_ti&ad6M5P0&Z($D-K_&*MG z{VN-NVAXB+sxR(u7lMrxIMT2b2woYzH2TgH*S1{U@^N6}Qn3EFb|KjMI|`<3_}%@c zM^wCDsQ9Hufes(;Z~2-m+}dz(+mU+VA7#&xTKhkS*Bz;{e^lkb{YUklZm0dDb?drC z`#*^e+%r=`WwX|w0v>nm|w!8a5YY5?jiH!e%o3FNpT(ChXqWbKbKrtwN{EH2thBg>Dv^m5KlT;hk}<68ny|j5knF#bZW>y^w{eDGQW_8u zbK$>W_Xw9HgG?)E5|=DV{6R7W;hTmcVTgQ8W!ELCk~V=}8Cnr1^ira|yqU*6VgXno z;*j+`bY2Hb#%Mtl-Y6pb5~bkiBJlhfpG$hI|C7AYu*fI zCQeIdI)=%4OcIa!ACSNV%a$f};UYIVSMfSg?uQ)T_plXO;z=xsaV1~3(88q#zJPje zb5zwY2WzK2Q=XZ}uWh`#@sr@=Uo3}KVL4BunNC#QWmt8J zFySb;rFrRJ01U?ttqNjX|BiDmGFm^JbCuwwkr43Ds80wW*VSU6bw1EK=UfQ1PfE-F zxcgtu2m&yIi-nyQpMOZKv1%_f^5pZT7!kUxT#7$853Bb-)tE zv*Q?`Ff3jW5u92uM_9CtMvbdz#aR2D`3|Omis9epiosi=ud*v)FP2Xz{Jcx}`c6S0 z=0}E^BAJOy|7F)uO<4gREBB({3p4v83YT|Dd_T7sq`8VOA2fIFu+*axPsDn?$}(Nt z6!vnOrvlwIkj7Ds_@M3_NT#6i>8=#Qg20uEWU7Lk#g@LYNwd!#_zDM%$XQ$Jrd3a( zX#BBFTNKcT@@-oNM_}75|GMw2A4_sZl1*cfH$lz306n3yu3f2|jbrA*@>W#eJtx zx8^s3NLB0dcH~AVcGb3ng6)>zIp}xX@`*@E^R0Qntjiflbwxjr#16C;C(*0)v5;7`6 zcK?{@bJTOE4Rxwy^YNg7u9YDqmjIZdK9lwHOrdn^Xju@8uWm>@lnBAL4@L6FYv8D0l+uF&x+Bbsq5M%%|!8}wM-H<-yO~`_7TL?;3!bLS?QU+C>s^~as;tjneI=0*euOB@#oi^cgzxg-C>=aia5t_@YtuEAbfS5>ZeLlr=Yozr&izeirpC z!wDZF2NX4#?(e4#!Pp}$2rCDQ@P!A){n@h5PONL+~d>H0nb>r4KArIGK+5iqb;&=%Ju7I zv6?5jzq14p#qoaR|6(Be7*0&*BmyBAT4#v+&EJI1~op6lx)o8w0gm)F$B<(;UTg6F{!Aus(uePy`qe zBhI+fXlYR-60i;TDq=gTB}YndgvreohL4oFkGb!?gt{#p6+28hrKdAn zxjUJ{e$B(TM*Em|BOsU|1nX@_WVbnC2N;gbUeNe)=9ce7CWn<_B+jtVNi~zhD1i*~ z>poUliJDcTylNlCG(vsBqBs4yPR@4t+3r8bHp~v9>kX9wl!R)L>}bbtWgimq^1_3Q zJAOU#w5)`h^d-AY@2;f2i)Yp9gF1)Du%SU!c*V}Y6GavKcGn*_|LnlQl9*pJI{!S0 zm5&23RHtg8@iDk@eM=2%Sw`O6%l@T}`zEDNj1XXE_vHR)NKgn z>_ur(DYz0f>Fcr!2F?m9$vA4=M2G2u`XCOOvKB95X~EiJ81TI2O9=e<+a#4$6ODPI z3PwDx(7X5ykmA9ofnc$NK)T0LbNRFwZuX;8VH1*4H#;-KwLD}hN~~~i(tNxE0Hn)1 zJrS7V=%D5Fvs2H`KKbt6>wDj8_{r)YuSSg0LTKM)7vhVmLR`I_lRoip{o=ky2(ID= zax&sYJ`P1-8NX*2>e`uM{7a2S^Tv(?PT@mm!-4ho57&uEODt}r7P8sghR!g18w$!V zV856GjMp?nY-TLgvhba0H6nEnvru7vzuAWJ3d&|>iyWOeuLQ*mW~BN5!{C)##IlxT zZc$DJwX`zjxQpne6DVLzgi})kJrXWB;S^hO8F`W6s!Tn60Y&2vBcBpe$ajf+Nb!Ub zx4QPq*-K|<4qrQZ_2_){M#LzR1tUBk3@-#XPdf6Fi@Yez?Q%QNx)iLN_D%ViX~aJJ z61UTT5`6k@Y56C?&0j1BnjT4EjcEVo&I9{|57)1ybYH{4di$+95h((rgFGCl-P~x} zdrpO`Dr${nBxVQmSfrpzj(A<_&ty{k++H)irj^Cj#xjlZFX;s(&k;&exFL;k6Ewze zh(cp{skwEjb@M%+*RlU@5OI9S>Fje|-bHtA7;vUnPpzKmoLZmvP>EM~{D~E+oo{kE zBBTx?BXtm2zSiexpdw^*+541n-H@6O%RCfvg8Flv5?DM0ZdBM#cVkHKmrcerZgq2J zp&X>o@B@kDFC8RxiI$^oOJ>+1OWlDwFeK0#)2mLs`uw42=aEC5&vo~FO|RjfMu57x(&Nq3$+9_5GK3l)l4=M2NH>S>Rud6H#S|}L8PSVe&ZQ`T>;xHI}FTF-Aypg zP{MFqif`S$kN<6zXVkw#72sUZeuV^v1X09kNKsk|!nW|KP|f~(J{559`&96LDg-_i zYJVv-{ZeT7rLg+0UHaCuZ#?^{wBf%?ZTBUIqj6@(wY^vO-bYktV?GG?!9_17!{J?W z)?OU=R_dFnw>oBCTW~&p&n`MP+_efj7wcN)>sn@Cn6GP{+c96a^}W#I_5<_V5B&V` z`R!fvp{}3D7Mw@!Ic$z@F>e<{&*#-oiRBgD*f8_;-wKqoY5w2yz@q#B literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/jinja2/__pycache__/compiler.cpython-312.pyc b/backend/venv/Lib/site-packages/jinja2/__pycache__/compiler.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..19546e61d061aad02407e5aaf9dd2c7a34bd6d2c GIT binary patch literal 103905 zcmdSC33y!BbtYIVP(T$>g?$GKJBkE~8^C=hz(piMkpQ(oq#+QmKmx?3R|S$N0TLxE zFAK_8#_$+HTRnbEFBgjy|eUN2a-CHSlHU1JYegvv2ap<%0OyIDhns~ z+XoySX)J8(Pakl0I9WIaVONI>;Z(uipD~cxk;%f2{;YxQj%*fA>(3d;?Z{=}bcFLd z@>tl3aDGQV3%d|5=qO;}41^0i3RyU_KXag{qlksG`ilojI!ahLyT5dxtfP#Da}aiS zxLG*2zkHygqrzzLnfmt2O`-mZsjLmEI;v6Ly#AVj+KyVI!9>u{s!(!B$jAE=@{{^2 z6ySZk`YeZfOa%yjRQREZzv);l6bZ#biBKw(32vcWs1PdOwRO}BRle0iwQqHgMW}hp z($OH)`n-77&#TUt+4mJW2lZF*oHYw3o+Hv(g>=?FHJvl+_i`v9oz+NZeTsqp3Hyb5 zm;1$-Oyyw(+a>(bUHW1dX7`twnSW{o0oR0d-(p&G_C~UwVwbHV=_PB(` zx2zqTgeE}g^bfw?h_>2@I&Ky=0Y+4Fkwd6)Kn|=G56wKSj@|6-F1+3Ct5DwVVQ=@~ z?Ox5>z3lBiylwXFQ(&9f+ZMd7)4;Zjnmh-BYxfNe4EOf?{O-Xa0rwtpXuusf=W`Et ziGH8x?i~yaxt|>koEsW+cLT!vGb&cA#~4fR9vTezE(Hd<2D{GsM0ztaEOZ5YofpNf z;bHd1))o+Z2hSclhFEL&xvt(p1X6na=Y69WheQDnNj`sf*RYR5N4v!HBf~#4B7Fj9 z#Dbt!L8w6q;N@?1+CoXTbl9K-g2RpO=+P8zU!#Qpi-2HO$9SKFtmF^qSFi|H zAt```gI|3~a!CCZl2?xJNu4nC7zNu~j&WlkMgDHgIBAfFd7HtL(i*e)ef>SLw0&r@ z1HM6@*o8)mS*Xur)*i8I06+WLPty5|UE*24SdFy0r8&Wpwc=iczekI>eam>=FlNv} zBZfEH#!PyZ?Nh4BQe!v&4*fLxl2sTvG-lLKSFYx`Wy~^WJip0c5HpdgUJ8~mlMLO4 z)o9W>W}sAi%)N#&^ZUl%GPW6R8(Te=Sjvz*_+mC6hGl1W;8M(XVF9`jrTnMXuU)_X{HbGuzGkua zg6~wb&woBJG<@pBv9@QAoVw`qoo_lN4*7@sn@*kS>OSuq6i!|64PH2Pr1#7zWbA7g z##`V3|Ea#-!M?8bYq~j35xv8sJpZ1N!R}z0Tno$?f55xFf2g~w-@nsK1tb73m56<(t2-xmhV0d|zK;iQ4@SK$cfBo(c}3S>yY^Z%Z*@3t^=$K8^{3uXybF1I zCJsJu=1n)=b(RrC@LF)DZnkA1Z+*zM{wGe?RQ6P0`efMIFw=uu$ky-(xfncF(T<;( zrRCDF7&8W9<~@U>A`J_Vi8Yqkgs`6`%FAxCkwDYpsvvH~y9RHlbA;h(0YUd@@z`3EatALkn!h0}F2dlu|9Axn+8 zkuoz44U2UMh^ujno82_8*zE2=fM&Nkucdje%x=A5E?5G}%*Kp2^w`*(O?u1mA=0C3 z+&G58=SgnmLyDC`9ap+jF$tcg$E9Gve;? zB**NU4`M0)u0i3<&?TP`%LMh|6T5xG0iVFr@W-qdMW7sUJz5sap|2+pvx>cE&joH< z64Bo_fcR+;5w_#=H<@9|Au(9oInZ_9$J10Xkrca=KKvuxXi6s;(lVls;;^GQ>ZrNv zsF__qmmOWVC%kS?bX|KG|5vv^0IGUs@|jSRS0x5(d41+I@?8=a|+ zIO>!)5l68SX2`1Pp2H)hGUdN=OpQ$VbUI^t{dCoI*VJglQLaJ}zH5pg37g|;>SXHF zhPRyzg?KCsMR7Ejytj9dFdaiDw@o57k9dfxs>N`2O~Z&s5W9mQw&RAzxNpsTXiB%{ zPYpdZ;OC>0AD_N`ng#!~iT!-m{+J>jnGH!<4DzAd;K;h%%1ZP94-|Iri=(h-z90%) zzsyAXHKMS=waesTo-_y1nd+1U+^-W!TGW(*46LoeGR@rP$Y3N67l<_5#9egTgBz%r zy%gSuTP#C6|LHTo*g}ys`8l0)5TW=v&W3cbh!11>X36wEN#Bg&_O$8U7GBpDUfrfl z@6Gd>^GWk(LV0^4j=k#aV{`PLqfVK?(Yn#mW#!}ixhkcCajb#%H-g#DLm^!=r!H4qc z(2i2ZY-fD|@CPG4k4@8~G*HAgx)G2_<6nFZw^)jjlAn4F>m)`Z6VvX2d<*1Yi-!IcF~qK)jqv>=DFF9 z`GQAgQ%2I|Ls(0#>0dkc#<8j9h^62`a@ytB7M=M~XIa=;7IoHzoplS&RUzA|2X?-E zfw7^w#H}03=xWEfBA)LJ7seIJ#jg>A-=-aBBL>kpY77vs$S!pRs3dTJ(qvaaAq)e` zxCo>xu`VT)DTmG_gCt!phin-tkgJ69l~AD^I%h!|nSm1dSunkYdNnI!PM!g62Hkp; z%HN@`ZcQp?N~Nz{j#Yo9(f+O;pIh_|i#|Uj z8sI#K26wf`^$pQl8}Rpt@bh7Vk@e4M%qEBeR4ky(=-)A3HyRCBGAxEs!ylM08bx9N zZyRH2=eqozlv^j|<}t-g-nB8~1%?aV5+jzfokl09nVmtDPXn%Edj;Y*k*uG3;BN_2 zhB7zYJ~?ar=8l<+XjbLzlfPoi$D28MM*X_b5T8yW# z3{qXoNkI9D_m?Wz_QTWPZ=XMYhgEVR ztMYEv=8w|mx)$m-FJx{0;c2PH)wRa`o{U&}>rmhj1Z+N%Q-S8Twept)9?cwv9>H!fiB&veDOT_f< z?)I?<$R~YRRYafQb-UYv0=RI|%`kB)Ef2kZcb6L->K^KGqf1$O>Q`>oM5-9s?|Ws$ zheeH`r6`htdRbBsZRMO)GHgYmB=IR{@9ff3%Oy}7scIfzYiMy7U!@yyFl?=p$v_E1 zID2{rg--P&@iG8^3xEFSale0!g(^dBz zWj{9?atcWhl@+y@gzY6EOUW-ETMdr9Ul@$mv_+d^(VnTqJhbB76F-p-Z|AQ!d^crJ zius2&BknYum5YW8U5{w$U&pH2VZ;_4w&r~1K4lqV5bWl&>Jcb-t1LWgd*TV^dYJAWdH-c$2vk|-<0j#LTF#}CYehKuX;BNM$jDGf{ zjO9_oZBy%hbd3jJ#+=fC@^=#d?-MmIxI8!JQXnpLi6r3#OG-G5_a$W_<9b^sqc=M{ zgBfyNyz;Bx1Dv1MxXXsc?EDGKm6XM@stHTPR;>KGt0ye?Y$co_PKhBk8i$>ovDD7a zfgxd}pTdsL&R0gd`gx4F841R$CkL^_NfV!C981}U%It;Q^1Mhm_qKuKhDL4gy_7>!U7HiG)@te=zcz)*O2QS@v3G&J{pR5U0?+KUeeP}@B9T4UC;ptEkaifKh zDqW8zaMO;K4l~=Ta|mW1`dWXK2nM!&Wz~=MC9~KhY$n=-WNe?=gfvL)EgdOBx{%^a z6_Owqv6&VBMs!QlSvSQH3x_K1;0YpVt2%ctqV}U1B^CcbnuAZ+bXU_ z;bTeIPoj+wYrpS;ub)fv<;g%*q%a$W&tbGBjzUoQno&4rx?HQFgv=i)m=;jVcogUx zB?kc*xKp75*^`1@2ajn|)5W@Dl!r9#wRr$X>r7g0zJO3@N~$Kmv}FN=LTk$L#4B|w zn zFm|u#>l_*h437jlyJ_8sC7l`R0po`qEE@eW8@2~nN5)dbp`ic|ruGjF4R`X*8#{xO z9#Z{7JpmpDeqfWF#stru$`g;e+1v`Iv+W;cqR$f8@8brMoWoF1j;Wpoej={~0s8}c z#>CG1MHRC-k)kyd%~y^9YkRyC%@Id6fa}-d)nNdyM%>%afK@K8oZ0xn&RaX@0l$mj z7wf#yx_#lgee9dXLif#v8x8c;VnNx>;v2;XK7#}bN?Eq4hQcxg(veG%8v*Ac{X}f} z4^!C-N%|H?Ptv$#g_4t&g_uc<;{Ze&3&B)ANC@sP@$BD++hxN~ z)3UC9W%4W2&BUNCq^+JXE!tAA+9&N%TVdE%INf-2$Bi8kn`ben;QFa+r=mGE;hdU< zoVp3qmDELN#zYE3$1z*4pLW=MLfmpmNQ8AH(GrBHM6ZSwFzD@ZfDKa+5k8VGy^ax# zB%J$5vn}}av}MGE{Tg#H_XOJuc6SW|7lVBVA%?}yD^e$m-@*+Okk%$X{i&51LcoR> zo0e>rY1dvWOC@OM?aUtj3Lp75;&$2a6MNSEto-ThnI5zx!fu;2azEti1uIq;e5ob+h>)U}n_2&x~M) zKTu2h76Hr{1%2`&qT@#0$Px+_-c%)x_H!V*@qcKrf7CrfG&__sdS#{!M12Fw3YH4f z4aE7NfO$A5^b&{O)vqK%+%jlWh;ve&Z!fv%F%=A;)4q{iLZ=$zy75#Sp8;7s2F!&)bH*|J&d` z)5WjjmG}+1UBQizgD}+H*(s8Mg_B`6QoNvwh=cTw=q_I10Sf(dx_yKj;SfRt_?A>2 zG=v!&?sOxJ;ip92GW^)G7Pz{0^B`C19}+OWOih1eN9a+H(Q3{7dAh~AYFZ$AZq@9?NA&Z^VaHZUp~02? z#z8*dk*#vc!}}2ll;X)ck}is`;dO9V%O%?QLe+VXpBZK2>t$Vj>17%a{@$}_CX6XR zR%dVPZA(JyivI%XCbkac#WMUQ0)9enZvpWh;_XL~-S|^38I3)93$Nl!E~GG~11co? z1gFH9B!Q4jW-wIwgiC@+W@IR(qe#$HKnaFORXZ4*)L34#Zx|{GU@}MdgXQyy64w~? z?r}>SdT6;W62O8J>BbC!R2w^pY@!5wenfz(_j}p!Y}Ln1yOF<^xtFmKNHMuHHDVu4 ztb&&e1Zu=_ zzr5-@ITMz*Q+X$P5F59G5w4}bN5i-+hi}IeqM8v2Nhku3j)^-qehP@nBNAR!>1ctDY2*$qd@E* zL&r-x)Xs~{nCW2U%4KFib`<&%b;Q-*@j)a0fF3MV zfANngXl2QYcMwiQir=Gmbo+1k^B=>FmW<7hEGBF1Lz~H3HIwr}@vY*A1_bA-9?=iI zu9zOV8N3ms*A=q@y{>p@Gg@nBtRL8K*&jk`R6A#ROh0^PQV#m)^-aVipjVU6qQ^@5 zk{BOv7A)Y_tqi#)`D}f(ekNQ3hauz&?jA6?2>^JMUHw-@!$B5)PGeOVOFvwR)t%EU8?Beh72^RcD6 z3$}v5b7(G7PXK}EJGaEM1Kxd`klBpj*FxIeH@q zST`8_=a3-QA-nVH=E==d7w+0iW~x5$-15u@J`UavhAXy^vcR#)V^K$0*iklP`5@(1 zO2n}WTNzhhpL`v#t8T5j>#V<@TmH^K2$ZSW;A#M|nwCL|M^Q&<*ikwixH)=b6pBQj z4`b&gVC<(LY=$R;GRfLk{8)Jl*7;=I=ioyRZp58M2++?=e9;TYC_0wH9`)>5jX5E0E5*|5< zu77At0-Y|QXaosGxPF4##UQomxX^T zDt;GLO>Frvy`x(-wLFO>-!lAyTAr_I6cg8AvNFY^4wrUKJBckWCd2+Z5%iE@FSGw4 z$*@<7O+%rTcOz+k|4IoF|l^Tx%2a zhc?La<&s+@Nhn2G3WPG0gSU_y&xI)4RrcD2(SxZqW zTXpM5J7NhJYQ8h!6&~?+_tLjLX4X^GB2~-uuepyXlZ4A>1$1-5OFZ%&KBf0@_eTx-qe?S&YVlkxjo&(D{Cbc_jW8vwLO-sizQpKH66*1`mUf=lvqfmYw{@&P z^jnhnmV^s!)}HVRkJ2tC8%1b^=axeF(tY)k0bG*cMZOI%N~>4uktD3eJ1@$jJ4U7Q zt^>>({tfD55!T~*EoSKk{H{~dvcRwmhH-e`gx?LqMyfBH?VIr2sCnLu=O)0Bxz|Ps zLu^HOlN8>D@McYZ+wr`Ge-Er<5q98tE56@}-))-wcj0-vG)lAjNI0Bu0ahP3rYqwl zN!X3v+R0jk2%CgU$t_9PgWPsAIATB&E)CpX!0lylznK7pM-ALQz%>JIx%owmTf&82 zBS~Pwr5zOv?=>Uk1FQr(X=qB&0=R<=PA63j+f+VO?nDy5qvpBHS_pTyUvSu2omAmL)I`ke21HiK=#^MLJqIxI$~ zO?UyYFMm$h7XjPFVE;6s0C?2&YzN@F8QfXcLs1GgZqyw z!gT`?35GaIvzDN))0^2)<=iIHv1T`|Dt1O^sef``?ft8xs=8qXu#e zkl&UdNotUAX&}b|`JM#1T$wq~^co;&DQ~WOM=u})6^Ef49M?DkOx;x z^9?}$z65z>MaVY+`GExa?23?I1>|iBa%DQ=EkJ%KLB6nJn!f?aKae0#tqA#>fc#j3 ze0fF4uL1HC2~t=QasrV5Qi43UBIG0>|5xlmTw}Jft=xKuY*@HpuZ=>~CaT#3+c$_a zSurD?{vQ1{WEv2sS}v!mdKdE8hCz3nG9*(M0bdRe6^aovj+V#BwB^i%upBgK7Z#f)9c<1WKijr9+8g zNDOp#_4jr`LU=4CWwmnjIFd9e>_!t0C2FWxyGNFl=Q-W=b z{fk94Oe;=S%*`iVxwOUHV*J<_t5;EE#bRL<9-WJ88}XC=6MOdklA4)U7fLoj<*pSH z?sXdotO!~d6uM%^t1_l+R|GYTidu>+#k*qY0g?h1w5TT|`a_p)Nvv$%duI93KStyJ~ zfFB15my{yFcGu}`!X+3+jBV0hxKU)|aULMr{ePl*gL&~yE_)vkE>N4(oP>DvL)BWtQTn(YZ^ zdqP>OLeAA8+iEVdC%Q0hcaeINwF}je4Pos7$2+>@Wl^h)hgMORISxg4{XIE2B{06H z*hfJ%gzPFewG7gZ5R~L-f0#50$eNP0N%{7$v|Ef_;Nc-yBtan#&S3<~cuT)|RTJ6eJXgqF#o~232rIQNr-&{xC-{x9%T-Z-pPIVHBpfwJR=<=( zPffwPZ26MDNcl#SmuYQ>}BwLfQDAurv@Abifcj3#?*!8%Eal_mfmmZaGU z$^=Sml9n}_7v5kQb{HiZ$18gX@^*~`uzN_uaBDC}%Cs-9f3-zJCPP6h~BhAZ(pF=ORY|)ubi(k}PbJtn3=*qsHel0yzwmah5Ll5?A z_HU-iZ_78%jeI)x$=KZBoxP#50}lhzPRB}ohs$;)Gg0gna6NKY% z_dno8FeiT0NW<}e(JOp=*j6qVo@>--QM0n|-SZ z`=SS>pC&`H3Ez7x!Ri-#ef`iF7u{?X<9_(mg^vW6EoSjk(GKTSPp+;eQ>qnl`A`BDbSZoFBpq2C~vX}S$9%Q&f-F>K7ibuG|$ zr-q?w5XB(tM6en_zXHSQWle2f#<<#ptmSrUL0J5I+_Zx$mV%~~8YY1TS0es^nxz;Y zYMP}|_W9v|`xta|994X(82#NezT`_8YyEgb6I{>WfxKGCrX6hI)@cq^i*3239pe(k zq>CC1ikgjW%x(Zy4B&gap{GX#mZo{!tEB z5!s%TS!e2#SeKC8b+V(@ZQVGc$=GZ-4Y37mvvmg@L_3<0(Mc^77y17DfgJ zFrr_^g1>gFo6r7MVEUI|CPTQEPqGu4T~M*{GF1Mew?giDV$B^esAL5WuobhJ9P80)CBXSvL`oSjrk0I1Z&^r7dx8Six{ zQ$6=I`YGV8PMLZ%D1pi76pnyN2+^MW!q-X(<#z^M`kmx{eTuwLg^h0`P`(<&^3R{T z7RiCaNeb3HPf|5ZA82wD!UrQb#8v>T{;*i3*Kk$jjTuv0_XjOBg_!UV+RXm}WfT7| zy0z1dq5c?!?$hlraf>DKWt5RiGU)-o*m0`^`!JXlKLyw-`ey`5+WNF6IIr&d`mV*S zyl7U{-K;8!u#CFO!>;m~s@d$1%Wjv2D>g@5TM!j>x$nB%GtD0yyLBw=+HlY1W*>UO zS>V>2AVIr+?Aozt_Ns99s@djf{oZi>-aF0F=Js%Ndua8^NcMA!4eQ`lCwtW*%-v!4 zT0-;g@Z{mBqa^GoneLehL~A#P@xOF)#Ia?uv<%|4V}wqbRb)XJ#9jG4TQOg*tdMbv zUHVJbGpO9JYsq2@QaKbR;U19dKa!IO-$i2CnRO0pQ>;FwShDn*HNA|js9zW*CpxIz zX|%H5ZbX0~xJ3CGOOH}tAovp2Pi(; z1W=f0Ymfi~Lr^@G8X0Sp4`cy%ZUrwp0ZtM~yaaqom zP?~=I_Um`uI~S`x5ekXm+sC+{xWe#0_dfj;uHT z5WS%7O~Lqq80G4my(AHWw8$O1ewhICMA! z@F>{SdbGCErHb zQ7rKyEE7;<|0uRLFDZ$@Bm_$mOe9DG(v7l8zNq4|)MN!_mOx?0e-{4B2bFZdZArP3 zdkM9kaYnu*kS6H{bIGK5dc%H!)@z-*8tARqsxLths}jTUp|sLVp5Huip5Ng3Dx=rm z$qUyhH3_$Ow{&Aun3=?Y{1i|wu@^V3aDsbgVh?pEKz4kch5#Cm!;id)Pkj1G2E1k?Z!l1?tbu{UsAj(Bh&)C-(sT}7b` zM8#YTt`i4hobM9JIU4d3&&I6mwWxgUr$vX&F}g8|3cj+*=AXJfk6Uwr3J_b_B_xb@FBX*CEPA(S%BryV5xkVx{id1fd#*YF7gl2@-BlcN z)-G0fqZN(eipC#RY`pf&)V}E);&Yz4_RLJ?%)XhXS>tT=Y+k5r-M#Gfkfl{_B93au z*LTPwwh@WTfdL$hmB+7*&-fya`oFRlNk(%aCzHsNtYJH{ejpWOQ^Zxdq@=!^y*GNN zPtR6_iW(v=uTton+iq-|wQAlpf-`%VOqD>5SFS|mOx~<%wrRF@E;CftcrP1X|EUt( zqEAyeRv=j@a&y;>U9&9_*Lt}K8@}a~OHM%;{B=%thSC&Y;uj*0Qn^I}*I&Q(`mFVy z!;5xK*Rca6DFY*Te}u`bC3t00Z5+E>AlD%G|GbV0v2f8GOSs_FO6M(fqe;Z3!`uK~ z=Pi7bnR`slhAHD|=sKK2$;U0@*6}3Gxgv`1d6fFUAs&u@$1E3&A_?ksh#ZzEup$h{ZlmMPfgfi{W3Y)$C3nxkXA_TkkWLhr zKpZ&?K~*w_XGUZhCC1$uF!=~MGhjY?{a#sy%sloY6_PIx(#s)HDbGH51tS0A?2~$y z81wF?UR0f)uFAx-x=^7|@m-Rj=pU8}^?s>I92eGmmu zI93i6f_xIi<{MU(&P_b|^N2qZ0bZYX{^d`1Q9SS)%N-NW%EAM*R zHSDzKJxsQwr9ZYNuSyL&swehOwM=h)>@pOTO^^Iu8btqDdD9odS=Eb`wb9D$;mYj` zl{=^QPd8p8e|;G_w0S>$A>v{i`P#kvnVQ+`TlF)gv#-ww=lee^|E&45&7rpTP}#|d z>p5B|wY&Hr7^LM>o5b|%5!V_5MIJNRGd;8IxB6$kGPgBUwlm_|MG;!)#oVU3zB^fW zD&~elP5T#fA&{DWVdh2bP2{Y7Y&K_P^71O#BJi#BUw8}!H9yZl-MQRQ;sem925dt~ z3-9;P*4Lq6OABoui;BPLZCB{&RLRQ(mc2 z04b7q#raCU93bMKU8it0G;{~g!aL3HAP=}b1(2U{2_mhaBGr^D z)VScYA8NYrHF&|t&cPC?6-8R{$eXw!mem^Pp_}2Ln57R2aPpB~#7n?+A{0M*pu>z! zeI$vU3|5+$l_>|S2Y*Sd1J2yRI>fzlCT{*~q7D*bn^fW;3s5CVw_- zwmsUgH{7syp`kfc-*V^posm1epS=<)JATh~0$;ql^KOPG{)3aV2Z)4rHL(O6?q)PB zx^fBSO!wS#RsS^C6I#{0klPY+wLHu*)a^6=JQsS%^3J1=`GUw@C|w&WSvOZ0D%yU} zv4b|}Gr4>?gBD_$75Br3oKJs4`MYQY?0lH~Coz4^pMUyF^t1&+QrbR9xW=@?FF5`l zGqYivoB)PL3|m4Y370wu8sUXyddDC16l)CP@_5jG0`!L1e;$Ep@_AUsH;6jW} ziHN1D;kXV&4LH-Y5rO5liuLfW2prvp4wn_RP0Y}M+=4>=9{I|<9lNNZc2h$UZ>2Po zqx;;@kl)8)g9+LX+PIggp}6ugHZh{5-f*cmTDs|O>86QSL$(9+9k?xBQYbIR%hk)( zqKYP58k7yMnS^kmo@{Ex;h7i=MsXkgNV>6P44{=VLD`xP?Mqa)#yi@Gmp0E9GjpSv zmEp|Fh0N+uM$L>c+c;Yja;^*6*6|Wk3FS-SKK~Y@n`V-p+KXIbERg!gHtNkG#ZCr? zFDNrd-8UXL3&wGa$~7u^STU26RF^}T(>nX@A4=_tdF&xJ+Zo*zD1V zFvG=C(U`SQhojN|Le3w2Qj+d+sNYV?vM4t{mN?xK$?40#IFe(;VhAWpBw8h3O+yZ0 zvBfZ;Ydi(yKniNrF=lzA7791UzCs?Oy<>5w{Z@9Z+|EIa6XKnXhQU=|sK(etOT5%G z`_$TDlgZqvkQG8QD|-`ut&kh6`zPn9@aG9RX3J$0Y*LQ4UsI0C##2I$$_Nlr#!Ra1 z)t8%BAf?vGHBf)?cAfephlEtQBv_N|f}?MP9Hai?uqJ6<0VeG|Y>mp}iOB<+R7g1_ z&srA0Nq(#TsstQ^*rLYBp#+F+@_Y4H3-JZ;!Vfff;ny@9$5ZuN9P*P?w3t&%IsyXT%%n}q&LoLjAl2!DTQeL^Li#6cuac<|dRuX(Hg+y?(zc23wIoX?gn-~W z0HncQigZq6@Z9r|lev)^4y1#4jHQO1MQw82Ihr3-eJ`9NSMZc8l+8o;06eYH&f(Ai zX-+bYYk40LvJO=A7FGP*mM4`z^Y zW>7m4>M9sB<^$*D4i>n{H#j+9gUa#+Sb7N+^-P?!gDWT-ne_xz_lX?$RC8a~jGJ`e z$o2lwppT#H{3eRPy$VBX8Jn*-OWP-wQbQ3<#~m8l@fb717*xEBcXX(efTNkE+WBK< z9P<}TCChBb~lEtDy76U?xH>!EL> zoC}9X{NS<3N|jO|OI12TkbIHzqkeJ*aQM3h0M0()8;?oHVgtr^pC4=7j(A{@(6hoM^!YS1ikazIV7&8W=o%KWjD|b|qXAD=6vL zDWzwr2FY?;5rqgEU%B{3Tq@6qnl({3R*mTa=JUS*l9;JE!*m2Pr+3mOtc$j^t7((a zdai(}-b`b}R(C(Uc)IHTy zi{^X6`JUOzkLzyNE#z;w=V*LrHxx8HPB-LM&$NH=;;k1$YmY7DJUfy4z@9Y~4BN{e zro-?C`&SQ5wv1fbu{(P0=**h$?VGp!Ny_(A{$*>pV(&usK9~YSqK67jx7<8><7l*a zTex`J{K17{Y;NsetgD|mgu^)&r6gz0g*F}v*BnYH*`{#*rg_^!K09tx`6PQfHEge# z84Ybd9IidA_esh^K0AQd(?Ge@V85|u^@Np-jh8gEq)|Ryb<=ahGjm{}us&4KFnb&t zW}~-9=d(Y2J>=cR4)nd#9I+je6eh2v(LtWjoSbTbVK83G`sxu|8MC{r4clt5ZD{k} zU)oujdDk1RHE^zJX5R+~Zyj97Y~UNLWKYpHlQmczrR z;+|*CA9Zu<)(;26b=$**JEoG+CtQ9yQ#q3}(>?ua#KmMT%#-~LntT-ZfFmDzL(a00t?ZYNeMUom#V-s=e5f3{cIctWRIm5Ys<{TV0S%O(!>#q@+?5ucTs%S?KIZzJTUqBxofgy81V~oG84G{>>i|-X{SM z*HI}s7;Zc;`^vk*%(@RY-r9JxACHpGOTJ^k5>fNNp zQWrFP5Gt+54jJ=sp=bR`TT*OQW(y-x2C-yFh`R#NGit+=Nc6F0L8tW{qC&Qo(nOKg zQizp1*#VENh>21`X{kjEB&wn)P4j(fhu=ry(2mEt0b~#^IXHLd)7DQ~qm2jdHXc|g zIk=F0a3bZtGk0qA`fJx-o4GI>Sa8At!+m@D#3(oQtOz?R7VMQXuiUjm3nFJa3rDk0 zFw_hyp~dvN+3Z={oO$lh+&18gU9Lq}LDc05yF4Lh{p{Y^(de2(;WdXs-Xn-TYK)5x z)j#vlYDzm|{0FloMQ0a>@B_mUUqRqH?UU&4;gA;qh_7@t!r#akGm)THKla;gT7`zT|`mJj!u8*cdxltT!x7 zENX3C0l}x&lWmvMVLMO1O)VgfHXKpVN!K! z15lA%HNFQA!42`dwXpOW?u0*@u725@iwhStSo1Mort;v8|ow zFT{_a%%ugznb&c?VwOVu1(mxQ<;K2JR^Ih3*S0`0tt9nwo7K`CQom?`)oVK%(n=Y0LcQ0-s| z`RE8oI2CtyxupZZH5w#=b5Kw`3oqhWxv}Ya1_uClpHuZQf>qK!CU{a8QsC&tC@1@GHO()3C_ScLgg6zI_LC#LvP(7kKeF<47`q zXB=vR0emctnFL{eQ8W94Me)NnE^>iJ>;ZH;xVKag%;W6VTKiPOM+)Q8)$J5>acaA6&yZxgPSu%S%;aI4_1;~16C zf<>opht9adY`ghhGLB3VhoA@r?IWgOEqP;MhIg=VB@~q^GsLhZmVD2K<*1V7*(o*c65Df;IFMjn{7770e)52ZWi_(FuuNxsTuIng z617!@ZB;mQ_VlgO(dw3Pb<0BafqORTFfuI;!smR@ZARdW3_5vXl?=;QKRYzc`$o1c zP?}al<}(CD7JaN`VrGbTmN=z&f$CqIQ2*sbKtH4E)7}cG6Xx=WRlXd)9^^Bf*dBHq z1wu23&9jabsw|cPStCC25||@TJ?8}Kh9jDUTi9JDcPoTS)wYlo2&L08)d*0|vP_Hy zAeVrtxRsp&NC)D$Np8jFqJ*jiRldkI>NMD2T!qGzn_K)hs0^qQA{Y41K6SoKf;>;n zUK!u)x>C9SL`}XLUotTkke%4aH|`vpsau%ltN=bnSqo*g=;NGYAL z6)Am@aTnLjk`FbL_*1Hr9aRuVanrJEv0OHJr1eO3h?nSbMjz@iRW_GZ7T7y#s}9?$ zqqh36t$y~od$z`|43EhQ$|xIPuPZ4 ziMs@gW3rVBxlyy_I*QK|ja!fJ=yeLPe#$T2P73tf;d- z3?}Xbq?#ey+7+69<5NpYHY?I*y>S%EJmASJ%y%2O04l#2K@zcKiFgUZyBAl`5?`mt z#33d&;%%^WX;oz6hc-U`AF2z{(WFV06V333GrY56IAcAOs_Yq4FW$A6E@l-kX68@j zPv?i66(L*2QW8O7p2${~bp~=yykyLbN-gV(=0oW_Vn*My5X0FTO!4CML>N#Bb+U() z%T(K8y8S&eiJMjF99HhkU~zoy<73U35q?rsLETAZq$ZqMvyfQ_HgUFKt}(jdnec{Z zK5JUoa6GjBMCe3Y$k`sUwJ)u`f-`8>Wx1i~hhG@-)T)cTnYZQ(2F74FGKFoZDAPt1 zr)&6{%?XEDxs1vFv`)`y(yL$>uxCx8WCQX4&b2DjzfM{ns;4?vg4 zjyyh;)m@?vnNP$1u2F1Yk@$fVab)nPPJhSqOC|A>B{_|J_&;;tF#iqJ$F=>^O5S^Ahoa8eUu1h}+HF{4Jo-lwRXsSOq= zlfwbG5>op>$yZjTQ05SMF3{^$s7qiG&5X~RoRf_jyWtU{+ca*zXz*kOhZF`02U!jb zLF=I3cfr@c92#Z9n2})toB52bN|hOGiF(r7B$3w?ItLCOV^xMh-b3gN+95>*wFoT= z|4UCSry(i{IwZf?{9T%qrk6bivs8F5F99rMvo&8RZ=d97zf@i`K`Ik|J~54Zo)pSJ zV7{3V3@eHkr~TG(x88fu5y4V@D5(H-;x7Q?$q?Df!bsxx@Iri-Zof-6+R2Dn$X!Xy z0zsw7Rh?<`o{N5tQK+77Ed)+NPjX~3EOsFzo8}UI7PC+@h-8`^a}1B1f!07Lv*6;w zTbAM}icDc|;aFSLv(3#S;yZDPD^DN;mV&rwh5N5ao^e<34CE{iJIkZa>aeqV!3l@g z4_rBLB6QbPzL;GQ&91teU4_8)*57XZaaP^~N9KQ+# z+ke+M(>UP>ol)yK(OdG$x^L|#|yO!zpZ>KI~RZcW7#%)YDFJyYKDeXk|Wp|xr zvQ~D{Z2RoNx#sz-d8=$WlgohIccJ1fDft)A3bQZFwa-`1=g1y2b7{kwwzp41LAY+N zYR*50ja^d2$Cg4|7P6jyZZxCfZbpTaW~i*`o{O0qF$bR;Bd$&G6aM~%S>ZclKPqXw zmNI3YYX5N-Q%8US@pK@9R>>{8K5%Uynp+#rt(~bymv-E8jMM5)>|gz2ogsgVpOj2~n3Q&KljVom7Tn{us#6fjsJvn<{vc>fZzMkh zN?#^d-ZZLb7XW2}>qxxtR)?IC5gxRqu`$wb9;+YT2tM%{%)O+nG&lhagdk0t#y_NP7zCze1J!JE?go$P$$hXJJn{~A=t<4Xx+7Ac0KK8=q@YTs%*nA zZ9E<6>5WmxSQ?0cw6S#D)5jbjfR)h+efn3I`N}zFSKt-G1Mu%K0!uF+7gExhyVy8Z zSOYc#biT!x>z1~ZkRkUC5i!gOQ`UPH!IYrms-wXzw=v7FX=%!8d;m-hzf^0bag&e} z*rL2Q>YczT(prpSD%gsv5+IzY22yb@?%caHZQKt^i$uHkR2Yi@<$;b zBh1uUE<+()p@eOhjA9yV9a2w8xE#RSoyzPSvoX?Mr`Lo6xh^cF!wJdYQDqw##8Djx z-PVmu_t@wCDnUc~xXyPbA^)R7x#w7!+Ll78qhrj*oNXEUbXv(@j{bYv*wbsZqPW^U zErrjys`-ie)61<`&28{o%fOVVFv~!c#z8!-%zEW0`zNR1j!R+XelzqvEncsTtQ?ZFa!t2i!^&;ODW@w5kXvHJjteW&92W`~PS1 z}Tpsm41?sJ^gApy`!<;4ywHcsGK0DE3aropvc&?Z8;KKB=54N4Qt zXC1_3WDu5Nmx27+Af>HAJ1+)%8!X1wIl6XqtGnxB7r9*rh_|b|ANJRE9_duKPADDF z&Ueh}AAx3yc$3o4K#^p*6MJ13wAFJL?VW5BEa=k6y#V~`c--bF(c*;d9}$zGC>P{nWi_ z>d||sqsJ>|;!E|sKy2`GzdqtLpv4<>gB5}#CS(d@OgEBf3fRNLrxZJIAeP+1j|Ys| z=p9ZE>=*xx5{}aCXLS1;`oeLDVGEzoiuoK%<M_0c zQvqnD7cbL|RI|7!^CX2@>Gr!6@ol>Om~PkUMs`->8oDu~D6)rQ=2P6~2$PlGAh^H8 z&6C5i1yc#8k;@PHQ5u2HKa?c3OvD*W0%pVinByFIegG=M6!(jiUQEJTov@l37>-%l zNs6(gfgxd}-xo6vo#|utQ(Sb)NI2T()K|`_qC?3Kp`q zP1yc#+v@*dtA@A1sJ$p`FN)f$?%J#FmsHLioP8}^wPT@V=Va?o>2aZ?VWO4HWtj3` z<6Pj=(N9M2lrC&~Hk|it#C9Bds`GzvH*mi5%k8;*bw9wH;!O7rs`^}ebycBlUk?b(#TFUhPnWhi6 z-r73jol6fD?z)rn=fyuPj<{MEVdB(G9^YZsm3kxfuA>re3Uk*!bWjoC9P#~=(dtd% z>Py#zx zstmg-XZD3%b+b*2S-I1d*S5majJfD&n=4Aacj4+?G- z%%p|#yb;?PMTwFeJC06{PUk`h8%i$^m2aKjIA3?CBIIcK>^RhnQt}=fOev`x9_Cr> zz>uho_J||4;>SsbjNGYn?>J#_XV3U%C%0~!OIgU-8n$m$#NX?}nd|1DoFF;9B%yWp z^vO`gu29kLh+~hA3EAp3A=?@p43|Eg^KRK<^}4&&&(2pxw>}%*`fO<9v&``9$M!r) z0uFPgh@+9|-QW+wOr(}6HoiS4tt=Nq74??Az!v$L+j;-i62+rYfGg?$1 zE~<|fc_$A~G*4Aa4JT=dProp0xzV|h)ey?`hP($pOS*IEGciP^h3lA%$K-#E3-U1) zP+3w+D-AnJBM$dto1w@(WBc}+iNlLEt0oRd9F_MA>Sl93F1%d`FJB7<2PU2&MT^2P z%qVlqqq&}Nt|ywiEu6b;e*Z%5KE8WE{=;Bn7pmD8Dr=6oFimr(SB0Uak?_TVh1}+Z zFE-6v<}S@&`pk0Y!e=;3>{!J0?4lzt>L?34%A$_?u%mwVBpLm=tEh171P6>h@<{6N zvWgVL(q;Okh{MC4pk`OWaRHCNdTjC-j4hwJ@yx89h8R_ye=*-2aun0pc)%tLg zp?J;1tz?4-8^3V*;rYOyy!wZ)E|ec$$Ui(GAG0%EG;@09*xdS1-p2W^iFC61%PYKo z>Dr}m*#Y3X*T4JvLfL_ZyaN-;iHIdLW1*Uj+H=i-eU&R2A$ooUpYGVV5RA;ns1mIP z#J!;Lb!0N4anytuqPY?-!FawIt5^+UDVKyRK}VnVPZF*VrDyP0Fu;?{<&1i#vWO%D zQj{*#WK=2KxMh%}w2C^03M1#j4g%2Gq!(Xaru?M7L6l3v1^N=_A0~LtSh;rk?L&Ja z`sv%2q@R;e2t3O5V%#a|N+w)-{$u=WAWzr$#oTsD{$EE9)MXTnZ>oh;EMRZa?*-DnyUH%HSNq-N{r_|a2{%QTHs5PkR z3eE&+?bG`1Y4JKW5ooOI)J4b;GUf7v1B&0B(8)*L86f3ps7rYFktITxbX*oW5S4wW zy20Sdrf)I}>t%`rtxt;dxmU)yGNwP63kY~SkU3K?Cq!Qg+D?1i+jqFvZ4Ito$@S+6 z-zy`%q!P#tZh{WR88hFX6`o+BhBubkN;w1T>6g}?=9-nk9L@|UfH0Q#Ne0zTVRnhv zjak{_lN5!^eUi!fTrHdX#7<8V&+Bnix?7I2Z9(3cp@bycY^p9u?VE$8MBE} ztvH$f4+OuL-3VlwLi;F${b0o~ROKDsp?K1lO)v=+@8DgcgE&r|@1v#mGWnc2u07&&d&IRvLw@8;XIx92vXY1JZC~HE zm|MtK@7d~w+_jSj9?HF{96MnuoK>}uRTIjr4b^TAu_L84B~)o4b{f>#8Td|b zkf?zxt#JWX)}ra=XmLZhxFO`-d*|pv@rh7TTgcV^SSl<`n&`ZwllN@=h@Cj?1Vux6 z7ArVuC-h+yBwqevU=1y8AOSFwTAlS>#w2WoNlHu&z7b7q{TGm`j^ZWTMY8LBrBQ0b zmpZGujFDNsdMRjjZT0gOQ&n9DIkh)wS6WAED#tIITignVG_sb~39DPS&Rb<4o28w% z6arq+40`J{XpCg7Y8#;R+Cif_35YM#l3E%4(^^NDauAbopo~Ft5EdQht~XZfMBm}~ zS!MjeYj_%tbHjSW4Vbum!zX%!^|1dU$tTP$VL3)p4{iyEqupUV2|d0BuEWPLD%WLu z4+t&Tw9*nHB`?7BP=BCzn5;VC)!L8cV|9Xb6f!G~NZCuq5%Pjp$93%XpeKV{XvH8w zO}#8$<%<(!r3nd2tDTn_^47u4_2&2`$P4pO*ddY2qdK18OQ${Z$+A*fENxFaTTNR% z>3p5}8Op&;&e>wamK`QPqZLOC(~Yev>k*3C|jEnqRT3QTzX@MN&wXeTMNbb<&p-^t~9pTT<|L}aoaRPiI884NF?WHprckLB; z&d!f!c_bd1v8?e&Nh1xy(nTjCjyB+ad6~MOTk+0d$W=w`Gvjy_nGiCI*balgXD668 zUf*$T$4oVRtjKRpa4#!U<1>3gS#Z8mOA$<(bRuGFqX$`x!QUQ_*iO(}=4XYHE1G^KY;*re4?hzPM87Ue z4FLtm;xtW(Qx&%eP}U#Z__UNY_0{2(G_m<|yQsgK+@O~?ZeFH`;PeGNL;`OJSRIvZ z{n}3|wK5v;ogRIkjQ2WvZdfnCGpZwGnX%=^*X3%xI^I{yQ0g!G28fL=^l_XY z$Ys*ec*lKOdG%Ak+ghHZ_Ad7oN)hMz(S+j%`f|k<71d30=@bg}Q);^)$-o2UwW1M0|3>VFAy zMGY$`9i|({KE2(_EY5%E1G1;(*_63N)LSlocf zv^-FSaLxFU^<(>O`}ax9XX21dTo$aIE10v-uY(Vg`9Q?hEYp;q zhsxB}hKVnvYK4lLB94vPG0&_vWU+%5bb1puP!!1jVlk%_Nd$HAU3;;V9-RGUWnABSouTh_I3->T&B(I9O+N zxY`6suTJiCy1O2w3yKX6u+)_g=_?euS_5$#o!_ooenr!rR%Gny==wNf6lpTzbYuhS z-U(X37H2w2nrM1;A>B>Aw$zk`EFjccVFj_bK1t%}GFY%OTOBlcyfOPg*Lk2fuE>xi zALFnB%HD(4ie>3w;9!dUmB*9Jd0vLah#BUHl3~2RKt&mjlg~F-ky=s@w?L!Cmoy?I zMTkzWQiA1#+!rM(Ld3@&A#C=?_?{_3K!gWxc~gR99c5d{T^Gv11UnqcIufxR{XDp2 zZz!vl+=UV@VN*U2zH6hEjp541xfgJ<6K$F2?8c!Vm{2&QaWSi4sxDO6IM*I+IudR= z^4ZCSrnXRHd#L?n$n~5?4hq;%0i>nThMnPto%5F#8V-i)4}De;%4@slkemW&yPl>9 zJwJL4?YHdI(|61Mxu=&rkT5`v30pI!|F^k!fsX4q&jh>CeSrqh02)B!4G;|wZ-4+v z03;q1CBEOF#D^r(wm=XKir@pFZ-bK90%gjR#DGjkU?hjl#Eu${ci2p{A-pHYf_J@Z zD&yHOo@~-h0B)$)I>SsR*~y$avrU1HJUY9x`~6k-)wiojO7_{=OX61bt-5vV@z-B} z{q;XYlZsi7q2hzh;NO`1w&-C#16)X1Iw1C}>&cgXSth_&4eH7H*%V(D?L@`i6&O z#R$a!oTD*D((j`uxhPQ&6~IKG7`3p3pK$&H(+v|oA{XR4c#z0Ba&qR-9wv@ucEw^$ z`w~r(ckv}=UVwNmfqK4xw?@iaL)&lfyR~njyeC}NJ71`+yZqQf0rNmraN_3cv#$ro z=Z=I+`WBu2%q&qw1U#ATjQ4Y&=Z6vJ*4b7r12GT5Jm%MwxJy<2^V@&2???OQpT1iY zuGqiiJb*Q4_2#L~$*WE#YRW+WuTgKt$q`~pqsB@KylL1YB8PBV7IX#p1$CZOzWVXO2`zC7Cdg^D+Ue{Uh4&)7x{>Z1sz+i^3@1P+^rX~tMM;~hD zG(a60AaSh2>lSHrPNki)dW(Jw=9mSt??m;8;J0`(6XRZz0F8F}%Z8R}UshU5<`hIF zmBO3?>jAVf*I3@A3UPfW>eb$yXi#I||0po2juP``BKlq#^Bhv1_@zq~&6R#PUr6W_ z0^ao)=JvJw-HJDPuXYdu{)T@QZrJ#eLF1;R3^0!jPv45fe6zfdR*(I3JCB<`?R75s z>`%LV+22bR4%NM|=k=tb+6NgKHaJ)#U-mTdN}+Z*3i8)C!*MGtHPC4h7oKG%+UQ^% zeo&E#8baCtMsE-qA3st6j7tcj9m5CEUJk)g;gBbjfqT zsFq!ih^S_LeE^KAW^5Z&S#|j=J`7oIZ2<-g#)|^^HoXNgWwGUa7cSPlPQ-E92|JB^ z4c3`1o4_|gf61F?u!Q+Y%=}l1CEK+6f{%7RJ3lcqF>^X_GRQ<`qc!UzH8>+*sObrN zdKcY&A70|p?Ej)=jaB{@jq2~xEsC4JSv}j*gqg{%L%VnMlw!|uFu}IOK(kxUrI$6T zf_Yx$>BcN|Pypw?y16q3)l%*Ts7+Mb!^BS)4^=Yohm?Z{S=quXee_6U@Ih3IDk` zUnKd{s?Y?w$UEQtlc#?4RJ4D8q<{b2BMbe9!hMIs)kl_GNAFiuzt?-Ccg4cz(25Nq zepD9BIB-VDJw=3T;9FzPf2S~9O)fb;$}XpGKE04fmeskqIh}ykJbfoG{Oog)XAXs* zJ{msye7O3BCD)4v6Bl!N3k}aKRBq9%TPzo=)-Buzu&sl$+-!?eASgnIZj5-Xg{UMG z6af^QFO`fS7k+TtrscriM~mz4Xu0i=NvB;60Ns4OX7#~Jj5jUe2#<(t)8)0juP>;Q zy4bw}fdd~jFmx+M-gGFoSw#!2?kQJftw~)r1tdVamz>4E{q9Cjzoi8(jy;y(j-> zR>C(eB61SntI_MO#wInP79y%?*DoSu4Lu|@(V^CwZ9X(&N&N=Y_ccgjIRwNmY9}~; z^E$mb>bF&RVI>gP$aJCRv`(8YkiQC<#@<_FO2$ubZbHd|94YFS=XI%NKduDb00pbX z>f~A^^q`=BK$JgzWW>E9fIpphP1!4n%D-Qv#)S#JBCgxxN30{cuZ%~S7@Kv;IY8iB z-#5CZ6JkR7dAu#?YdjUq6dl80rWBj_V~?K|M97*heQSnMu$>`Jsp*=O2DNP`@FA%M zi|R`o;zUCqkHg1ZrVrt#I$GN;UjZe~jQ4Cv&gCtoO(cxf6vBW`k06~nhei5o)U{ub zUWWGsCQj6u1j8`TU<)gB$I6^WKMH4(J4sRhkTc10lX$i$-(zu*NnHJl!F0OZgnA0_ zjJJZZHpu*r2p4JwIMAA^?`m6a*l{F_iK6n1m`#X17(@x){2E#NTb0mb;u%DWB7*n5 z1|uC~W5`2$JJWUM8Pfy&lnW=*eW_ZLXtqP#_gj<8OyDN}W@=(I?;-BjRBcFnQ$U?D z)f-Wd)~fRp<6R`~bzq1z?`jwT`+T@tv|byy-uRYau6XP8`XC2wCruaT@J`bs{7hJn z#j`vGmirpb;`#)b6uRq8SV=`|1G%*q^t@uoNLVMQ#k87;s6=0io+@B9&o{Dvkn?dX zs%TUUb3SFC3u-p0QSWTE7xhVE$$~Z4(5u4Ulm8uRv`0AJ${vP&`_Uy^&g>JEU{(?m z%np28gfSab7zN}snjq&%F;c3T{QoUBN>vLZJ`rQ$L^Cf3ME$Gw5*wj`6JXP&fBTXJ$JZ?bM`Cu8QG&q_G711=CHC>LbC<{#IesRv2Z^p{ z>_H-CH0B^w4#_Nqh%Ko2u7b$RB@6kklH2hjO8zl@D2?;`Zs3v81ia7>p2ANWmjx`o zKOx={Z8f>=hJxLZHM@d4X1cF$`t~M7|BGCPuc>Xzf}GPJcQ6#QkDT*CObC{6C;X14 zQ)Jy0vg=v8Z4kemq@v`P@xDKQ=;FlqAgq9l$V%3j#9oP6`#AUa|3(%5iC7QJ;)%b$ zNrrP^WN(8j8yI9Y*e_{=@ssMV&P`e0ua8Sd{Sd<&&#u;Ql4uvZ-7DHQgA$_$WOin-$Pu!x#?A|A8Km z-B4ot%B`>bxcevlKk8pxvumMX_d?!on9t2DhVvnJ z>6GK6?9%0unrKOLq@+1o(jO@y<@u6rQ@igw3b-kTsDru3wa*ua9S|UShMWlYz16qu zEas~EQD_k=flp{Mdx8W- zo`qGt;i|s*rf|i!J4gQV*oVg!od-2mF(QhR{P9I6yh(B+#a-M2LFmi#8x|^lF8I{ zb1%+|&NemI#C4bk3AQMzc~qk4y`Dv9o&JWgK9ElfUF*D3S$9Kk$ufTBDwI5zo3QbU+oP<(y?o zae>o;<3T@nSxh!Q;1K%z%s9x;-D_Z28df{VJ@v)~C~;2Qyfk}hZs$THGadnZCd=*t zIy2aJZQm~?8+gT%rKlaCgnAN8)HXzG`y;je3$;&$oz=?c!b}(tRxm0cg4m;oL#n+W zs+@aep=9$N`=VoqF2&S;tv`q<(Mr(CM=nqh*d6E#9tqV&Tlym{{qwsPTDFIqcij1M zxa821^Dv14ssqd*@U33u&2V{3xU4kp6egH7$r1P@df{d?h(r+o^?kJ$5avp%u^ zx_xr>Ym9B^PVP5(AVrTP9!h+%kraII^Nb|h^uQh0J|f!wBW`|>kTBlBbW%X2y^rQ_ zB9ak|jIi86&mPiEC;ylt0ef{&et=?yr9vuVmfC=>F7GZzC;0bQ*xMeuYRIIU=Uk_c|+)jUd6@wLJ16Fi2t zQ4&YIMP=8Izk3{Z!4$-@F}P#V*`lJHi`V_v{6WwL8Z}|29SE;->p*Y?ypG=E^6WX5 zVvoMys)ZY6`zf!El@s62v^a|&fvNrk{h3lE*C5QwqyTNH=BHtHr-|58@-Z>S64^}A zrR{y>;86hCzn+LLoFECYC*-Nj(t?6-cO-!9a0I2Djv>WFm zSPU5hTm({S%DM>BI+{9J@=KJ&#AKM53)_P+F&8%V{xiOy3ku02^p4_4o|w|y zkvs(J;agRiamSFwJma$Y%sN2X#P&m2(o;0=W>GBWT}}PX>e*`8l)Jc4^As$pO=Zs< z)8~#Nq09YDM++Mxg^<2jR~ctYCpj3i>Bp#4ES)oeIOmC&SjoCQPL)R_lQ_+CB- z!kvtZ#G$lWC|RjzI7o2%O_TySEvY1i#XFbDLZ3V8sEjx&qYiTP8mfa`O&u;P7aa`* zl^{Z9p#D>n2%(!69c%Tx8VpArWf2D{IJVws4NfjP$fzZ!c!>9;!F=VCqahid2}3b> zp8IbK&j$SjFsof zh(L3ifl=x^P>g{-XR{*RED)Q;G=CY7mGOdc1^_8xAMHzNdZ-gbSqxr)-jBajG&3mW zI8BN7@Fu2&&InyLGb9sGH8D(nQCS_d-*nD8L*CnGZ=L;lW#9Dvshu<172=s&&SFfW zfZs@qE58N3Cy!hOI1IZaL~Hb5kKR(Xw#&8$x)X)O*FJmV&19A1buKY?1D`{ zP$ZRPx{M&BqBomioEXJ+2jiZoOr@A#-htsbJaK-)taZpSmYRBsy555iqw9elOwzA8Z%1 z3tjVG%Z--c;n3>fi;?p7NM6SRFnUhz+sCJm2W-=WFnG+1tibC``99%*kbs2YUpf=N zZZUd{Q-KLSlCAz9AAv@MVo$)s%nzdV9y-pL7=_vcw&SESVbG?9?_`{eW$`)cA=~<= zMqj>21`}yQLsep=-E$BpZGtyX!wCY?+fd{vyfXXrLePC&&0^y85NtmxUvEVAixU?v za%+%mEQZD=e7XlroL^Fh%YNL*s=7s8RW%Co6mXpxOgsWH|pTrQr(vtlf60Bti{ZhZ_6hA*q`SG^-dd+&-`W6KFE~g<~ zohXJ(B3_mJ*RaO)Ir6_HO^}E-yM$BAW=MCcIrY$MH>3;d=#@roBAQQMlSQJ@)0#Mj z3a2C*j$>`xl_qccM1lH!krg~|#-r0u*{AGN60G$&V6DeG)mI8t>TeF9z0pwdR;#ii=N);%z2}1|fCr8Mb z9n)FTW(;#RJETuq#VJC&XWP*5Y2@{d!{jQ>Hb@(IhG9K~^qI!ThJgsk1vt#KD)W#X z2DfKv6Zg=_#6@|`=Na;xIKdRTCdl5$i4zrXw39U#%EL##JP__6*}Rn|euU z&yY-}aG=wLGj65xMu?nY9bo7%s+8JkT20}5#()>w)oL~|Q>mZ1P+L0jZ>ItWhbLa+ z=hrmMay@Pdm;}g&+uZRWLN<5OU@-@OX_K00syZ7E^L+|iQ=q8D%KHkyBIZP8G(5#u zbk$N0d9h&28jS9usk@+&g(GT+a11gN2x_V>(V;&11Hy_#u>R_b<)ez)*-dlO!fKqE zZVbCO^3{h#i4vMZNRi%Hq4nWb1nc{QGY-llzznnw20sA<&=vy*e%qg~r0UEA-BEHv(4s6G%bJ;0jS?37p0cdO{O z6)&*Q$;A9-BaMz{Bg}_8W`mw0+=f6CZjgLqFe0Is^3poptdPM}VYw8ynBxLuOa_PK zmt`76)xvOa?yh;nv{HoZBVT~FrqH(%Qv#%Wc$ zWmRposxwm68Fq9|Ic7F4=N3%an4JgRAI38C4_r|lt!Rx@v_>nsA{AXz`~SVGH0oli zPR+ldXnn+0A8zbr@w$ksE_gnkVK2@7)M3dhm>y=2Ya*_iVB3PL16oRXxuBGDiolL8 zt%SrtUP(Bwnsl^!zQ5(>j@cbh(#r37f9Uqet&vYDigUH{s({3fpXG3I%Z%-QVMX9F zyc*!8q5`U?7^$WSdde z9*y|^h<-!9hA=DhtaReUK}Opc@Dvlc;m8PvK4lmt0md5gz;qJfPhhQAWeAs0Bteap zTQJekl8<3J1Cf-*R1#&{Eh-+8ShZ>EG!i}p(JhduWR%iCfx z8-{2dZ6eqkL+3zcoE*`L5xvgHjgcYWC|+j{gI-1t7$7+_<{0vE5akYy{u!_#6A{am zc!@C?a~@GF-E9Yz!1o6w0H-AWF-PN+WImoK)+Pg!fP=6h>j-~ciV2aB>o!e_7f=zP zUpJ{@=3L7OjJ!8?V{E~-W(pR}A=WUxS@AjKE~gnYwFA;u&f*#GcXmW8+as0ji`gB& zC@h}2_znc2s(>X4Z3RXa^6J7W55YL6Xg;wyRSYm=tYbVdU!obss`zpEl|2CK;M zQ}m?oBt8W&b&{E329&k1lB}FKhfDS@IrlB+6ukY?^h>%$HBANzXU2>(2Kl)A*@bU! zn%)%7X6EAP>1)>~uT3sF>qyW=;d%)nmMV~n>t%#Oj4}Gce7#BVri`;O&G_b}G&q~E z`Cmvm`a`E6ula=spB!eE;A=N5$p-5~BCdkEjQiZW^0w$yNv#*N;4k8@gAWg0IiXuz zuxDhKn+&ypUv*+JPH1YU>UZTLsAaM=ku4pgJskLww~O<;r;+&HXZ-y!7@f6=8zq#UXY4)BJ z<;B%{8`PNI7IvysuRhnq$qXYLvRncsAj+jeAj?DO#B?QN^~a`h~73iToV%Or=k+G5xSXgo%} zxQSvlek!fbA{U{);#sP3FRhkimYKAxCttO^W;I+OP4q}X~&?WWiciv1F|=1dU*!jyP$K0>P%t3%9=t?Bug z4Vzsb;d`(z_{CWmih(}93X2W&@w9&nAnKQ(2?X&hW`GKso)T7FI$cnL*S*9U%Y0JL^#ZLt3R zqG)q}q`7~wWYfPdua1_tM9Nzh%G<*3Hkh%AmUc!;JLh)Hci(A($GjQofeZWF?_>qL zLTR%-?;lw#T@SI~nM2nc*YmFB1*Iid1Nnx4uf)L7z^)}%UA%*&?$#4w#VI4Qz0&o~ zOMxx$RH0aTslVAa+ZJ3EdM#Ytv*hZf0?7D_`uGy}!AK2eZTx#^Uno|0?2CEz%;(XX zNb#DGccHkGI3uOkH(lEVo1LnY&YsZl?B*r+dXm^DubiEs!r9&>_Zm^oBTByg*Y*e9 zi|z(yMJDQMh`1Vp6QQGXyA^j#B<0@4&D_8_hO05+Y7E&!BXcjp^P^I3q_CA43A(m7 z;QRK$c&nwTEZ(knM8erBM)LcsgWf-G4t@1|?Ke8-ykt&M9d;!rH_6-ZtA{WSQ&b*x z*G1fQ-yaPZuKmO!v0=p?i#i@gZfaw$(s(wWe#V%VA69M2*_)g8v)q=wo1~xhTX9d2 z(bA}+D}c9DWT=iObRLlU47PBEcFiZKWOj)*GAh2rdUu`4EZaq=FO#-cpwD!*0JM)t z(n|P_S~9THlgk-CvLq(;Ae2~uojkH;Y}~d9B@)!WVi;ajQep{$a}vFTt2db31Cdy! zOXte5?}+_i2&g5~`lwM(dhxmm)kl=<(etY@Q^}%L-moo(w45~HFTf6x_%5)p%6Nyv zBTb~|H$ZYj7hrx2dVU8U<#Y6mVj%0aPXYnVAPD#ruPG<*%zHghSD0(pv- zhKs1WuHzSz1`Zz@ImMOm{wGTMeY!nMIrW8zRtSSc0kho7mJXscC^5-M;Xae zP+XCrfV>J5y7IvBPq1jo(a2b=2?&h{D8>nT<%tj)kc6_4!F$@JPB+CO7fRw65Rrz~ z)MwxW(PD49Op`I&l#HK7aU&3hA_SL+7Bt?gUKUU<^qtL@Nz_Sza7?umZSurIREeat z00||i#|Uj>yjg|T3aq%GE!vh*Z;`PrW3+V>ebXl19J9?^Vjqg$*7(#6xe3r8&=@8$ zT`Wfpj~nmCv1Dj$r@t5SzD);)T zC-@$xgBcD=DVE6ySw_R^h$s^PEdQ7aAZ#QHMKtB_BHhHZQ6w`tig|=&rXj-tF(O(n zuDE{o+Szx`Pi2D$ZCf{$%^ZXkatn)5M^nVn6mpY-o+d0-p-2&vyym_|hlfysE?Cyj zWjh~_M#6;yi;jb&_t!t&A7-pQ#l?yDy|XvYhWeMB8;QOI%ML!-E21@>k($o1r)zEt zTtY88H>wzjtFS~J9QAPB7DeK@V#!gTjED#+Fho?z5s}a&0em_)VMJa88q$yq-cv4L zDV`gdhU#-Co(m9>+=U4uU>h@oLxSfDH%5e<#4@4!GX9We>QQa3AyjxZC(uq3 zNHSd_`B8le;&99kBxCp5X}0TL%vev;PFO%+>2EXt+9EVT<`e}SIOx2jD}EoyADQF3 z23`Q;9SX|Qzs4j@GY91VMDwzRZhwV3Gt0PsR}l5I@>Ha=g2>!m;Zon-=P~#X=VyQX2i=O`l(Sca3TZcd}#C!d1YE!%M<}m82jks!q>#_HWx>_Qx7OtYQ=;~h1Eqwd@^!aFRbtIQ0S2Jfb z7jj#sY+U`DKJf~vpsJ=BH%SM2qd#7f>{m-g{5@01O{=o0lASzy9qap zwgwZN(k0S1W+&1ak|)Gclbh*Agexagse;7W;Cu~5lZlbaVofHN^acS#FWv+%Kg$BE zv7%8VY)cLaRtJg#Lws}tmqS3s?Msf1AO~yX9y#t zLIO|cq3g5R*vBc}(#SmVTihf~hTKjoHaib{5jB&?=|)qNpXCnGuq6#mKi)Ad;L6Z! zBY_6-(6FT6p`jruCd|{^0vZ@-Q4ZV~SjcUivXRTD;qP=WW;1nfER*m00-f)?w&e6E z%jUZifo<=QO@QR_AxLGj;1`Hox8M{*cvz)#6)=L@Xy6s)60de@Z<|AcaPTs05I4|LPZca8*vm z8(>XE%e-8$`>y+M%l@kDZVp*YcD?Y=%yG62IX?5zdh+$o4VE9S-_mOPu*HhIc$4-Y zkTDh4$#}xXe5`64wMXMf@RWe6G;LcO<9>_AIdN+s!m1FnQSksyMA{hVMNkr?X6=l+ z$nY9?-M^MlzyXRziEdS<$o9BV>_xFw?lsxLzaL^eFhuqPk} zJ6XaKEE z7^7cncxF09bc!}4eW>(rcu0nxXcj)fkcg-n%$=M9E_L$*LWrk}Y6tlL*tZQP{mYB7}pVooD7DVe~HVDbZ(#B=K zor%tA2pjd(0Bsc-4?q(hREjpiGO0e;#wt?0A;1cF11|c;;BD-Yu7c#hDpSR> zHj_&~Vmh&3F$ZL;Sj?Y>!&QczKEYrBE*WvjgsuLW0Fi+yBR6Q#N!|heZv?U+nUWSA zg+&cI5-ck*i<+nX&jhh_^vX^(4YF3Hho<)=%2<`wPw%;3T06z`&1roao%vEQEnK*o z_`i_h?t8b7^Px%3%7;@grz){EGqL2Xj7t{xDs0gdc_A!FrH@#P{#R7#Ne~~#*9gye zi!L!Kk^mP%BNl)xHz11~Ns3Cf8B4fYoDvBckSA6lZ0i_-u>}>w{(y}s4W~>FUSqcL z3qE-_ewsE3inrKpP$U_G)SO8jkW-IJ;=iFW+=(K%-xQT}NM_O(6kl(8w`pptic#bM zut^O>;R-7rxoy_4#1uY~dQ>LR9)5}YpLi}{##l{9bAp*Cp7+MyN54W9_!*RlSwUSI z%N)PJbw_-1KYnwG0qSA_eXexwL3(4%EACt+ae+Fw69wvP{&VkM3c7EW%$C5=AY}hT zHQ~ZGuEA?O711Wu@C~RdaIo$*T9%G+A@L7T4fSTJWeHB($oBVF0+LP**iz8T?eOz!Qo$Jbw z4`;(9w8W{nHAE&V= zhq$GVnajZ~;lc*6x5Z_0{0fOy0mIvlx)21e@RK)#x~)|-0uz*0#`qO6u3dVGYK(19MKv|-FjBO|K!W~; zd&w{hQkMM1ddaXQM#)dwM>JbSeU!j#$82>N7@IOdUD8A)5iNxh(kE&r7at?~M)Bu< z_}nO5ow3D}%~wMFhS_`vITI}gD2N`DlfIC0=2GI{)688&fzTP^N)OjhUpxJM>1Ot9 z_F}eX+{|D-Q=!Whb7w^LOe7KTkbpKBHrx^6q2z|1~$_#X>PZG8P z=1l_G=1jEYsWAtZTpld%uI6M)OT!DwN+di8W10=d^-Gx^nCI$5F@&bs__){}Eu-9_)NJ8_z?Lt#`UNoUOBkm~~$U zPf2MBz{|jH$=L)_UEv$YGDm$--6c!X3EFZ*MXbi(%8vmZs+D&UOo-MPhFc#uCN{Rl z2y$UOMUWsIErsGVyS7Kg&6lW5k%>MrWvX(#F5AbBi{TAV12k`R1O3ptZzA?$X7r0X3NMT{@;MNPbhLC*Zjb`!0To%mjHI zhIFzUV!FJUhICUJ{q$zR;Dg{meL|D55lXpeE4enl>67Vik|z`qT&81h17B@wUU>7f zaNh>VFO;k?;u3M0UZ-9fatK-`oL{M^=p4N?!d>KTp*eSet;l?f%0yDgoT=Y7Fz%6C zY32Pxy3x8Qdx$#TN-@T=*g~;SaBI#ptigo&D>7y4B%RFum7ENo;*@p%|$H%Ve!TmN{|h!U%IsDmUSwkFXHqw5z=KLIqdBMK5%P zVT9rQ_?W-Oq#UUjJu_rULqR?|Xy^W4$-;9=%Kh)M-OBbE_Q%?8wDCjfNcp;O+4{Mf za7ovqvm4xyXyNKe;p%8%D};`tg&mQ?jyd}WnLo%}DD0cwuB`effDGvzxp{2%Sfsoo zT()-38ZKE+wx{(1nj?kH(ZV&6LWon}9=$cXP}noIogJ%BZ3;?J&)R#QwI9{3x#5`G z0L~2Pg+0@I0=B@OK!5OM{zm94^EKh(P4nKLoc+<+Mdw~nH#tR$Y3tEnINecaO~hFf zUfs>&o`};ETmxNscNTQzvva3cv&U5tXH~$v;9Lz|`Rpt*yPqF-S)A^0HnWXRaym_c z^5FWJuYr5Hg2RVg#pX91N*JurGBq*LzDVE0{1+y0`So4pyDF^-=Tmfc$hI;+$55qW zLrlVU3APgo(b8?fd7^Nm!vx+$(^#0>I9102;*(DiKU`jeX)8cHu=JWHS`dIjz+_61 zVoz`{b~HsT1jM`SNl^>vjHUdRVWY!D{6wutPx*d^k;&r)D)egRH26vII@m>eHH~yp ztoV0H)kSd(9P#HVN48Diu9C!^zrC4>*d#Gq%_^))euk9%xm?UoEkxc%Xk-gO2==mQ zFU&Cv+e_$NSBAX;gmoDI^$q|nVMD>>^~C&CZYi;iPzlNPVE>QFO%mOB*>aa99dT_}eY_@>|rxUkdHGz5mw!(B}C9 z*pOXvJw>VL0F+gMBgF1cD=fLa(VU)0PS0mPqAK3qmbR_h_OGg? zZA}>ovyg}{HVdyJ@;PQR=! z8&A;)((C3C>|V-I9Wj9NR<~%M+AO(!(VX5$PVZ;FOuY7PRiEvDl(yIsdyQJjdhHp2 z6fAOCzX4l1@RN>T=Ic+D2X8@!Z7OZb%B(e6VXesqYfTDXGrnUK?nMp(PMa2PwWbZn zBq>TZ;DD4R6IM1|Pf)T(T3KOH2vRpn30AT(C2FIA^#O)L#=x-glLV3^PrVYvjV$}1 z!HAi!H>=R$g2KhQrxOqs-V}7K*NW#vg_y2sO(7NtJwZGLm4{HuI$$dAAeogM)TIe) z$;id%*g1$6LZEOBrNZ4hnW?~k{|19u3)t8=1#LE%>R=|Kl(Q!2O)#4luw|zRD7M!& zH{0R<2qmr8_od92JLU-^uGkc5MD-b(Q|%VTvY9~_R>SrFb%_L&diF5pB~y#KX(q!f zJ82H>N2$NUwiU*0{L}t$UcHKyy58%%(HFe9=vuSvDpqJAXeJc8NjnQ3T!M8A?#6Io z6EI$LOB|AYt-rL{b8;CEgVCvQAw?3G=>{=N`7iJ_90k0OKoXB-N4G#MWeq@39r#jydNakm-Fef+04<| zSr~4A*%x#2&+=bMTSM87x5SG+nMgfGQ~6i;Cd6PLx%~qZPTd-k0ZFSjFDZAKkF?-iDnslff@Xir3%WI+eZLyE)ps_g?Sb zKu+*-q@)`p-jwsB?2=_?_0;~TvpV9e4rWK3n?jQd&P^ZXl-}6?iwb&DfhV|4?N{V< zY0DLaG3|9~B?txS^{%^@t-JA}gZalC9MMpurt?HN#cNHpMF2<@z%uq_B1WEpDgi`- zy;_c;R?p3uj1Hsin4nG)Z5LA*{`*EQy*e(ZIN4PaFVL7bu`yRWs_S~swVuH6watr; zTKySA+Cps-jjFryh(0nMZV3nw^aPb;x{OpXdQd-FGHn6NF2(&r4{pOz8 zJz#JN-IZwD&Et6Q^R}9lEX0%R4=qW`7yc4se=yq@M1A|dYXqKx zAvn(9Oop0L4mCSon;03R0`!h*5W!4xzHd-BH70gbxTp;dFb8i9hTEQ=m+#d5W%Gy4 zcPhe#2bOTSx&e6;_UPIaJMxH515ObDinzOI(2UGut`VW&m!Bh14go(2;6{;zC*vPv zVUqNZ#FFsF99O9Wh-I$hnJ#Wc1KifH&3-LXxN*tRliX}Vt@O9jhg&LGK?4QNPHLQd zRg4qV27w%sVY>Da4Kn0-n;KM**dVe$FLbz~wW8q>tuQVse3>K`JxtRQlnTb7SlhY~ z83*BnOr3hSaZ*)pW2XS)Zv*luf)otEu17$4Mmx{Xqy?HYHD$FI;2kB&=|sO;ugxRC_Ds5ua+a zr1z35`fAYrXcCLC47&D_EHg-M3hnWU$xj{3fC^C~^Q9|;vF#W!_e>XXNtWpme&Rg^ z!?5=R5;De;RS?e*c{DLQD>18=#j<_FkbC65rc4r~s)PY$5Rb)SO8Op+#X(dX$X3?} zUv@l+7I>28_ak+$sf!tI_(#Bcs#&6P0#gg&k_c&v9fgKLu)G_1m&i@uHC;?Q(<~Yw z0t2CFfr&cLHWiMa#z6+y3c$c?dtc*&l76&^4(j?-E5$*KvBiUeDr$?ApxNQ$%EL2c1EX1V%js~HP(To|lF0Q`s$RVQ*QAZWrga$^HwFghaW$WhJ=2p#rHC(b~$+4B~4WKE%^N9T4 zqiXyh&C2b765EPcu;?3v{`4W=rLkd;{0Fq|{xGH2F=h@SmVN|SW6wePJQX^P8$620 zpf}}-OY-ydY>aOIM7RG$w^q6_(Th(h_KlAy5V$2!rX^LH-8~OHB+d&Y*(T|}GzhJK}U_DC#iC)~I2xV%JpKcd^;Q5M_IaasP1 zVrhF$$^Vs}!%+|V2e(+Z!H=h$O;7CPo=`5JsDsXN$)O&dae>7}JPj{XN@uQNVonG) zPmB(qADK8k?&aQQnBSRljw zZf$6t?K~vjug=e{Z)q}iUR;lZLQEgnJ2zcA@lz3+POrUUjJf6WGIV^?l z>n+z>0*9}4#538WEK7a?6UJKiUeAplxG0Kev*%8-OPj-@xfXY6oD~jX%dFg$eD?HE znk79K0uxe8pbPYk)UskzAH=iLr2W=_EpDMOc$kNwudJ}&afeN63l6VX5X7@=Qbz!e zjSvLA^oTUdyZav43Z!26Dvh&n%{ms|&&*ko@O-5yO{#w2NRw&<+o}KK?1fikZXKtODFZxOOkIEzM+u5`5vqx4aEuL$WDgzhkqm>~yeY6rE-EQ4&ePBzM zRxRhd<1DPIV^Chyb!5{ZBv0+$eS2&&_-L<>{B`~ARWm3CW0fF26(V2CLUKX+t>MdImJX?>uOo~{oT(zEsP^yjP+ ztalY%-*s&l%oFXqu`g6~yZTmjxUwhW?v2}6^448Eaz8Wc?ULz|nWBJWraF>Yvm#M) z{8U<&lojlWTM*0vA`#4^ClSO;C8;2A^u6OZj#CF0gtk!!7sN3RH6ggyLNK?Q9@VVm zW=pN{@(gK@bq)y>&Z8SBTq#JC>f(UV4I#7$!5o^4Af9WLxJ3x3Qa2ZFoEfFM3*-IFFgYlR!4(Ho<23;RLi$09UjZ6~P^(Dp;g3I1+8x7-`r@ zm2bR*&m*{tk0Xc|XG!&ei|_ew_z5uU=jvH7zn$Q-K3lW-|m`7UekiTBW`a;LvmIu2;wKKlC(Nxy`6O{Yi`{K-9PA#H1$$>tLFii2;#Yg zQa!=f-fMf~Hi|d4@vsLt4ZrVaI#(ow@s?aeMv7BL3MnH(Hrxo~o=mAyE0N-qkwVId zkYz*|FFs%eyeVKoaRLhp2`ng#zm!%bHK{oer3?rt9YK7vTWZk91V3m@5YU()h_5Y? zO4Ttzl*R-BjR}JI`gCcn3Jr)7G$0^oKoECHQmvYbD5WBxR0Q$dbSXD@G1}N0X+(G8 z#~qZ7fMdwqxGO_ySKmgI-bO%gBZwEI>-9pE>V<&ng&^*7=&6WODgsJH@BkjUDg)aV zT%Id?K5|t&DpuqPx)+KXt_)DV?F+6N^BX%BT(x+XS03nE$n#v;{gJC2w&C(9n<27+ z<+_han3gS-(O`TJvlvkt38np*tco!j)YScX!-IshhX)@Yy3Qq=l>e zt@4@ek<7ABBxIlu@`B=rtgL#u(gqcv5v4vvKz)cnsUBi+56g`8L4{vL2@(*@Z~ue> zB{O15FS*g-Kr!C~ib0f641znzj6lhZSiB7--`}zKfz3^=QzkyeX_`{Fc`FMsO+S(F zTYI%C-j;^>rj1ntAFBpFRt<5dO|Jl=Q~?Bp;}FENFxdE9)ZKp1-A>d}>GDRbUkDjK zV4win(vXFIQ5J+O3sIgRMh{{MLNRUk+^8@6+1 z>m*k0RmSvHJbe{UhxHj7h)nuQ%RM(Fi|JQq4-1uVtYTy_%R-h&DXC+*?`an5m9+xI zlo3IcIs^fA2m-1@g9?C%5&$9~07MW^m-JLbIr?F#_!ZA}V$u-$VeP{Ysy_m%KZ1B= zw$#Tex8|OEP25JmHeh*1$SQ|0UY;dEON83kdC%P$x3Qm_w(tmYJ(TDPWBSOqvDInb zDgPPm8`Gg%N6e8P`jIuv_i5)wPx9?%Ci8qgK7P(8+bKiZ=(tS$QRoL_A3DJjhzo0*U{Pg3dFuM?Q#_ac_vk#$@~>&eqA&d@=fD?5dc24ZPqDpQWl0!&1(r8?hf{ zVz|qsekzkBh1@|mI{J!97h!S9$2AJ+q)XmIw_-}lIdbgT9fR9;@7T6)&%mx&K5r!C z+7;OxUn~vv-%9yQD1XKgXc#^Z=Zt044#p@drNo!%CvE1rsn5L>BW{EIEZv9~ATxH( zZHmoNX2$kE%hH;>OQuV zd~B)s*s}f~EL9&{s{X-J__3w^V@vhNmWGclEgxH&*nQQ<77xo-hRA)J{Tokz{ptVR zUi%OBru+7sD_g#?=gmD+!-4$w%5Rhhw}tX=7u_lf?v0dnEZWyzA?LQ)dCOV3%UL;K z=BxMI<(#4i`I$LsS2E+JIo8IR=i(Lwfpses#61Pp!Wq!z2>8w_l!v`z)sL#~W`rA` z4Ig?w-1vN?@`V-35N~l=3zr?)aT~(>Qu;TJzj=J78knnNwqtH%*wsIOB<$J}k+!Z# z$Piy^scTv;sa!5De~?#XMTPR-Zl4B@Li~RIsO^YN&5Qcknm8D<~D|nT>?!gZR_Ogf<$Ad8IEHf;E6fD_U(cLkVm06P?z05BW ze}ccolh?g^5N`{65l=qRJ=#=9ypnbgGjrAY#p z(4B9C@1f=5eBX9)Yh6p4`s~)xr%9U&(bwuip65JeJcBc{i2&OST$RwIbt%K)g=LwS zQ(vn$zxOdJIf}o6(oCk?jN(bWdnCaqO%h|nBi zKIJ6AO+cIT%0JRDz3_Ca$DKOjJ zlgSID)Q4`#b#gi{QYM9>CY~TmvjD2Om2&XKil$5L^KjE^%PvAap)?+v(dQyekCe(@ zg#b!j%xya?5hWK~Ugy$S6k%l^BE3QQ>?J_Tz&81VC1mzdYWHkvrbo;+n>qVl%+V28 zb#o@HsSE(y&YYobuB`b;OhR*#2PPCi%XhSul{Co_S)!!t9fne1qDwgq{QErLgKL9& z>ZbO=lCP)W@}$}25)_ks5x4ll8fx9Y$i%zE$ct3g85VZf4mCwDD?lOn;jG?S|C+IV zmt9VjZYWCkcO!tTW_v3ntA48oy({NMl0&~p10AMTnOqfO#QFw@nkHh^Hq;!HRm^3A z0h84cPjv#vae^G{1TK_j09`n1^l77`*j78L(a4?4V2;dEf~L?g8JPdOT$iKi&J|zGE literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/jinja2/__pycache__/debug.cpython-312.pyc b/backend/venv/Lib/site-packages/jinja2/__pycache__/debug.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7a86f30cbc1669299c6598581fd7e3b8f5f8b304 GIT binary patch literal 6579 zcmai2Z)_XKmEV6Pm;Xdblq}hnthN3mq9WOjYdf)&CUGR$uItE-t!rUL0lng`WKyeL zW_BrA!ZKEh0wr7FETh3$MSD0IcL(d>qHv2A&3!r_iXQH8AL_N7lHEFhfaY-UH@41) zpkMCZ%yLOdq1yp==gpgWZ{GZS?>F<`;c$S0^z@7Wz4n7viuwaCxQWz2;n_KwqHa?X zCD95s;pFrL17${G=eP-u#yl2i&x8kPPVy+;Ip2hj&|Za~^H2B*?E^Y65uhoVN$qjF zspiNFvb++S3r~cheN^&8yS8e*OUaSFKuQ6*ewvel-}X#2NFlji3O}c{hqSJfBT__e z1S!vSK&t;XHxZQ@K%&>xTFvDM@cXJ|mzrkE{W7V3msidIvJ_a_2z|CJ(y^weSZFLp z+x)O5$>WP@8R+mh5)<;2n3%k8mMY_Dbwd_q$#!GIc?Z# zo9E35%rm|63yI0{#^H+Y$~Z@;_kysqS(7)}cx9KFY?faMbFg=6?H7}Gd%aA>JmPiO zJeTAJlr&_)xF!pU3_`MM2=euWoHml0Dj1r8WH`zRSrFAl!EjHzE=(hBE+9Z!NE+9Y zs*up;(n&>@1fzWRfg{PJcDtByO*8~W(`E%FIZJw7Bw7;UoJ@2QLn=BPXK*M$+KgXI z>cU(`H-ss$Ra9_q<=#bAxO&ww`|4F;O3@OtWud{eh{QR;Q8Xx=))2I;;h(Nv?I&Gp zC^?e^A61qRlGCJbJknWJTTl;?;-KT528D5$wu(q~-mqCj9U{|f$S{@e+&LP?$CmuB zWmKZ`b-OVhPbJlq7a=FlhRr2J-LS)NiMl-ME)v4W)(#}W zlj?@3CS-)Yn;n1-RULa_31K&7*I}dL6*KI*X>nHGR_3Q+{Zv>7+p8p1S=DTxF%?&_ zQ|5t~hG~SVY2v(*4{P*K$7d96N>p^4oskW@6@E|+n@CS%6FBWScRjY!8elF$=wyw-mz1(e^oZPaz!FbnGGV;*j)b zad>d@Z*)*QdGyH9qqCD2RCxp?=jF)}S)Vnu^yH-rmoJ{5T#)72V3>ZRX;{OoaUnK8Lyn$7-4S zd=J&S|F(I{{Qd_P*R*_Ud2zM#Nqxg@?=9~~+4baR{gLIbJ@E%_?#b`@D7=O?{hiBi zedcRejXiEZ^4RzC$FaiT*rUO*VnXR?}_#G-XL~rlAwJ-NpG1RmbZN5EpYp4+IwW7U+XulQhe>iYz zGx}DJ-wH+_20Mz)?SQcjXs#)+%uLt zQw%lSJfAm@q3P&8fN(aHD{Gn1e6^SmNfnh~jRx^LA<(Oh~TaH-? z6dRlJzLJNE9021(&4pl>73^9+vl;Av$n`&id8bep{^5Xua4aOdC4mozn;L*1_+f?x?YoDqgp~D4eAWkco_daT75w3}$NyBQO1o5+H+jiF3#bvX zQXuP7_nLev;?`DkDd>(3@lpt6!VQdF*#mrJY_N}SGYK==Jm@Cv}YJs}WUZED~ScBLPQ28R#qzr}#f+{am1D&8v zrR0PGaj+cobtmX24T#>`!aa$ou8*(8T?l5fC<)p$iK7*Gfl7CB-R4)*U&38{6TL zD+vgP+*x)ajYY&lhFv(k-(f(^b=@?F$IBKJCwV#>U2>Vs>|Nd)`{p&OH2#S{0jgFx6g2SNgdHK zJL+N`m?;Nl0@z_~J|4#_6^~;IcNdQ%e0Xd+fbhj_X)l>Bp@y{0$=Brs!pGI-kfs?+ zEfDJm6aW}XWt|BgwY>xz#+RI2c#5G?jCqRv?Nfa9!dKCRMl5-XFM+WGb`+x;cOv3s zT6Ki4Pc}bYF4}BbOJhNTfzf`bMEKy@0e}X`&@u8t7#r9jjClZAJBZF#2G`&bQ1c~Kf zYIV{B?1*Z?T~@meYe*v9D5EqiuBe(JP7$GLB+DS^Xh_J4f(r=yD};jq!v2WhF#vO2 znBEzM0a4MhbxVK}S-)PuqTn|0$IQ+2XNbc-s zzCgj(V)zG}cVw#i!LA}&r#m2FUuJf09Ji40HDU!nh%qcysiexhl6w0Z~9Gs7Od6jmG|Hg zz%$LjlLhx0)UC+y0Kop0vBJr6#!CKP{A{vgJW+T;h*rnoQea8td5or3x&d-9I${;lL}p@9G(TJA=OS`-xYS8c!ND6iPB>>qr_1sj03#_zZm`W{~#ga3QHDIHw~#qX@?axR0ilq+zpwBJ997@HLe@Z6b`5VgYmsw_y{;b(@n! zL$o7gNO28ZK1xd9emU%TZ4bHN5=(5q1QGBWcyeTW2nl{WgW`nL@$MqmTJm#TAqH&- z|Nag>z20$!0ZMr3A8!2M#>V1i$I0d4Eni^yMzQOKyF+(|{_(4YuH#nM@y)JR^4wOW z0nT}dIytm_VXLLH(9&zQ^!~P`FCWZtIT`z-8~Gb+#^Xr$hUe!kR`07@p{5eY`J0Oe zd+zSLvu|Vge#7R$uUMf2xl_5tweBZPEo=VokLB=nvbnp^^rF@D;s&=NZ#Esf|Blu4 zO3uF(Y+B812HT1~eH)|eW4Q}!BacD{OYKzaOQlY#y}!`*veowTZ`;0N@vS*7pUSpV4d+)*FKIT__{^1jzUmd66AEU=&txgQ~8jERon?QJ%+8!v#Itjq#hm;B| z(Vd4BPsT_pI(hMMwn2FO%Ei(6@Y&JfuYYaqjO{D$V1)gJ&0iodXQBeHHwJQ|BYqh` z@8TbhWVY{Zcme?fZ1$A8XmcaUgh7_{Unqoc5oDol{Tv ze@_K|Pc?o@?faDK_#f(}PbmTDEtdPv8{c~4Q%?A!cZeQXKXv!qopT%doeL!jiXUg6 z;jCoRXJ|TBjI@X)NG9o<;6dIn2yn(9A(|KH~Sb^bx(KVSaM@&7vhAZ5Mr&gYm<#`OO@@hQgu literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/jinja2/__pycache__/defaults.cpython-312.pyc b/backend/venv/Lib/site-packages/jinja2/__pycache__/defaults.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3f19acc357effca9f01abe4e5cc800adb4a57af8 GIT binary patch literal 1619 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�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 literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/jinja2/__pycache__/filters.cpython-312.pyc b/backend/venv/Lib/site-packages/jinja2/__pycache__/filters.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f9c2fe8f5f0d44747780e89d9d3c760880d0dd49 GIT binary patch literal 72282 zcmdSC3w%`9c`rI|jWm)*=!L{{&;v;z#=OBYV2d{xgKfYM86pkZTVg<(k@t)MiIF2? zr;!XTB6flt<3?_r1{bFxP1@M)={ct7^qlne_S_L7L7sAYN#ono+}nE(j(l3%?YTYw z?^|m>MjBzTo%D2m(w;SYuf3k%`quYef1a0@W5eg?AO6?FZ(g_Aenvm^PoYdqR4lOB z&f64QlTEQJjt+a1oxdGT4*qsFIr-bwD;DVPG@!Gb>=tabJ~lvzsb+(Y@`dC3XslGd>u173!4f#or`o)QxT{0kS=a2 z=5#*NB~2xq_IH$a&TN{=>4J{3&hn;mPS5C=)j7LqHm3`bp3^jk(?v+nZJNvJVx;Fa z&Es?l(({|YC~}J-cI3=i;WtcALYt&8EzG-loh|tByQjmZ+yLIYp{ziG%7spx-yY zm3g@T1@pI_Qs(1+i~h^}ZgZ65$D4sm4sow(*|a4uxMY`kmQS0f!pO5isZ>`eRqBd1 zms0(_t7&DnE!(F2Tv@2pD79$I5wi_?3U@p7wE3;BQP+xAQcIP(Y2VGz>&$&_w`aa@ zsb$f$wX~Qm(^K58D!lPIwV*9WS^T`a>0XT2|NXCIyzajDaeeg6@65A8qbp{n&8yU7 zT<%krOglTD3_sM;%yoa_yMW{%AbFiqsoVp|_T%?b{9X@8pAK@}M-pcL^b{caHfs^j zp3!rf-?-av{?b#oFNsIaDWP)>TDuIbZB*wmTrF2tC@a-9$}0S?#y_y=r+D-%cXksl#Vr0Ek8!4!8Ka?WMk}@`Ta|6xn(1J_-y8!y zr5a`Mh~_BUvG(?;b7kHCFJq=kWe1l`wR{$=UZw18%T*qiO(->;h(e z$Wq5682du?5q+F_O!fM9^T>U+K2d#pEcHEV^yOjYkY{FtrFw4b<-TsB*!r_hrYJ#BtdoA0)d5_5h&J#Dh|^hxD? z%*q<&DRnL5G>>usGt#7E1BnxUp&WePW$X}7@#s8d9UYMmb2y=V!IJa9q;ft`nk`Qc zs&kb8t{k%5`GWHI)9x;7)Mn6&V%KYB_*v8DQ53Ych2P0A(%d7LqGBb5rp3l>dOw;D z2{@E}{s#$-Ym|1(*7Q5*VYDSYO^!7TpGR){^yoBCGp_QexY*v)F6QV!PZ^*MfdIiJ3pF{NuFnu?THR zFyyZVF6zT5gq44~P3~quR5PIN8RR^Id~1|1q8FJUuYa2Rf^K*g?K%n`fJ!)Z+i{@$ z9_2aI*CDA>qRXDg`<<9=l%RY``8D+5%gTUKr3|7MFCcG(S7<~Z6Pa_j$T>}Y8T%n1 zjmtf4nTMz>affmyt?pk(-Cc~!{|EZkto#O^o>hi;)V#_$Jbjuu;je%bei7|>&%}y) z%HV`!0(zAH-`HCT$7h0SgO611p1UL3qe^)R`|VdP{fqPX#m(_UfAx0k=Dp^Z*N(4Q z+R-h?;GcO6&VwfVEc@KB#JU$=xZk2_X#t>aAVf@bxVE6hwO?? zc?A%Bf@?mZ*Nppi<$`55=;8Gt__0@!zgPaI74Vz*eNuHD`A~-&^V^c^8dJVnmQ|Iz*{}x)&V)jZ;Dc=OnAPy>1E#;Zt z5p4r*c-_*^XEKk6(xQZT1n!OoqgLHLF3db88T-v+oU44x(t|Hf(}Ve#(ciw{_>?`V zMNjS?kI;CJL4xeV7+!arU6@4iUGUSTJu6@^aD{kEgQxQEDvl27TF=To=yyOz?P<90sxIkoe$rR3*7b34ChDeX(#&M$pV z?fgAU$-nlQ+xdM_>{t{Cev4vT&w_zM$tdzcbf%dkqnK^FvTzr~d_d@fO#58mu6)+{{oF?exHVt-BlPIkWsd|F{ny;1 z@1RHj20i+Xuub`6_3VpwXwsg+_1~&pxc)nJ7q0K9O}MU6hj87XK8EWezFtxHApIw5 zKCb_sum3@9LAp~tfa{;CM{xa*>Uv!NlX?`_AF16h+ELH%s|tSonHt9Re^Z~t_0QFV zxIWD_{O@WH(tn|D#`Qm|TXFqA)P7u(>ONdY)&00$RYSOrsb9eLn)*DhKUN2D{fW8} z*KKOwi}r6(P1n_@@q1kD#r0kF6s{@t*KqwyHHzyE^9v){#W%d)ugtm52}O8-(GNj%ieUZ$5HEq zTD*77#_n)Od`UPGh^w7l9ig}yXu}Oviv_x4suDOJjvo%h537NemPAWSAljvBp?Fja z{+yP@?mBzQ89LO8ul#m39*W1c<`}-hbjRI#I24W`k=3q6ySoncAn8$Kt)VXU4Wu3l zX-B)eaL*fyw#D(9_H$Cx<3?U6))Q%MJ{Ho#p-3DzazfqlXmcoxR++z!lhxO#$$D&XI0jEb_%WbximL^%{ap(>U)T4}8HkF2t=$^d~?>cZ?RgbPZ zphaU{9jgu;3bh_pBg%ne7`6ku!iNsTFl$S?a5vPh#ts|_M~;M+-yxVhK)=)=5zEKrdD|_AJ$uG*>jyS`iL8_>W#1aa%()LmyCX`<{$R@f zSjvrQ>sGZ2JWd-J)XY!J1{kFKHBYU7ljKSw-z%KVOd^>o5^#HXjt zZ=I*s%iC*9*!E)G^q$xn)o9TMLa{(7&=rlvyR>Ml8jImJ05s6h)*WeWXz2_cRhwz4 zV#Q)bwFCnIzhkNvj|DJl;YfQdCxA~p8t8}~SGCpSHy8DWU0Z=)0=#%WQoe9|B&w;+REySt zhs!7f%~!we1CPyHI8=S1=vvm?8~%c`#|DqR6dEr1#_X48zcP2sUz7CK-1HUn@8UU2 z`78@nn}Y&U+0@DKq3*bv@>xbBl?6-?>h6fQ67cJvv?=_u?aPiYJHPBsn@YP*q`m-i zF>_jvSWA(mDURDeZ*vVe2W$iG0SAO)&gXOcTnQJZ(AE1lkMdfj`D+bzbc7Cds6f7< zIHn?c6d1XSQE@vKVI*MmF3_e$I|Ct}H9}9o+R;Nt)YiC(yfrKm%v>A4ZW*XxAh0=# zi4SR*;|`i6MW6goD}jz#3%_pE8N-`9fGFDm3SA+B9qb@oq4;4gi_4%UqbX=J;4v)n z#)AAPuPh2I*P z7uI>S2k@10QJ=L9bo)N~?dCDi)*~IGB^?O#<0C*k$6RZ@m6H}PNMOBowXu!uS1RW}C?$T5=Rjhwr8qK2Rt5ILd*%;|T z52;7mI=WDQL@&2cYBMg}y%tadfd@qQ{FAz*ZAUIz$+0!K{3DiesV%R1WM59W-CtR2+UZ0-y z)oHFceX6y>g#CztYVof8D8@?eb4HvAd%L~QnQ(5loprT3+HI|lgLwcrS3FD4pK$5m zan5nZ??R3~*9#u3aRX5w$U( z=lYM^>fE6>Fcf!zFj}LXouNRC003m3Sm@@0mRJOf`0g+WFX+iggm#aN2t*CF9yW1` ziA1;*2E{Z)!gwzO65;IoK$Y@_EVm})JJiD%PHa{9Z6MJwp;RIf2?>I{(?YFNhCmbs z6vd@)IS~RqEU>0AN)3SuN-wLY>+*_v`7;=fL{x2AaH+U2el8C#MFutADsi5@o^i)i ztVf{DSZ@T0uR6(cx!rEk5QABlBzEcrF!$L_{ANA@mb}MiI{;dv&jDZt_!2-LgtVd0 zJ?P1_2okP@TVE)Bt}~^;hF->oUK8ADTT0jy4#EXzmbrjy_u6#a=DGxnq4r`l`Ti_YODFSb1BSnM<<4!@X5!UIgV+7NQ z4LfWhTQXrz628Wc-~!A!KBHvFbD?N>|0}ab3n~ZP?=4t#an(;2EE~<8JJ2}r%y>!p zz}BCYEgW)BA4ne?7fz?V0_hvA2xrl`JKIE zt9A^!Z_b!CNgjB zxB89h*Vg}o4YzIu1Y-W^7uB}B`SnlDc9#2=6dasfr~7I63i#^C_w1QwcsQ|-X1 zj@>DHu+D8xr$#fB$_mGnaCn<#Q$vM>c zlIP;G(SrKR(NX`_q<8Dh+=7AC{SSTg3%9Lco1F*#VpU_ItG6T`+#d-?BTs?Gt`A7w z>0sJS(0KBm`2rGYyCs|)^u@1LnFu8_EerBUGBLLs@jjb5;&Fp*F-a?Z4nXHRdpB)~ zfFo&D1H_>QSSSF-1KYvA!@$(X!yO#~@Ggfy|MmowXg86;LUI5c4XFTr$AW^tTY#>C z|HwKViV-A=B}bHpcuXL|42gCxQdZ6*Ux_wz8$`j{K|DWAc~;`mZ+kB*f1rEl2-eb# zf*I#M=R89_Bh_OCwbu(UJIlrjRsf~=X1r86q`tUl%r`gbnk#4)327+9W^>`6$N#U9 zNFV>H)JklYiSn(4YbF*^pO2Uo$_*lR(pod93;iu^2G$yAoXH=3?ey6r4s0PXS2*II zoCl5!j_0uvY_{pSt@9dM0YG_#q#pq#6b~`iNen4?gHT}qqq~?x2!IuR8eDV_cvVb# zVE?|YOV-LwcVj3PZVepQLS2wEfh!^2TjyILOz8+83W7+8sX-R8v;>YH1|uZdp&VdL z$-&lB9g^KmdksI-NNZG4TexkZfD#6qgv{8NGy*Hxjs~KUIt4+{5ZFw80Y$@=1_O<< z76GS+RB>NHSsIwGjvnOTworQ}mrvwJOH1uhwWnT`Uf0rsQ3*rb#!!#ajzmdJ#Z0_W zj2JJ$p35daZt1$w?TULU0$4ziXk0cbh!wW)VGw;9IQ&>3uBl)qDHk|;F1@09`PPbn z`gC^~q!eUaSa3Qg7YyuZ3-m<00}&PN;m#|8SVt&!SdG=QpaGHqE(Eec@D&}QR<#yo zgDRpzsb@maBU>B{2B;ChSs_JHm4=4E^57bNKV@H-hPY_elB8hb04@*O?7WQ}tdbOt zz0YA;Dv*A?X&|##0G^g-j`U}*I=^N=Z@1gdEOgm=oZoRCx7WG$LB`_&9%z0V1k3u} z8WG;$lpMjODf`is{aB0^FeXwkJK5{n)rfkcOWV*pANa!nCzBd6GJFT`#i$d1OXSEc zo1@tC?w);D;_p2DqXlQ~9eQLqe$7{v%&8uE%H`!p3XfjepktQH(Ih zsYUhnINdg>fPE;q~v2IVPTx)YRB9dOje~ff8ARVeq zNz3a^m)$>z{V?&p#I@?pH~eM8C1d{iN$-5xzp5`3U(1>|zHIdmXMb<@_veDL01f26 z>B~R6c5vf|B zZ?*3J1`V+R_!KmRs~-YRkfSzg_~cJ4XzpO2Bi})e^2}E04yEP36QgS_kSoa};b9j}?B`$RWA)tlh zfoMbxV$&w2fd=L(B*pH8gn%3-6~L0L*x_h*2RJnqTpObdrCwxJA$eEy7v(dOx=Z9H zxF}#GDmU5{Cp6N5A7Kr+Qm?k9g<%Pp2MyqT0b4-?IE`N7CUQ^AY}PK55KM1VgJ1%I zvSQJ05Gu510AaEGT08!}zKXEYDP+cq*>qeXjE7|BMgQLnNssg^8qj zm|@A1ebxxsYD_Q@$p9+&DBU2YO6#Nx@flha7p6kF69Oy3z`9v4B#!65M|qyZ1$Ymb zC9l74yr7WqMA3EMysN%>H~fV|%T6CV`^?}o7g|RuUpf4y^WvsU-pkcv{hu*2HJ-lj zx^K>?Z_b!+UeY!1SJweU+^=^)TZ=|%$8oU|&eV9$s-47>zoaZZbXkN;+AdC;SS9`^ z-o!=h;+DNRlV-%;W08A&8X_17S5Dz6`|Y(STfhRH#58}+ao+K3ZZ~L*9{U>G88=e} z&d?qZvO3C)2=5`a34)L1K~` z2wYk_DCJHfgQK%|tcw_pYv0llf z7YXeyIRqK`Q6OK^6E2>Ff!8S=8@LuiM<=V9syB&iYH4RrGto$54g%HbNO+wR-vA_z zHzuR!b&5hy#13ge-KYclO;V>>iduIMHG|tRmB?KYT*gm!_ttE}pz?ME#R5%YrzHJ_ z0!JSM=+gw%M;ZqWFbV<0LjtB!+54b(W2H8ecvHAqTAU108i^rp;y*@O3Z_9nSR|;t z@@rX@gA`d`RZ=u&rFszj^%GmdN99Qx!X!{Y-hB=tlk=F{D5G9Vm+o zIsUWxCMBiV6RuYruUZj@GZS|lH+W&Q9A-Dn`|e8;`QX0uRiidA9BnR};yNS>U zX|_I3!l7j)Jepf^B|M}6!yVfZ8v02e$hK&=;7`J%*NNO7>`m^_tH8UPh|eRnZD8-V zhj!ib1cWSxBv$8M4`Hj~pj z2Q&r!Eq)kS3U??QK>l5Qky0(^y>%pxyZgtg1*gSL#r8ilj~44d_6@;zv3 zEZPxPy1~x2v~0l7b{;ov2{2eB5QA=-B?&Dp>+uXcGBkBuns_4W3xzv~cZZb>;Wr*H zUZ22qfk)N$kfuObC3UZ1!8gl3ilPKL98qa!v2={OMO1~QQ{0wLj1=Y5)i@YP;HWUf zEmEVyRIZ6Z)5zD17__?scovCrpas8nCO0rh`F2%Tpoi?&;Ps=c8&2GJaMh$D*`3 z@SYMrO8ZGTHVr{eJu)fhb=c~-AL}b*FCY$4)>m)?S1zyk#5Od>c%N*g*;i>*q{A_` zJGBew-vA?8F+kp6Qm{Gd>xhR5J1+f}JF&h=1K#wWbw?O3C{s+ZJ}h%mv9;62-3D0G zrBUXd0+XspJBv=Rs{~gX6Y?NI3j^V&1ZxI%qc~pYSZLBDz=S3#ze#V#3gbPq8NA5Y z7J!9OMnN>^z12G+46^~0!-_as5EcYQMm!CHUdQ^1lpTM8I-l6=Sjj>N5!OBgRn1r= zU_4Tum>SYr52td>)tB;+2r;4vekP1}G>tB_EkF&!oXxXz;}l(3e&R%FEIdg$v|};i zgQ&6im`sj@X6+0fI)UqB7m)yy^RV5P=kMQgvvlV9_H*rD3lHYNzGMHmuV7&Pg`Fea zZ-%eUSv#Iv{GM+n7@$$#yy4iGuQKVo=SJb2G}N|f0|Wr z?$PnQf}!PuPYgJ2X8EsY&AOU3>qcJD(8kkExZ}&~-!YXyr~R1s+J4 z&&vm18#qMfrxuL*7SNcxDtQ=s^J<@3av)ZF^1xH;4lb^1mHRf{vcXedj!F^4wX1oMHkHKXiU!IjvyxUcvJ(zCQWe4rh&_{X+B(bgXX1G3KJEoulbPL4xKv6Xl8XPRyk|pn6K83 z(Oblu0z_Cm@c`0k(oQ0Sxpx{#IUgjDP?5k=1xVzdT{E}_LWc5X*UMIqmaYE5iFfSZ zKY6We(}dfVo%7SOO+&7C{YAIjw!9fbGX}SveQ5BZ(|d-Mk!2&xhYx=v@^WNsUT`co zI9|5teR^TS=^;_4$L;y(7Y_Vp>ByT)8!Nr3d>Y*5m>PiUEw|03AtPY_5nA{RJ~;LW|4^A7OG){;CwUNl*rcQ zgy1M|+ZzQeN(~O#C-#I@$Q7-s6~SEv0}uCr(~Ph#h8WEr+L9Q6K}TWZp)D9NhkciL z?+EqE5q=GE+(yF4V$I(w3uFB=kqHY5}0s z!td5!g0+zg>&!0xgEcU$qN?I_buAYXY|)qHYS zIbVk1rE$?-z!DI6iWMt_ta|I81fUR+$jm%X7UoDYM!cv=rzn^8G*&;f@fP8Kq8^v8 zI>=CBkfVRV*3kjQuCXOq)di*nj-9P#>s+FAZrV#IDCLBuE31zJFhP_`D{5df8UOaq z176f&&eT~M&yNwJoQGndu^KNZ9@={@8)hT^xi^aEkGRK*7Y=NJXh0ghyx|Z-^EG4# z@+RJvmG3F{zHW$(gxQOSidGdSu#m}UruJ3JPOoZTr_0N@2*b%1jQIni-9AfWwckXJ zC#ZRZ@IL|~58Avr1N%>%9MAU;I>)np1IJ&O%jx&>7bGhl9?O3u>3!su%LB_6`!}*) z&U)ScZTD;L*Ps4&_iNoFxua!E2xXW2V8IWozgPYDl>DH;2ElUm`NiiJzqn-N$+xnu z`5s8R9$m#w;1vklW0$40W%|~)-XvG zBLRGe)mVaxn2aE-Tw9tDj4`QHm`m)?5a6~dVEI9V6D2^#;c5ut2C(J&O~D1qH`8~@ zh5)O#sU7sTP(p#c;D#~TK?-bPpw9KvQf2gL^2KSz8`6(SB@07ou;-fC9zelZIgzMl zlnx9`+XA=X5On+`%YzgGa?UvICqhKpLF{TvO9d3%8o2%-jcWxY0Y)kG7Iq!e7SU)} z4CaaQ<#x56SRj6p-`qz`BFzaHL(pKD`+DL{NyN(R73eImg}jkzDj06i8gfUAws8Tf zkmHh44x(8Yf`ZqCNexLfNPUN5$;J%4H&;O@BuoH?{-Wq`gv+1?V4!FpZEJ(97~7d<-ujJWiI+Kg!LhWUhIw-r>6dy9sieEXU2 zJeb`3_y#S28VVKD=AJpNG1L!Xuq4PGfOxV zj@#@aE^`;r*+z)YVXQ^AGkqQhMBo;IaaJNL;XY=EM?^uweZ*i{QL+3a49jD?E#a}) z&e)}v>@P3|f}138ms1XTZW#7TQl!kP4O%e5N{bmE)6NR>ecRpXWZLOzQ#UWgw-V>V0H1fMQsRtBV39pii^w?PL3_NgJHp*o1Eu=?%e}U|S?9J@ru* zWh}6Uz*csFlukfWE+{+6q%Ne3KwKi8Hy<%m-7KuGW zOd@U_GNnAijf^}8)rg=*iDZtE!iSniAF+J$*{u_6NVG-!9preMR?#C!2n|)OEr0H$ zb(HVv-%9Jqe|lB_=AXgd$n|c1@zB209Rp4n9t|lk+z;o#v)c!^5A8kk(0F0#>7DQU zY%@wfishixQ_CCk?7v@z%g2j!d)aufks4wl=U{+hrS8&KB(cKJ;eTQmE>l;eMJZ*N z?>uKyY*M%EB;9ht0X2_Y<$G<=GUw3x5tj509tN!dg}>p-G{BOW*9S4%9KYYiJ1H8! zIwZvS<=b*+Vf-$vyXYR99lTx=yqy0|HVm?)E!KER@Z*VGP#`aD(% zfFzJ<*7ySg*=8Y-vw*xDal>jg;b{k%tXo$lvOq4AED4{zz@Mgeu*#+t19{mpp*PbH zsMYZ#-aBqP;e66YMuAY(?uG+PJJdn#q*!5G2I><86In+=Mi3L4_#m$rY&8V(by@7! zrlnjk5satu_QFS&p^UWW@C?=m&|F*^q5HITbs0A_b1!nh=G@J=M*Ak7WLQ+bX6W9V zVZYcJI-&g`^85`!#M4M%U&^=T0XHP01@k8@G}^G< z$3iQ3$vxCP)IO|@6;xdGUh^$Wx|V(TL7pwQ{1-Mm3K{p$y6&$U^;adUcaQn^T=nj` z<)r%`$A|~~bzh^?cEvfXG2py1-;QhA_C}kG6aNzsUZq0|Y>G|U5ib}T8+^##CWLVM za-$K%S0^A<1%Uxn+bJBE2=VIkV-gdew7D#UAys`~#lZvyak2#f_Ksy@llY|~>uoRv zpvF&j*`yXRwiYs3ke!ooHH4ou-zg_@YHV#vD8@v$9$*T3^vAgSF~)B~3dJknA~zK%V-6A} z3CHnJ3tor5oS;y21i)rsE37dg{1-Y*&Lw>WW#hz4LOaY>LC3@3i_OxcYE;(>Pov45 zESNY+mOJ`830YMwX{Ys@#EOwQfHaSSpbyj^lSItXvc@9X9fvhRdShBzEQNrZk*Zpw zSYUT9MV1S-JNlw=r&?NW*8o!aV;prUvLFay7)VkA;c_l?w0cdF9VgT1ZZg*Zp~#|3 zE`d#^;!!RHBp7#LilP{Aw2)M_<&Fonrp6pgnj#@uF?Tf3*g{OJk7Z_-Y?-iW0=C%^ zhv+F1Jx&1!OsPRM(iU#-1}#l>G_X#-q2(E##2`Le zXpl%&!3DR-VbvWCNLO`~M+}95SC0VoVD~npA0(tOu&5k;(g#TE5DU=rIuKxhq9h~0 zVgYV2z$!p=FUbhN0XM*O&+MMjSYZbuC~IJALwyZ)l!@p+!GhKPJuc}^24qevJEr|9 zo>l-S#O5M_9euTF!u3Yh+wO7yoTPV-83iE?g&U;Vd%($%FFT(Nm{Mg6L1xS3_63Sn z5>${s%M{GgZJFGWVzm}R&M>4pLZb3XA4~njAMnR4{}S3s9~j-6gdS8~di}9>ixHMd zUP5^aWfBn|{4wR_;Cm~i37H$jrdg)PEE6g;C;VSaEIlwxsz?$`JkFUa_`bTd+<1|! z0;H(k);bhD{A_z_&^4C^D>&VaadEl_*iE5a@&~%B=W=gxk;waqNvd?ghy|V+qj%$TzIA%o=(| z5>U(5W};&jcCiyxx_rz)a8^0pBJkhIGxuyHLv8`Ajc1pDl#3)Q z+Cy}c=y%q^>ozou$DXCTEDRv-RM`2!RaQB{;()29G`YGUfO@U{Io{p`u#Jr&0maT* zn|DSsYtD^=qL=oJY`2kTXkc_o8M8#3U&>+;Z&PjobE^fW7P{QF2qK*ymJ4T ze{s^gm@GevhL*v9(+B^};-UR7!vA?3!8EepE3X(?^^@|t!5ssehKg_aONZjaP1pRj z<8uP%vfrB<7%6_`$szYp>sN9RP-E7j_YqK|rD60Q3A8Jp+w5ML3!v z^>iQbFNr6loyqJ`-|P#UUiV(C9-FgtjCrT2wDm7tq(DQ;A_Yitj#4^(nkI=9NUX^- z@fXP2M>A1{gdtEU8}`1LdwKs@?S0oP?tAMIon=T?-1o8eU1UtTkB61`;a0q8e25-p znshZ1=`^X1t}^*pSdk+F8U;5&$-r)lCS^*Vq;0I}r`0Bpn6Ug1fJ;HtDJr^JncHai-im(nX$!!H@+( z(|!J!ebIaTIY=fPy;Tys6WSI+NalfgFbtgiaRtN|=F^Ol3xLM&qoLXl=<)}2`5`XQ z>JlCxso&FSgO;bSSs{)12{N6bfx8z8EZQ8W`$78+f6+^uhl^g^ar%o%@4OFh_{vCP z@Ss&^Qw0zNemu@#DHZ{MWwc{&0697J^Ko08W6cq^mF*1_zEsU@@5@sbAU5} z(j~k@A43-BJkPQ?mcO|^tB8o@-;UiHp)3p}Q5LD}=H?Iyeh`eTkVHSGl#%2=Ji6L7 zWK0`YGE@>Hn!=;=G@{#(;Kg^#%Y#}nf5iD>Gh}(ACBdh*7ie!_hGG30Uv>7+k_hq*!8O_IwwdjHk}{jgV-0-$u@7cAgz zIHALHTi1{hV<4C>a^Pj>8HBJRGY+Evb(pp{_kLX{BLAru^UysxtZ zd;&5lnAmY-#M&C(%CX0|t>9&|VwZdFq`J0SHvAslv? zz#=4zo$0UerTrL}G;BaSlPEy@8J_)+rsx4AFhw4xdmpB#{PU&@j1!96-_t%g5>yt|!9rN$K>fK9ov`?R-;+eMdRU4dtY~SEac@BZG)_T%r zhd45x9US^O&8FQ4v5^Lj48nPeGel`8(ufj-lp84zr?Qapaw;3C98UR=%H>oZQu&R@;(cV)`V&J0~11;aets0yXoNP*7b%2YKf?}(KPdeuZt*Kin z?M3%`(Z{|ll$%B6Li1Tn8dZv`l*sD!0rkv$#if)bJg?YZ#a?6wCkoC_=J=u|#}_#V zIIi;E54W<@gGI!|b{wHV&Ef9OP-F=-dJ2g!YOo>0q#{O!(zRhStX;MuaCD;(o2?8k z3p}*3KCo=*^1#NPIK@{$;HWwTM0pryiIR`PcWW4uZ}LKD3!i|w1}Q7SBf#qMAt)+D zQQN{uaoDLk7>Nj}-W0hJm^PLvL4352#7EqE0TMaHC1tGPP`Ey@Eqo|kCnOqSjEyb) zw}6o+Lw?*YzFw6MMH7zN&I521PT-;^xne_#OtKtOS#CqDdpAs zq3xk(9`Q5ff&wz0L6=A> z<(C&+-gVf9FBa>k;I3odTGxHjoune?s{RIU`j zpsxZIFghs1kIXbY>1KL^4{MNw^#EoN94SCP03t$9FtA@ZpOUg!Q4e*u!=$@CsF50C zir*q(zAi37`)54=DGfOhhvX7nIJD~YhNP>Uo7h|Sh1#bM91kvDa`5Ex`o4zRd+JUu ztzX_(SCz_#hP;zva=?G76N)o$B-$3Gpq42Q?A9T!OF3a3mCEDrZ_Tk*81{l!B?3qP z7{ty^#(>yi^e2|@OgmLymIVvBPuOF?9dI15mMu%r=~A66>hmU?2*~5jxNjM_4!fN< zlVm87rLfKD-PDMdxjw$`;3_#=zm>?*YeViFfUYmJ6!hpON#r3skr03ZJRtA|!Pg2}@F<~f5NMI3dR#zh zEyqUWu!e4pwnqr1a~2X5lZO|ud>j&eko_Ps_s3vm*8%fwc!nd?Z4TjAvcS_+MDU4` zsh+?!U|B&`bVF1}mP`SPkF7+HM^N%14O=ykIo*c*4H-otOkzl7=i?x7**dSK<#0US z)o>5I8_BDYe#DGl$B!Qmiu-WU=!i!f=m$x~$z?;@u?f>f1lS7fqHYVS837Z+=wf@I z3ueT!Z-H6}`od8Kn-yDs(RW9b90s|0WMUWrn;KJNbzBEDS8NNKRs;fyv#UsYZaGZG z@S=eyT06S=b>e(2MFay|sO@C?MJAWn71_oS_A$sWM*A=-#x}}g1F>n6+Q?FPEukn? z1bh^`D0D<(fMl@`$frT{^#0b?^%OD~2+VmnN$Ey9tdMN%9hSY1mLB4-5h4&Fr4b+;Bxo1AACtecjt&{0 zSk|Of%SXo6dIJPp8pud*PT(==(;V3GuvrSUs~j!d7;g*GU;F8Kl z&qV-f_~0@q2g43+*7=6^)uiSf{K@iNi%v428FFt=ZT{cPEFf90sZQZTUn z+adlR+WVC!hc{j?t{yF}CW%BrZU2s+X8FgxGtTA>=0UdaU2xNtcimMy>M9;OJe(LU zt-o5j{IcVE$-Sc`_l}j^cg?kK9B#6;gS9WM9XmE?Ql&&7tz>vR?6+v|Rgq>L07qVC}ig(4w z8c@f0r_>}|&2YjmSjkx_nJ!r&gJ84Q3Hjor%l^IhH}PH--3hM>gF) zClQmG2w%mBbq12uqXn2CbY*JEKvo+B6wiB!D4kqCiv*}YaJbRjgD{7tJNSi2+lZt= zR#S$2$Qn0ISFBRh2aafs%@b-(hCteP z%tz>)5V6_BwAZ+))4V3)5pg%}a1Uu|;a*^mGkga`!*BCG91_e8b0e*jJ03a0L61V+ z4WeA^HDZvtt7rrGLOv&k2Cbz<-W9!Pl%BHZu=8K5v5Ej7PW+R^VPYvRU$qO>M8d{# zQlT-H((*74sVqePqfCtKakd8mu~vvDR+-8J zCe{}%*JdKez0}q}MsXiPm|}@K3Ek{q_RZp%!`0^=9LTVfPVg=NDtU%Y1^>!!;+F!R}6{f$4(${o)y8O|QfUvNFIW;CznqW!zMZ{%Le zAIn=a=(vg4y}9RdU(AR0H?Q#QlY>tVJ$?GXfa9mWg7Mt^p_<`s-`Mr?E(ELO5rd(0 zT|R!y%||TDBD&<|4{Utj3jxh|Ug>b*;1{f+6jDymj46*Gy;Ipo5ww_G*AdwgK5uki zJs#?5H8dXRGo@*6CxRFW805J7{h37!A{qc;C5zzGz{5umU<^xlBF0drrx1%mhzbFw zaiBdyp}7?|zm=dv__xHfl!$~)R>Zsz z(;P$4voM%H5%88MPYbrQ(0NlR`<9mFt5!*)K0+QsjLO*Dd<_+VY$PG7kfO?nFKm6t z?qqn8v?1WObT%!p2c@w=A(y2aSc1cAMYtet9IJi^oYObNb1#01M1+)GNVpOe0it^kT)2A=}H4cPiylNQoh#{pwbdW#G z?L#z(<8d0J6AbL-O-VB4>@H1V?yyNxpX40LQyb#2ZH4xuRqU6YK+Wi?bQ=<0`fZ5C ziPj+J*ABW z#zeO(qdu^YUG1kjCCRt$qOfJlrfX4J5ALvO%V0XSl_Cs54~a%V9l7*&#dABk=zW+q zouw8SPS{z350t?HC9?}SjRjUQS4Kd)6f*?wQw`uaCN4;B{v?EvrlLxqy#u~o5S5Aj zcXzK}pN^oYs<%i4Fa-2S$l0(y(CeuWw39f8^#rplISBs-kYlOL@Fn0TRxx1XCH6(z zg&WY=@umlZrZT$6`&~JuX3=FfUFP6I$Eb09Dw65a+~Xs5IC4|h8>$76HB5Wl6=VZv z^MKvv%_mNy`23u6bCUDGZY%}6fynWDVJPv$Rf-({P;$Y_AMAar==)Dx-uYJBJCD7y zJvslOG2Hge9rw)`dgO)slCJg1St~C;c6ocUZ2g#P{lIF~mH^RH$F z#{C5YUW5U{cXCG6(CQ1DMx3u~A1$g%`l~NGN7*RqW?p{MUoljAp>nwOmDv@Yt^A=rPaoIkWxBT+5(Y#gtTdC4bgX@y6nJjTn6&!*N>nLJ=A{vX>;c_TKyFj-3 zQ=FrBxTlLGnrT}e1;^tp?Qyj5IJFyi$!CrY)X2 zCZH4IQ{I1QJlSfKxixFYGs^=TNHp5eVlh+?%85fXAK?UcdzWR?KK}MoPqKd6&g8V~ zEt@jonT1!DS|H?=n`%pom_BoOL75m^rnxyzkxJ^(_-Xd6#hJsIUJ&JDth;+Ff<+UL zfJ69Bbb-5VMvQ`3s!+y+ZidVhI#~({sx82>(kgMGgB*#Zp~6!IlLuD_uZoZ_<)R$A zkDSSka6uJ%X<7}XX5eCFK`aQG@D>%MEkd4`2|+)H_V(K**4f;}H?v@HT0UM9xL&es zv}D;p4jrRbdiMUo`*9vw`K)i`zMOj@e`02CcFy~yI2vfkb*sddH}mYC!9C*zW#{wG z<&77YjnA4t9;hC#sUNRig}+;Qwi)v#Y*{l3|GP6gFaK6C-g}=)m~iHkGiE+Vi^6Y? z7Ik?^W0kkpdEofsRy5D}80yG}amy;Czp{`oMEo$*cIn7@9^w{&ov^bf*@TbiI%e2*YvU4*^i<3B$KT}V$5f*ANCp7pxv#fZo{$86C zrDj2i3){LUVG?EaHZ{CX?V(@Ci0SG`B9B?ggGmAM0zHp!I&M*C2pA0lS;}S1!9Yl^ zg9$iF$d^fDXy$SBD;Sie#Ky>|Mf@g3vev>1NkxFsb&}2?=A|siL>u(7s1i+Ki+D>3 zCQV3Y7lGPkpe7lXGV@Hj76oE>3XY1b*iX%yKFVIdBl@Y zG-6?ndp0b&C>S%Ds~43Hbq_0JMU~0i%J&c{f7R*Uq__OT8@VMf_2Ov9U)bF4*>LC0 zo{gL@br0`0bq-u zX&;@FXZ!UT3!EeN1x_5drXkF>=jd_zPTMSKUWnSB*o+H=OLi>}LTyVNG1Ce%P2^*s z#Dqgwa6ohkWQGmG5h}toHgQMu>}=+bYVE<<5<>6dwqbUx@l}HpSn>m&eK>RDCHf90FRT9 zg(i^jqIv#^&=3*^jf5e%XGEa3wUG*#c17X12|O&jPz~xwKmMFlm<<%kw}E;V6b2j? ziZCs1J&`%0F+?$u%s}r_pgK@{o9qH$55uG(WlZ{h{TCYME_{exvt&~;NG#-2>ea1 zQLJ)@Wg_8HgwG)&z!0qi!%FW}7Q%-yXAYrvgv^ja^RV&WN~{oV6)x#Glaz*{c5MwF zeoSkK+>`ok@7LmNy>p%$`3uH#cR_ON&%tp+**WC-Q%p`A!);%WTy%|^6b2tiuf@_3 z8Z8?7pZH9ED(m-x$>;)SCG1;h5Da@6=$b`{V?Z(FT>3_9lEjAFiksF*myS%<(ohf< z)x`{Cyp0T<+I@I}<2tAKtOQ1Vfsv9iUro|gGu4`ps2T3*ZzEx)B@<+CFVXd{`Ygaq zW@x%x8VJbQ+bBlX2x1?{Ap;C#lC^+sz!9(&Sgz)P(l8@hxzLSSPYKKtC*06fYisCI zM;F$95J;u6c><`4Ddvep*_u!3P^#H91MBhHT^|*A-B&Z}s~PjvC0%vGq|uMiD=<_f z@&)HPK6VhwbQq$*iZvU;6&h~ zASZlM!?w{p)Gf3XmF}f61h4?K!5_!9-I0)_NV}Y(KEa#8tv%rjNC4u{nSHFs0yeAV(Tl!+r-Mk z_|6j0o=!hm!t|}kLG(AbKf$n6yJAXQI7_g6@yZhHH#oGtD@gh}in5VbyjcMiOU28I zCWYEVO#hBB9i772`uf&k!!hIT(-uPwg^CPleR7ySaT);S5ueOCaoS4wm^^M}hX}X8 z0ryDaBy}{#=7UxsJOSItV?(Fq6p)7+@H|UmhRnrC9YGE_Xf~D=7NTGQMCe!I0C$5O z{t>DRg2qi@JD@Y>NdTR4#yh*%99kb3`WDh>!!M6t)^;F!C84GfG)%Z~*4upk zf$r0b`#0S{g!rP81|7iJ|(SkK}bl1$}ti@M-i^mbqE;RVyz}B1j#lyKHPmh+>UfeS}^S;si`v#oj z`8XnQ*f|iP&|JkyY)1!@tF~UP-U@q|vpWZO4)t8iU2rph#_8<$%WdTgKjHv;ry7?x zuC%9NF50V}!~euiTqa{Ki}ukVT@5Echj8*E6Jaxa>g0f1G)BTZR?;5E#HG_7M81nr zeGqT#rctdhMimmG@(YQJTgK)uzYc5rt#9oZ^KDJKw!-vYlI_Kn(ETs)p7&MSQ`sZ~ zWwA(FM@eYFDEb|vqkJ%q4G6Uc2-IadmYN5}Bt+JsvHL1-=OIb6o3KuTUl?qo6pdAUHmJvg;X_(O(#D1z5jBP}&7Bq2^Z zM5boM=L>wgLkKA#_!N!y|BH&^DIG; z_QBJ*2WC8Yg#)>os8Pq?8e*v!$eV|*b_LXQ3nPbOUH8FXFb&_Xi)&^HCWGi!Ai@y29C>^;TPB`I8NNG(zG0Th(v}eM5K= z)hg1dGLkep@jvm0xPVQEGu<(J8k=r7eZX!5iYa!6%e7)XSZQFL(Z?#=G$oM0eeyYI zJ0frSbA-69Ngq=}iRgMxZ~{c>p@p=_FJb8EW8A|YsF%yuapeB}C?C*Ft5hyC5>-l_ zy)j&D11AKE3}xm*(=9W|JOGx(`uGNFbv6kLkY$%}WkU{rTl%um3ycp)I3%V+uDvCA zrAACf4On*0gm8TzqJfXFfdlMXRr5|yZ)*gvdOg+pe$Ujyt53X93;6~}r!D5+mbkmh9EP;AKbXjuOLdRbt zTAn5(p|=qig>nk11i4CMc)_J3wm+!GHZcUGPKrWtZ%hk$u&_LibbtZ_!zvvSphT2k z3VX#TMThVZvH&TsMl|Gb7sq^wA4V_Q4+mQCcPB;IAcV$cX-^_Yf)LsvfQ4x0j5TZy)pRNV?>iKd8$1&>+!gB7w_!n`&#aE4C)bew*q% zLbz$tM};-Dxe zc>x$@N<%5ZG0_`WfJMbcZrGKSrCIoe|MK&z+A61uP)WE)Z`KSi#96_xNB01+ZJ&O? z1Y_9-3KrbZLR@kj!6;)vUbcsNpkCaEE!ljR47@-*r=O1io}WvRf%!tMka9sVYMgv9 z>DUAW9p*=R3$U~6)wKveJt6}n6CZ+g8AWF&H6KUkM$|4gI3!^pzh>RHSX4sRAlx2n zbZogZZ^gc#y98pmbUve{1zyb>s0Dq@nB@qeWpvg9Q4#v+alteSFkFErq&Qv|ggrL} zVx=7JA&O^bOa0yf<&_-V(JnhOo;^vz3H(|;VX_`41~}(@m$f5un1b(3ImBH0ABs* zIg9Q|AnKMD=;<&WB!y+8H~}?mHA3UfGe9k&l0*n<-9d=DOyI>VgLnMqtTF zdwUEgRG_o48-n4rPB=0srETm&g1-9=hd7Ca&0@X}+6D3QIZXr%Jdw8JOB~HY@=!jX zMUa=o3B2L69Ew03g?RNPq*5+e8)_VSKjjhNmvX|ZIpxCz7DW)RcWEhmb7pr`zaG$z zA^1>_)&a`udqm8>fwJM9w9#S9osAgz@Hc(8X4O|8d~4-+!ORb`-MOCr%{VJ;PUY*X zFIHdPcdfGFtmyZ!! zU2T*uWBBPMgYrdW-rLaG#u;k2rL#%7!yid!yNH3k^oevf)C%4B-)_*@ljv=hiMw}e zI2_2P5!h=grEUZC1(b;yt2X4!47L;;T8G#Oa^ZLpTkKEqqEPnW47*Q&*&pP-wSR2s zrt6C~{iyg_xI2FM)S|I`AegZXKJy;(GatAA47h&))yJ0r0IEw#A$6AKr4> zX07~q!f68YM;wsu)Y6S>?Z0Q=SeyI(LZq&^=WML^Tv=e>xTx?-MGmFw%W(fsT=O?B z_xwqvhtiAexc?{hxk#tH#GKGRpl!ndW%j7vi4h~|>$9aMbCxD!HNn@Aw)WXgn^0(& zi~!kWOB=e5svebE3EI12Ftx|7n9gSjAt@9e9o<6YDTpEDGw?C*S2e8rs|nOjjW)5A zf`akkcwCFl#1S9S*+qx=8OjkZi3^fD1@tD!HYJ)dwUor75tw;R4Qf1%LSqt*wGYAr zg#3_NUmWAs-D#nRYG6~;nmLHEx#L=Pn|&C+=?)w-0vVHV5|+qNZ=f=qbJ5P7z(&sf z#&&BE+#pHi@*!@^VR^t3OqBi;txVdd5E!+) z6EeU1=tdNC&T)?!&?d?JeER-^7c>ny1GG{X;XR1`7ReaLu;BdS$jQq)#%6AK$2(TE zW55eD>46i&Fyon@bj@dZOBw*941v+VhJ7yeFbLwvQ`+aT`k=pH=^V?JKornhR*4)*QhSR@3)|gk`aP2XVmroRg3RM_PH9o` zz;+%e%oCFm%W+?Wijod`&oEEywaijl?Ez$(8lIZ$bZOF#qrLahq=k@8D4%ekj=z87 z&8z|nQ0<>LeDWfMv#SSP5NTzXywrHhhOY|?Amz#~K~U(K3r5PWl`i@R2)fD#lyPs) zpfa@b^pR0-*`R|AJj*{!mM)@j*7^NAK8jVNmQza_v+dt?HF_N1M?6-~51dH-Fc0^x zxa>$?@i>ugrE%0hP9*4m;uE5@9i7(1miR5K5U4PKJ9v2o$kYi7iq?xR=Qr6hCc`1q zFo}B8#!Z?{+l3JKUbM?HpD=L1xm(Q`U8+*+K{peZ^h&>1N|g6y1x*SL^`bhhm{NIDD}Wawm>>q5T130I*qL zkl|<^)}oP4HgqHZ_dyh_eG$D-s28NfU|$qi#5BO_WojRgK`ba2 z66X=L!9-D0Acu%C*-GtMR1u~s@K0!|a^Ytxo6F-%r=`&QHcTy)>f=HGD{ioL8!%D5 zz8z>@viBr6%r9}^z`bdnE~bA=x_=D3S77r9pBPgBZV<>g6vTeSAfeF&`MD&&O@n`{ zmkdgr(Puf&&5Y-gaGZipywCBB;)}BVId&`ZeAiBa(rzq1LLT(_h@B$!4Rh(u`S|Z(~ z`83igyP9THWKQeTG_AeJ!l=)SMRlR*TGrfgfAP6}L)y^3!IMevtXnQGM`oTm?ABwd z7ykl>RqwRla=5b*vv~$Z3Y|T$5z#Ej!s^Vf@gmqke0al8q1P!xVRdq0<5=OwAK8<+ zJN}W}K@hX~mXC_~n2#_0dQP?NTiK2E&hO4?%y(Sz*^#`GpWRsNzA`hnvC@5|(oN}F z7w&_-K6C`f+d-V#N+73y3=kZ_ok@NnWQs*R4?X~ejA4P;TubIj_Z|V5RM{=ASk|1e z5|lv7=g9JC8-sdpQFu0qfc?!2rS11 zLK;d?Z8nJ{pk!#TlJ~Hr;>qHu0qTK<7Sh{u$j4asp;#+y$2s6+U>yW9YHSI4G+FO& z5VAgYdQhOy4nudtwZcf}OBfIB*KmO!C!xJmext6%5TUCN;HHRR|2XAx3cAX8Ee*s| zw4YKRv_a&3j==m2cpX<St9>kVV-uhhoE<5xtAtEN9{*k5S*e;n>J#VG{k}2R=wg zeqnRE*T09;IVh)p!FbWU>qWJrMYR|AUXCY=YR8J!UCmwhzSCAvam$UIAIE5CKb0G> zjnp>gImx9d&zT0Icr4swsDJ5b{SCJW$IW_t8U<}7UDz3cAe**I-IY|QVCdA8GstxT z86+WkE8kW=htV@e)R0se?gkPbr`ucJa9J8*yq(TdaE*NVZB(m~yP(((^s=dw)Z%;a zKd~DZ$syRa`POX#avxJN0+SzD8)9GVbA!5fL0W@i=_Adm^I=wPTKN4O!$%%Lh>{qf zgE-j84_s3yqdpN>7$#7NAqxJ|y4D2X>3cn7!U#ww&e~RBIYO(16(K|>vcg8!wb3FY zGZRwvk&TIr)6c9cnVZ1EnosMb_UNpv!D5H?6|@g)432@}R_MHN1T`_mn9eS$mU?2r z2}Blmh7g8CHIHNyWG}BA@a;mLZEaV^#!ycP!BBR>p3_->PhzY0lTMDAQc@Ilp|Q+k zbET7X4wkcm%)^9OTf z&lJ<--G;WYj=Rozq}5byH?%r>Zqo2r=5zX&v4wD#YERU0rW34i;ttn|c4X3fOggy! zZdD&4ilM+KYOUdJ?5?w?d@z55a83nF)b)nPf}@Q+!Xio_xd!!JZWkuLz6`7!qy2@s z%J&~bRG7RQ{#nCoMmAquIObnA;QAR3r`r5(A&#SZanV@r9BgeRvuAu-PDvgW$yUayW zD``;tD0|}TNEjQ^{nKwq7CEe;V8|eja+}iF^o{Eh8bzPU!hr9%)Mf3>i@N zJwsJD$|_!4dC~RFhOx5X^}^t_+~9{~Xq-p#qkBFaFT_u$ZFc>~Y*2M-cB9Y!s;e>E z@tVES?fEUpejMK_!M#7k0Y08T%0cRi+m4%8vh0-3rmI13piwsB?-@v{keFmK1u8k= zRP4{&6o(%3hFtDKzlEvV%KJL)@Y7id8K@3%$;eJWDwN1#qZXz)ghhEX6i46?Vl;U+ zJ*+seEEfR$Ls7wyNf%bPL9r;FVe8Wkg%zA^0h=A2@zX_7`U$FVI;BR-Q*vcVTO^+5 z&E7vtPzOfKYUx@xXNBtW_CKftVP8 zL^B4gHd1HV4{np!GAOkX8kH$HelluKlY!EDFT(#sCb_cKO)HqPNE+U|t|QcWNC|D| z4d~Rom_Sp+tmg=zK*ogqwkwTHYHxkRo+=R8>CkmeJp!-IG}?V7suH|I8mdg?r&p%^ zCi1yZevGt@kO8c<<<1%2HnRWX=F1D;Ui?n?nC~Hk2IES53*$k{X<~5seC*(qb$*rx zfUG;GN=Jz!p1RgqKk3~4=|@s~8C~d|jjejR@mpk$-=8fo#;-KQLos<2wO3JG`u>t4 z_ivF;dmT?JX}sp5kBn|{ynSxPNX^Anm#g0LT=D&A|Cn!Y(zW*^p0QJf#h)D){sHRz z+;E|Qm4BsZP&D3x;(o;_1u~6vw8Hh9G~k`#2igxw@06RSd76wN1Y8@)L3Dj8a@b73 zjejiOAK9;L5#X)80+7iB$;R>*#c6LK-x306x%`9H<$uqQR*m@{NxB~4LVw9i{cZ+@ z7W;JLvD-2pp+BpZ#%<*RKNmpb?Cct)>8(5%PS47RWpv$7noWGsj~(%#)W^j`n@L5v8G+maf=0 z=6f{hdh~NbKD&NJ$VVX8+mai+1n->l`iyu7oAoE~T)a>dqTzRjW2|}q*T6AEsC)`M zW6(FB6Rx?NP2IpY=4ejEHvhA?D-Dh+yUy=*_v=+sOKM3#YXxmc?3)B)8#aMh#3Hec z?EprAAvO#xG>qlJ1I|=v5y#W=QfgIPLBvyqNL(4Hq-q#vl7UHF#+Ak0)+E#JiK>)x z{KNV6S|a5syAtR7&VAi2361P=s-{c2_uS>(bMAKTcJ8@fXYU%$_O6eb=VZ7|Hn9+= z(O+a2v*tQ0Cv%%+Pgalk4#XS>J_&B~af*ffCYy<8OXS-uk?&?pWHx@2O(*mgzW5dk zK@d2)j~R^5cNUuyDEHz%mSUXEIs zm_=ZAK4!`7V8>XvYuBY7?DasoJkDgh)@N>^gKAz*NQWRplvkj1BDLIMCk!tEynq`D zl7`B*wVO5dc{ye=TfCUwSf!4#X8EdfHtQ4Bj9NsL|Kv&KLdG(Zr*blaGiy1U?&^WY z8J=r{93g^xzSs)KL!V1TLtJ`bk;$h;+f2)`b@Fv@-~z5JER|GGP=Jp|)x8CiJe5Yn z(D%?gl7_@fOIcD?JFa!(nTHTJd2nIi_hG49*Nm=oxxYLK+qU$>nxy7-P253jW-irI!R1jP+XP~sd^c&@2 zXQFg|*cpBal6?P(v+JI?Z^Q78m~X@VBYuz@U>@;zKuz0b zWYL+LQn{hohiA6>^gh%!q*$!l17o$}G)j)2AYDMI)}-$=4!}<+av;L+9Q>5v0_DJ@ zD~L#kItaRspSrkxAECYTCY@?!M>clM7`q3z5kI78ZSeg-T|7|teqd!huriTf6zPg? zAF8`wk5h`GRd^|&7@Ep?l6tmvn9NsQK)D~GA-fp_> zp1f~f9_Z=sF*Sg%7u+qrQ~V2p;x=*n2MK)mv_Q)*rIgkoC8gCmQn>R;XDsI+g|rS? zkG4NvnQ1?R7KAVB4sn>!cS&iK*c#0o3Y-q~vOEub z%MC_gf7wYPH;Wy(u6V6awVCuuAiY_`Gwi?(Z0=WcZn?s)us!TKYwz;BimUHn4C&;x zXBb0<=}l$~)4qUUSe7B(azSitMTUiV+l4Fi*6cekHw!0?oScbp!EzpgAW($^0S|d+ ziuRQF0)bylz zB+wDd=}?0%@MV6PJd&S%%RZplz=rX!;~(0N(u3c0d-7HUCLzz^W5tR7fyMcRIdZ^{ zIa0hx&OsV~bB5B#O21&HI65FxgRVP{JI9BweCNbS)tdL_HYrx>4*flG2`k-2{Bn;$ zE;eKsC*HV+0tV>yn8rSZ%J1{@!}t;+n`h5v8L1+loebPm*y(eMp(f{k6#b!pL0Sot z`~;uhWyvBG@Lj-3F9TwbXL;Xq&nRk=ty>P`(lootjWI6D zPqoKyBY_Z&U$WNLB3y|l;1yDcC)5wS&~;vXc=ZXMVCYOso}dD@|8Z}kB=`+)%E-!| zF!8TcHtK)oZq%PC5j$3T6JJJ*Oo^vAe?z%sMK^4o(n!ruG9~m)?}yMUN1+V_dmzHVP{yX)DgKX7l<-_qCH{zl)ZC+&O`#ZZdvzJ?D%F&IgA*ZI>| zc$Gi&D#>F@OXgu#ccvT5XACU3=Aqsi@J(77CY@FYDp(60r*WPiI;g@l#C{rLwTCDJ zsxGg+P3RGfr1J$?z=g)dp>`&c-bp(Y-3SOlLor1MmYion!=f5V4M;JLzr1J3KZu zNx`tS3K1sdatO|}Z#Hj}eX}J(sNw5WLWM0AsDnDjdL4sj(uOx+oX{GN)xYSE!XhN2 zxVk&U#Z1x#trL8SLkW_5cymG&1%=2LLu{`}FL!);USQ*r_O5hrb5Kh9lx#rH6^N&Y zxX7C%ij^DboR7WzX* z{3q7zR|&mF=u%g7cy~d`Z+?>y zrFBFEMGo#mJhGNUG&w$!4Q|=kl^v#}V>?*75+vkUE<>@5JE0%bxfl6Px?0=zcJ4UT z5vpY=G}2f|fAY8!9UjrO?oVU87LyiT|B1Hor<(5rE%yV>BWB^KRywLJ z5VQPeTKOpdDu1TcjcV2MS39aL8r3RB=~F2_HKST^R4W_R=8f4MH#dJ}^9POvKXWV` zbu1WlRE;{8JayQNg2;k_Mg5DOY5=iXHS(@+x!HE3Eqpp!a632{9NIQq@J8{y;-TH~ zdCT5&EWfTN9J%Qzf6)Gn({wuZg2-i4gB3kEK@0C{t>2uOUz_sG(@PQs6{a2bm_Pru z-oD=G{M+?|^+VM|-9roG!9{WZV$(n*;=$6~N2Y2I{U*n!JboIXert!cS z`f|LiDPGWQx){@~<@sNGzVG>{e%lx{;<*(j(I6*I*Ujf|Jg?N!MO?^D@nCTzFK$#$ z_!wamh)TKYEQ(;yLJ>lLONtoN{VeK|!IB~Uu5rg0ERW^a#f|z24`UwEJ$fPa=QZ{< zMh*@f?LQjr7^;pQix=0$z1Vj_=$PTWdE~~C@Rrwh_U(*piv}XQ;yLAUqhi89s5#fr zD`LSFrUv`|*$G-^ewpq}KxbrgUvp#?ip4YNK>=UB+jFO9s4+fw$?)YjdhhignDBav|f-%Z$&h-m|4w(2&$GGfPGl3p3LV_!+HG`%x; zmFne@Edx9IccKln4Ym!P8ZH>>8r(m8JcimYYBn`Qc(~=A-EZwi7OpS8t^y*IL7#4F3%dF7K=JNr$qIoGag)KTOY+c{F$ib+N>wue0J3YsW=9&fpQ0%ES z(OLnb!55nHjcVlC*0CjWIkLTPU)%^z_$2BfU9%P9gW_PKv?{S|Rm!(oUn@Nj_Lwhd z8nBTz5_Azl%z37VkXOqu_=x_=G;o>ASumaph^0|z+UN(qE7*`Rpz@UKa|9J^K?NJA zfWSov+if3(fL}6e#p6Ce76L#i)ThlK{_+UgxSPdCEN--QvJ}{3zGl;aZDAoa8y1Eu zEP#lm(zMa9q(EOONx~MwVIxUjrRgH1%81ZxWyEllQTaqJp@mZlCSTv93jzXyfq+G| zfU}V;5kPnOxR0P!JmOpT$)IV}<_6hrT@`u(nyqPvJr*c34cN#98xtY2!3htct*EyE z+VQJ5z|e_!`5IG$@53u%#SVZE!ih?^ z=|K!?hx-pRzrkoX^BY8d3(F#f9NS}M%_9YCujiq7rFqmZN`O&SEJ&1ACRVIT`Sovpz94p=D$QK+ z%F~L92U_}DqNi?O7`!kX7`zk@EHwqAna?&=z-U&Zk}po$w06BiPuZ7%D3{k1J5V&x z+}|8sHDr&j#q-O`a|MPCMrz$HwhW_inlUL3uCG#g&EGQiC_IsnN`u!%@y%R_g#_ug;fGlM61LMyr39po%e0IcF ze%+1T5`Af88!LWkbQ>#vY04YWOC$3KYWr(V4d76eZ-+#r=z)VkT0JBQ7u?uZA{KT9xu0&~?AC6aq3h5m4E<+IJOKw6{fGl5B|o46|?X z_i~_@#5fF=j_1Mg#-|hl$ka_Pa7SW3FQ$JhqwuwuGcaYqX8h( z?a=2%G1G)Kke*nb7JYr(;@O^z@IlI;K(pAJC^l zKhQQ=ew$1u#{>-1=lah@Ph-q%xzhrTg&SiP%i|?jeJ~V5=eY;x9-e-*;s-5{Tb`VH zyfL=vK)eZSKp9VJWB@AG8>KvG*Vf%VeCM!fC%h6&6E;^nM{gVrA6KinST0vO;|4-V z3C2l4=5mWZj%;O#TyRg=&(0*^iL7AQa1mmmzP6@sjp?Dwt6}+hrtb`NW59*BqSlJ~ zfYEQnjgs+PcuU>|2M13nFML-r4=dSmel|O1ux<=V3fJ@n>Tit{qwZ3@ToBQ&tP)l> z|Bc#vweia3rk$SaTHYyst60Ii_xz~#hqVH;B)R;}WXV8eW=W-Keir;oUv1*{4w9R!_Eh^<`24us_zs5%JOdtVZXe3$ql}=sa|>Z{Iv|n2oor%I22a9IMAC>3XxRB?jVAltl}3u2ulz9=LRSfWERf}KzR5-32LKyjoAq(cZK zU=c_#wQ@3nIB8U!`dFI4V^ax)b25Q&rU^VIsS1JcRRjhxrb~hXkU#;_1d1a~ARR&= z0gFI_sTL3z^UojA7clc3X$m{i6n0Fd5YEXI!kMP9Lz1mlsaO=w)eou!1t5h2q$w0f znnF5+LIM_r1XE2@C_I{`@MxOCqf;q_b25c+rYSs{r4YU-!@$^%wiNd4Hp&W$c1`Ww z9d|GxBD`w#n=KDo9-e-HJqx(U4Bt3*@HUb(EXV+vYv<|tQUSCpDsP_~JU4Xe?wLDh zhC7BX#4A?tyZprZ4evC4uW8bL)cSoAkY;4^yu{RfJmASU*H-Gyk~-`$ukW?`zIrvw z#8z2j+>3!70chV?7PQ`Kl?^fM6GmF%ITfahL7Az9><~s>YGxVDi|5vx9!9{5rNs0R z$_x}U5R=OY+x1+%RH%V1vnSXbg>s&y%f%q~jC6SzQnOE^5?Ri+)#n8O?1X&Qh)gOL+HX1WNwHS9VsF+GH_2R-EK)6sd{1KlSAY8;aC1x?<5~g$3oI`l7W$qTrOJO9;pGbN3c@QDyo&H@mF614O$u%%yjH>M2)8I2))U^K;EjYg zDR?tsY>Y{XZqez&c8iqPHgRoNuJIk>YK4pSuv1)klnoi#Yqp7NH(acXJ>uF67i(#s zxUkre@AiuePajDE926IJ8S&lc%notkbkfL=l$nRcg=LZy+fi}hY*A7YTVfr)vde3IDuA-kk9- L(C3CrPG9~HO0R1D literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/jinja2/__pycache__/idtracking.cpython-312.pyc b/backend/venv/Lib/site-packages/jinja2/__pycache__/idtracking.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..888048771a77cfb73319bd3313bac21678d96db8 GIT binary patch literal 19133 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 literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/jinja2/__pycache__/lexer.cpython-312.pyc b/backend/venv/Lib/site-packages/jinja2/__pycache__/lexer.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..136c51989441b39ab797eb10571e08652c1ac8f2 GIT binary patch literal 32078 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 BNwfd} literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/jinja2/__pycache__/nativetypes.cpython-312.pyc b/backend/venv/Lib/site-packages/jinja2/__pycache__/nativetypes.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..16a40d3bb7f86d7d78580e8e5341c59d25a8babf GIT binary patch literal 7032 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 ZZ+>r`z@v1MBb|qqN%OCuLbL}q^MBI!O633m literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/jinja2/__pycache__/nodes.cpython-312.pyc b/backend/venv/Lib/site-packages/jinja2/__pycache__/nodes.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5c4dba4add20613b56cdbd3ffbccce93da483620 GIT binary patch literal 58232 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

jCnsZhcbcY=-0QjES26{>TcO;e{Y4S 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 BP7444 literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/jinja2/__pycache__/optimizer.cpython-312.pyc b/backend/venv/Lib/site-packages/jinja2/__pycache__/optimizer.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ebc510f625850a849c37fe749776a0ca3b054b1a GIT binary patch literal 2702 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 Yq#P_$nMTupaSu6-ML#ysnSsRr2Oy+$RR910 literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/jinja2/__pycache__/runtime.cpython-312.pyc b/backend/venv/Lib/site-packages/jinja2/__pycache__/runtime.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d9b856a4f3bbf20fe1f595f2066f2dd41b43dec9 GIT binary patch literal 48897 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 F{|iM6GgJTo literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/jinja2/__pycache__/tests.cpython-312.pyc b/backend/venv/Lib/site-packages/jinja2/__pycache__/tests.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a079fa4b6645190c7f9e5a54b552cf5f8981145f GIT binary patch literal 9063 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 G)&3V-yc{9` literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/jinja2/__pycache__/utils.cpython-312.pyc b/backend/venv/Lib/site-packages/jinja2/__pycache__/utils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..237bfd7dc4cee06850f8fca95b97c0121874fe73 GIT binary patch literal 34811 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 literal 0 HcmV?d00001 diff --git a/backend/venv/Lib/site-packages/jinja2/_identifier.py b/backend/venv/Lib/site-packages/jinja2/_identifier.py new file mode 100644 index 0000000..928c150 --- /dev/null +++ b/backend/venv/Lib/site-packages/jinja2/_identifier.py @@ -0,0 +1,6 @@ +import re + +# generated by scripts/generate_identifier_pattern.py +pattern = re.compile( + r"[\w·̀-ͯ·҃-֑҇-ׇֽֿׁׂׅׄؐ-ًؚ-ٰٟۖ-ۜ۟-۪ۤۧۨ-ܑۭܰ-݊ަ-ް߫-߽߳ࠖ-࠙ࠛ-ࠣࠥ-ࠧࠩ-࡙࠭-࡛࣓-ࣣ࣡-ःऺ-़ा-ॏ॑-ॗॢॣঁ-ঃ়া-ৄেৈো-্ৗৢৣ৾ਁ-ਃ਼ਾ-ੂੇੈੋ-੍ੑੰੱੵઁ-ઃ઼ા-ૅે-ૉો-્ૢૣૺ-૿ଁ-ଃ଼ା-ୄେୈୋ-୍ୖୗୢୣஂா-ூெ-ைொ-்ௗఀ-ఄా-ౄె-ైొ-్ౕౖౢౣಁ-ಃ಼ಾ-ೄೆ-ೈೊ-್ೕೖೢೣഀ-ഃ഻഼ാ-ൄെ-ൈൊ-്ൗൢൣංඃ්ා-ුූෘ-ෟෲෳัิ-ฺ็-๎ັິ-ູົຼ່-ໍ༹༘༙༵༷༾༿ཱ-྄྆྇ྍ-ྗྙ-ྼ࿆ါ-ှၖ-ၙၞ-ၠၢ-ၤၧ-ၭၱ-ၴႂ-ႍႏႚ-ႝ፝-፟ᜒ-᜔ᜲ-᜴ᝒᝓᝲᝳ឴-៓៝᠋-᠍ᢅᢆᢩᤠ-ᤫᤰ-᤻ᨗ-ᨛᩕ-ᩞ᩠-᩿᩼᪰-᪽ᬀ-ᬄ᬴-᭄᭫-᭳ᮀ-ᮂᮡ-ᮭ᯦-᯳ᰤ-᰷᳐-᳔᳒-᳨᳭ᳲ-᳴᳷-᳹᷀-᷹᷻-᷿‿⁀⁔⃐-⃥⃜⃡-⃰℘℮⳯-⵿⳱ⷠ-〪ⷿ-゙゚〯꙯ꙴ-꙽ꚞꚟ꛰꛱ꠂ꠆ꠋꠣ-ꠧꢀꢁꢴ-ꣅ꣠-꣱ꣿꤦ-꤭ꥇ-꥓ꦀ-ꦃ꦳-꧀ꧥꨩ-ꨶꩃꩌꩍꩻ-ꩽꪰꪲ-ꪴꪷꪸꪾ꪿꫁ꫫ-ꫯꫵ꫶ꯣ-ꯪ꯬꯭ﬞ︀-️︠-︯︳︴﹍-﹏_𐇽𐋠𐍶-𐍺𐨁-𐨃𐨅𐨆𐨌-𐨏𐨸-𐨿𐨺𐫦𐫥𐴤-𐽆𐴧-𐽐𑀀-𑀂𑀸-𑁆𑁿-𑂂𑂰-𑂺𑄀-𑄂𑄧-𑄴𑅅𑅆𑅳𑆀-𑆂𑆳-𑇀𑇉-𑇌𑈬-𑈷𑈾𑋟-𑋪𑌀-𑌃𑌻𑌼𑌾-𑍄𑍇𑍈𑍋-𑍍𑍗𑍢𑍣𑍦-𑍬𑍰-𑍴𑐵-𑑆𑑞𑒰-𑓃𑖯-𑖵𑖸-𑗀𑗜𑗝𑘰-𑙀𑚫-𑚷𑜝-𑜫𑠬-𑠺𑨁-𑨊𑨳-𑨹𑨻-𑨾𑩇𑩑-𑩛𑪊-𑪙𑰯-𑰶𑰸-𑰿𑲒-𑲧𑲩-𑲶𑴱-𑴶𑴺𑴼𑴽𑴿-𑵅𑵇𑶊-𑶎𑶐𑶑𑶓-𑶗𑻳-𑻶𖫰-𖫴𖬰-𖬶𖽑-𖽾𖾏-𖾒𛲝𛲞𝅥-𝅩𝅭-𝅲𝅻-𝆂𝆅-𝆋𝆪-𝆭𝉂-𝉄𝨀-𝨶𝨻-𝩬𝩵𝪄𝪛-𝪟𝪡-𝪯𞀀-𞀆𞀈-𞀘𞀛-𞀡𞀣𞀤𞀦-𞣐𞀪-𞣖𞥄-𞥊󠄀-󠇯]+" # noqa: B950 +) diff --git a/backend/venv/Lib/site-packages/jinja2/async_utils.py b/backend/venv/Lib/site-packages/jinja2/async_utils.py new file mode 100644 index 0000000..f0c1402 --- /dev/null +++ b/backend/venv/Lib/site-packages/jinja2/async_utils.py @@ -0,0 +1,99 @@ +import inspect +import typing as t +from functools import WRAPPER_ASSIGNMENTS +from functools import wraps + +from .utils import _PassArg +from .utils import pass_eval_context + +if t.TYPE_CHECKING: + import typing_extensions as te + +V = t.TypeVar("V") + + +def async_variant(normal_func): # type: ignore + def decorator(async_func): # type: ignore + pass_arg = _PassArg.from_obj(normal_func) + need_eval_context = pass_arg is None + + if pass_arg is _PassArg.environment: + + def is_async(args: t.Any) -> bool: + return t.cast(bool, args[0].is_async) + + else: + + def is_async(args: t.Any) -> bool: + return t.cast(bool, args[0].environment.is_async) + + # Take the doc and annotations from the sync function, but the + # name from the async function. Pallets-Sphinx-Themes + # build_function_directive expects __wrapped__ to point to the + # sync function. + async_func_attrs = ("__module__", "__name__", "__qualname__") + normal_func_attrs = tuple(set(WRAPPER_ASSIGNMENTS).difference(async_func_attrs)) + + @wraps(normal_func, assigned=normal_func_attrs) + @wraps(async_func, assigned=async_func_attrs, updated=()) + def wrapper(*args, **kwargs): # type: ignore + b = is_async(args) + + if need_eval_context: + args = args[1:] + + if b: + return async_func(*args, **kwargs) + + return normal_func(*args, **kwargs) + + if need_eval_context: + wrapper = pass_eval_context(wrapper) + + wrapper.jinja_async_variant = True # type: ignore[attr-defined] + return wrapper + + return decorator + + +_common_primitives = {int, float, bool, str, list, dict, tuple, type(None)} + + +async def auto_await(value: t.Union[t.Awaitable["V"], "V"]) -> "V": + # Avoid a costly call to isawaitable + if type(value) in _common_primitives: + return t.cast("V", value) + + if inspect.isawaitable(value): + return await t.cast("t.Awaitable[V]", value) + + return value + + +class _IteratorToAsyncIterator(t.Generic[V]): + def __init__(self, iterator: "t.Iterator[V]"): + self._iterator = iterator + + def __aiter__(self) -> "te.Self": + return self + + async def __anext__(self) -> V: + try: + return next(self._iterator) + except StopIteration as e: + raise StopAsyncIteration(e.value) from e + + +def auto_aiter( + iterable: "t.Union[t.AsyncIterable[V], t.Iterable[V]]", +) -> "t.AsyncIterator[V]": + if hasattr(iterable, "__aiter__"): + return iterable.__aiter__() + else: + return _IteratorToAsyncIterator(iter(iterable)) + + +async def auto_to_list( + value: "t.Union[t.AsyncIterable[V], t.Iterable[V]]", +) -> t.List["V"]: + return [x async for x in auto_aiter(value)] diff --git a/backend/venv/Lib/site-packages/jinja2/bccache.py b/backend/venv/Lib/site-packages/jinja2/bccache.py new file mode 100644 index 0000000..ada8b09 --- /dev/null +++ b/backend/venv/Lib/site-packages/jinja2/bccache.py @@ -0,0 +1,408 @@ +"""The optional bytecode cache system. This is useful if you have very +complex template situations and the compilation of all those templates +slows down your application too much. + +Situations where this is useful are often forking web applications that +are initialized on the first request. +""" + +import errno +import fnmatch +import marshal +import os +import pickle +import stat +import sys +import tempfile +import typing as t +from hashlib import sha1 +from io import BytesIO +from types import CodeType + +if t.TYPE_CHECKING: + import typing_extensions as te + + from .environment import Environment + + class _MemcachedClient(te.Protocol): + def get(self, key: str) -> bytes: ... + + def set( + self, key: str, value: bytes, timeout: t.Optional[int] = None + ) -> None: ... + + +bc_version = 5 +# Magic bytes to identify Jinja bytecode cache files. Contains the +# Python major and minor version to avoid loading incompatible bytecode +# if a project upgrades its Python version. +bc_magic = ( + b"j2" + + pickle.dumps(bc_version, 2) + + pickle.dumps((sys.version_info[0] << 24) | sys.version_info[1], 2) +) + + +class Bucket: + """Buckets are used to store the bytecode for one template. It's created + and initialized by the bytecode cache and passed to the loading functions. + + The buckets get an internal checksum from the cache assigned and use this + to automatically reject outdated cache material. Individual bytecode + cache subclasses don't have to care about cache invalidation. + """ + + def __init__(self, environment: "Environment", key: str, checksum: str) -> None: + self.environment = environment + self.key = key + self.checksum = checksum + self.reset() + + def reset(self) -> None: + """Resets the bucket (unloads the bytecode).""" + self.code: t.Optional[CodeType] = None + + def load_bytecode(self, f: t.BinaryIO) -> None: + """Loads bytecode from a file or file like object.""" + # make sure the magic header is correct + magic = f.read(len(bc_magic)) + if magic != bc_magic: + self.reset() + return + # the source code of the file changed, we need to reload + checksum = pickle.load(f) + if self.checksum != checksum: + self.reset() + return + # if marshal_load fails then we need to reload + try: + self.code = marshal.load(f) + except (EOFError, ValueError, TypeError): + self.reset() + return + + def write_bytecode(self, f: t.IO[bytes]) -> None: + """Dump the bytecode into the file or file like object passed.""" + if self.code is None: + raise TypeError("can't write empty bucket") + f.write(bc_magic) + pickle.dump(self.checksum, f, 2) + marshal.dump(self.code, f) + + def bytecode_from_string(self, string: bytes) -> None: + """Load bytecode from bytes.""" + self.load_bytecode(BytesIO(string)) + + def bytecode_to_string(self) -> bytes: + """Return the bytecode as bytes.""" + out = BytesIO() + self.write_bytecode(out) + return out.getvalue() + + +class BytecodeCache: + """To implement your own bytecode cache you have to subclass this class + and override :meth:`load_bytecode` and :meth:`dump_bytecode`. Both of + these methods are passed a :class:`~jinja2.bccache.Bucket`. + + A very basic bytecode cache that saves the bytecode on the file system:: + + from os import path + + class MyCache(BytecodeCache): + + def __init__(self, directory): + self.directory = directory + + def load_bytecode(self, bucket): + filename = path.join(self.directory, bucket.key) + if path.exists(filename): + with open(filename, 'rb') as f: + bucket.load_bytecode(f) + + def dump_bytecode(self, bucket): + filename = path.join(self.directory, bucket.key) + with open(filename, 'wb') as f: + bucket.write_bytecode(f) + + A more advanced version of a filesystem based bytecode cache is part of + Jinja. + """ + + def load_bytecode(self, bucket: Bucket) -> None: + """Subclasses have to override this method to load bytecode into a + bucket. If they are not able to find code in the cache for the + bucket, it must not do anything. + """ + raise NotImplementedError() + + def dump_bytecode(self, bucket: Bucket) -> None: + """Subclasses have to override this method to write the bytecode + from a bucket back to the cache. If it unable to do so it must not + fail silently but raise an exception. + """ + raise NotImplementedError() + + def clear(self) -> None: + """Clears the cache. This method is not used by Jinja but should be + implemented to allow applications to clear the bytecode cache used + by a particular environment. + """ + + def get_cache_key( + self, name: str, filename: t.Optional[t.Union[str]] = None + ) -> str: + """Returns the unique hash key for this template name.""" + hash = sha1(name.encode("utf-8")) + + if filename is not None: + hash.update(f"|{filename}".encode()) + + return hash.hexdigest() + + def get_source_checksum(self, source: str) -> str: + """Returns a checksum for the source.""" + return sha1(source.encode("utf-8")).hexdigest() + + def get_bucket( + self, + environment: "Environment", + name: str, + filename: t.Optional[str], + source: str, + ) -> Bucket: + """Return a cache bucket for the given template. All arguments are + mandatory but filename may be `None`. + """ + key = self.get_cache_key(name, filename) + checksum = self.get_source_checksum(source) + bucket = Bucket(environment, key, checksum) + self.load_bytecode(bucket) + return bucket + + def set_bucket(self, bucket: Bucket) -> None: + """Put the bucket into the cache.""" + self.dump_bytecode(bucket) + + +class FileSystemBytecodeCache(BytecodeCache): + """A bytecode cache that stores bytecode on the filesystem. It accepts + two arguments: The directory where the cache items are stored and a + pattern string that is used to build the filename. + + If no directory is specified a default cache directory is selected. On + Windows the user's temp directory is used, on UNIX systems a directory + is created for the user in the system temp directory. + + The pattern can be used to have multiple separate caches operate on the + same directory. The default pattern is ``'__jinja2_%s.cache'``. ``%s`` + is replaced with the cache key. + + >>> bcc = FileSystemBytecodeCache('/tmp/jinja_cache', '%s.cache') + + This bytecode cache supports clearing of the cache using the clear method. + """ + + def __init__( + self, directory: t.Optional[str] = None, pattern: str = "__jinja2_%s.cache" + ) -> None: + if directory is None: + directory = self._get_default_cache_dir() + self.directory = directory + self.pattern = pattern + + def _get_default_cache_dir(self) -> str: + def _unsafe_dir() -> "te.NoReturn": + raise RuntimeError( + "Cannot determine safe temp directory. You " + "need to explicitly provide one." + ) + + tmpdir = tempfile.gettempdir() + + # On windows the temporary directory is used specific unless + # explicitly forced otherwise. We can just use that. + if os.name == "nt": + return tmpdir + if not hasattr(os, "getuid"): + _unsafe_dir() + + dirname = f"_jinja2-cache-{os.getuid()}" + actual_dir = os.path.join(tmpdir, dirname) + + try: + os.mkdir(actual_dir, stat.S_IRWXU) + except OSError as e: + if e.errno != errno.EEXIST: + raise + try: + os.chmod(actual_dir, stat.S_IRWXU) + actual_dir_stat = os.lstat(actual_dir) + if ( + actual_dir_stat.st_uid != os.getuid() + or not stat.S_ISDIR(actual_dir_stat.st_mode) + or stat.S_IMODE(actual_dir_stat.st_mode) != stat.S_IRWXU + ): + _unsafe_dir() + except OSError as e: + if e.errno != errno.EEXIST: + raise + + actual_dir_stat = os.lstat(actual_dir) + if ( + actual_dir_stat.st_uid != os.getuid() + or not stat.S_ISDIR(actual_dir_stat.st_mode) + or stat.S_IMODE(actual_dir_stat.st_mode) != stat.S_IRWXU + ): + _unsafe_dir() + + return actual_dir + + def _get_cache_filename(self, bucket: Bucket) -> str: + return os.path.join(self.directory, self.pattern % (bucket.key,)) + + def load_bytecode(self, bucket: Bucket) -> None: + filename = self._get_cache_filename(bucket) + + # Don't test for existence before opening the file, since the + # file could disappear after the test before the open. + try: + f = open(filename, "rb") + except (FileNotFoundError, IsADirectoryError, PermissionError): + # PermissionError can occur on Windows when an operation is + # in progress, such as calling clear(). + return + + with f: + bucket.load_bytecode(f) + + def dump_bytecode(self, bucket: Bucket) -> None: + # Write to a temporary file, then rename to the real name after + # writing. This avoids another process reading the file before + # it is fully written. + name = self._get_cache_filename(bucket) + f = tempfile.NamedTemporaryFile( + mode="wb", + dir=os.path.dirname(name), + prefix=os.path.basename(name), + suffix=".tmp", + delete=False, + ) + + def remove_silent() -> None: + try: + os.remove(f.name) + except OSError: + # Another process may have called clear(). On Windows, + # another program may be holding the file open. + pass + + try: + with f: + bucket.write_bytecode(f) + except BaseException: + remove_silent() + raise + + try: + os.replace(f.name, name) + except OSError: + # Another process may have called clear(). On Windows, + # another program may be holding the file open. + remove_silent() + except BaseException: + remove_silent() + raise + + def clear(self) -> None: + # imported lazily here because google app-engine doesn't support + # write access on the file system and the function does not exist + # normally. + from os import remove + + files = fnmatch.filter(os.listdir(self.directory), self.pattern % ("*",)) + for filename in files: + try: + remove(os.path.join(self.directory, filename)) + except OSError: + pass + + +class MemcachedBytecodeCache(BytecodeCache): + """This class implements a bytecode cache that uses a memcache cache for + storing the information. It does not enforce a specific memcache library + (tummy's memcache or cmemcache) but will accept any class that provides + the minimal interface required. + + Libraries compatible with this class: + + - `cachelib `_ + - `python-memcached `_ + + (Unfortunately the django cache interface is not compatible because it + does not support storing binary data, only text. You can however pass + the underlying cache client to the bytecode cache which is available + as `django.core.cache.cache._client`.) + + The minimal interface for the client passed to the constructor is this: + + .. class:: MinimalClientInterface + + .. method:: set(key, value[, timeout]) + + Stores the bytecode in the cache. `value` is a string and + `timeout` the timeout of the key. If timeout is not provided + a default timeout or no timeout should be assumed, if it's + provided it's an integer with the number of seconds the cache + item should exist. + + .. method:: get(key) + + Returns the value for the cache key. If the item does not + exist in the cache the return value must be `None`. + + The other arguments to the constructor are the prefix for all keys that + is added before the actual cache key and the timeout for the bytecode in + the cache system. We recommend a high (or no) timeout. + + This bytecode cache does not support clearing of used items in the cache. + The clear method is a no-operation function. + + .. versionadded:: 2.7 + Added support for ignoring memcache errors through the + `ignore_memcache_errors` parameter. + """ + + def __init__( + self, + client: "_MemcachedClient", + prefix: str = "jinja2/bytecode/", + timeout: t.Optional[int] = None, + ignore_memcache_errors: bool = True, + ): + self.client = client + self.prefix = prefix + self.timeout = timeout + self.ignore_memcache_errors = ignore_memcache_errors + + def load_bytecode(self, bucket: Bucket) -> None: + try: + code = self.client.get(self.prefix + bucket.key) + except Exception: + if not self.ignore_memcache_errors: + raise + else: + bucket.bytecode_from_string(code) + + def dump_bytecode(self, bucket: Bucket) -> None: + key = self.prefix + bucket.key + value = bucket.bytecode_to_string() + + try: + if self.timeout is not None: + self.client.set(key, value, self.timeout) + else: + self.client.set(key, value) + except Exception: + if not self.ignore_memcache_errors: + raise diff --git a/backend/venv/Lib/site-packages/jinja2/compiler.py b/backend/venv/Lib/site-packages/jinja2/compiler.py new file mode 100644 index 0000000..a4ff6a1 --- /dev/null +++ b/backend/venv/Lib/site-packages/jinja2/compiler.py @@ -0,0 +1,1998 @@ +"""Compiles nodes from the parser into Python code.""" + +import typing as t +from contextlib import contextmanager +from functools import update_wrapper +from io import StringIO +from itertools import chain +from keyword import iskeyword as is_python_keyword + +from markupsafe import escape +from markupsafe import Markup + +from . import nodes +from .exceptions import TemplateAssertionError +from .idtracking import Symbols +from .idtracking import VAR_LOAD_ALIAS +from .idtracking import VAR_LOAD_PARAMETER +from .idtracking import VAR_LOAD_RESOLVE +from .idtracking import VAR_LOAD_UNDEFINED +from .nodes import EvalContext +from .optimizer import Optimizer +from .utils import _PassArg +from .utils import concat +from .visitor import NodeVisitor + +if t.TYPE_CHECKING: + import typing_extensions as te + + from .environment import Environment + +F = t.TypeVar("F", bound=t.Callable[..., t.Any]) + +operators = { + "eq": "==", + "ne": "!=", + "gt": ">", + "gteq": ">=", + "lt": "<", + "lteq": "<=", + "in": "in", + "notin": "not in", +} + + +def optimizeconst(f: F) -> F: + def new_func( + self: "CodeGenerator", node: nodes.Expr, frame: "Frame", **kwargs: t.Any + ) -> t.Any: + # Only optimize if the frame is not volatile + if self.optimizer is not None and not frame.eval_ctx.volatile: + new_node = self.optimizer.visit(node, frame.eval_ctx) + + if new_node != node: + return self.visit(new_node, frame) + + return f(self, node, frame, **kwargs) + + return update_wrapper(new_func, f) # type: ignore[return-value] + + +def _make_binop(op: str) -> t.Callable[["CodeGenerator", nodes.BinExpr, "Frame"], None]: + @optimizeconst + def visitor(self: "CodeGenerator", node: nodes.BinExpr, frame: Frame) -> None: + if ( + self.environment.sandboxed and op in self.environment.intercepted_binops # type: ignore + ): + self.write(f"environment.call_binop(context, {op!r}, ") + self.visit(node.left, frame) + self.write(", ") + self.visit(node.right, frame) + else: + self.write("(") + self.visit(node.left, frame) + self.write(f" {op} ") + self.visit(node.right, frame) + + self.write(")") + + return visitor + + +def _make_unop( + op: str, +) -> t.Callable[["CodeGenerator", nodes.UnaryExpr, "Frame"], None]: + @optimizeconst + def visitor(self: "CodeGenerator", node: nodes.UnaryExpr, frame: Frame) -> None: + if ( + self.environment.sandboxed and op in self.environment.intercepted_unops # type: ignore + ): + self.write(f"environment.call_unop(context, {op!r}, ") + self.visit(node.node, frame) + else: + self.write("(" + op) + self.visit(node.node, frame) + + self.write(")") + + return visitor + + +def generate( + node: nodes.Template, + environment: "Environment", + name: t.Optional[str], + filename: t.Optional[str], + stream: t.Optional[t.TextIO] = None, + defer_init: bool = False, + optimized: bool = True, +) -> t.Optional[str]: + """Generate the python source for a node tree.""" + if not isinstance(node, nodes.Template): + raise TypeError("Can't compile non template nodes") + + generator = environment.code_generator_class( + environment, name, filename, stream, defer_init, optimized + ) + generator.visit(node) + + if stream is None: + return generator.stream.getvalue() # type: ignore + + return None + + +def has_safe_repr(value: t.Any) -> bool: + """Does the node have a safe representation?""" + if value is None or value is NotImplemented or value is Ellipsis: + return True + + if type(value) in {bool, int, float, complex, range, str, Markup}: + return True + + if type(value) in {tuple, list, set, frozenset}: + return all(has_safe_repr(v) for v in value) + + if type(value) is dict: # noqa E721 + return all(has_safe_repr(k) and has_safe_repr(v) for k, v in value.items()) + + return False + + +def find_undeclared( + nodes: t.Iterable[nodes.Node], names: t.Iterable[str] +) -> t.Set[str]: + """Check if the names passed are accessed undeclared. The return value + is a set of all the undeclared names from the sequence of names found. + """ + visitor = UndeclaredNameVisitor(names) + try: + for node in nodes: + visitor.visit(node) + except VisitorExit: + pass + return visitor.undeclared + + +class MacroRef: + def __init__(self, node: t.Union[nodes.Macro, nodes.CallBlock]) -> None: + self.node = node + self.accesses_caller = False + self.accesses_kwargs = False + self.accesses_varargs = False + + +class Frame: + """Holds compile time information for us.""" + + def __init__( + self, + eval_ctx: EvalContext, + parent: t.Optional["Frame"] = None, + level: t.Optional[int] = None, + ) -> None: + self.eval_ctx = eval_ctx + + # the parent of this frame + self.parent = parent + + if parent is None: + self.symbols = Symbols(level=level) + + # in some dynamic inheritance situations the compiler needs to add + # write tests around output statements. + self.require_output_check = False + + # inside some tags we are using a buffer rather than yield statements. + # this for example affects {% filter %} or {% macro %}. If a frame + # is buffered this variable points to the name of the list used as + # buffer. + self.buffer: t.Optional[str] = None + + # the name of the block we're in, otherwise None. + self.block: t.Optional[str] = None + + else: + self.symbols = Symbols(parent.symbols, level=level) + self.require_output_check = parent.require_output_check + self.buffer = parent.buffer + self.block = parent.block + + # a toplevel frame is the root + soft frames such as if conditions. + self.toplevel = False + + # the root frame is basically just the outermost frame, so no if + # conditions. This information is used to optimize inheritance + # situations. + self.rootlevel = False + + # variables set inside of loops and blocks should not affect outer frames, + # but they still needs to be kept track of as part of the active context. + self.loop_frame = False + self.block_frame = False + + # track whether the frame is being used in an if-statement or conditional + # expression as it determines which errors should be raised during runtime + # or compile time. + self.soft_frame = False + + def copy(self) -> "te.Self": + """Create a copy of the current one.""" + rv = object.__new__(self.__class__) + rv.__dict__.update(self.__dict__) + rv.symbols = self.symbols.copy() + return rv + + def inner(self, isolated: bool = False) -> "Frame": + """Return an inner frame.""" + if isolated: + return Frame(self.eval_ctx, level=self.symbols.level + 1) + return Frame(self.eval_ctx, self) + + def soft(self) -> "te.Self": + """Return a soft frame. A soft frame may not be modified as + standalone thing as it shares the resources with the frame it + was created of, but it's not a rootlevel frame any longer. + + This is only used to implement if-statements and conditional + expressions. + """ + rv = self.copy() + rv.rootlevel = False + rv.soft_frame = True + return rv + + __copy__ = copy + + +class VisitorExit(RuntimeError): + """Exception used by the `UndeclaredNameVisitor` to signal a stop.""" + + +class DependencyFinderVisitor(NodeVisitor): + """A visitor that collects filter and test calls.""" + + def __init__(self) -> None: + self.filters: t.Set[str] = set() + self.tests: t.Set[str] = set() + + def visit_Filter(self, node: nodes.Filter) -> None: + self.generic_visit(node) + self.filters.add(node.name) + + def visit_Test(self, node: nodes.Test) -> None: + self.generic_visit(node) + self.tests.add(node.name) + + def visit_Block(self, node: nodes.Block) -> None: + """Stop visiting at blocks.""" + + +class UndeclaredNameVisitor(NodeVisitor): + """A visitor that checks if a name is accessed without being + declared. This is different from the frame visitor as it will + not stop at closure frames. + """ + + def __init__(self, names: t.Iterable[str]) -> None: + self.names = set(names) + self.undeclared: t.Set[str] = set() + + def visit_Name(self, node: nodes.Name) -> None: + if node.ctx == "load" and node.name in self.names: + self.undeclared.add(node.name) + if self.undeclared == self.names: + raise VisitorExit() + else: + self.names.discard(node.name) + + def visit_Block(self, node: nodes.Block) -> None: + """Stop visiting a blocks.""" + + +class CompilerExit(Exception): + """Raised if the compiler encountered a situation where it just + doesn't make sense to further process the code. Any block that + raises such an exception is not further processed. + """ + + +class CodeGenerator(NodeVisitor): + def __init__( + self, + environment: "Environment", + name: t.Optional[str], + filename: t.Optional[str], + stream: t.Optional[t.TextIO] = None, + defer_init: bool = False, + optimized: bool = True, + ) -> None: + if stream is None: + stream = StringIO() + self.environment = environment + self.name = name + self.filename = filename + self.stream = stream + self.created_block_context = False + self.defer_init = defer_init + self.optimizer: t.Optional[Optimizer] = None + + if optimized: + self.optimizer = Optimizer(environment) + + # aliases for imports + self.import_aliases: t.Dict[str, str] = {} + + # a registry for all blocks. Because blocks are moved out + # into the global python scope they are registered here + self.blocks: t.Dict[str, nodes.Block] = {} + + # the number of extends statements so far + self.extends_so_far = 0 + + # some templates have a rootlevel extends. In this case we + # can safely assume that we're a child template and do some + # more optimizations. + self.has_known_extends = False + + # the current line number + self.code_lineno = 1 + + # registry of all filters and tests (global, not block local) + self.tests: t.Dict[str, str] = {} + self.filters: t.Dict[str, str] = {} + + # the debug information + self.debug_info: t.List[t.Tuple[int, int]] = [] + self._write_debug_info: t.Optional[int] = None + + # the number of new lines before the next write() + self._new_lines = 0 + + # the line number of the last written statement + self._last_line = 0 + + # true if nothing was written so far. + self._first_write = True + + # used by the `temporary_identifier` method to get new + # unique, temporary identifier + self._last_identifier = 0 + + # the current indentation + self._indentation = 0 + + # Tracks toplevel assignments + self._assign_stack: t.List[t.Set[str]] = [] + + # Tracks parameter definition blocks + self._param_def_block: t.List[t.Set[str]] = [] + + # Tracks the current context. + self._context_reference_stack = ["context"] + + @property + def optimized(self) -> bool: + return self.optimizer is not None + + # -- Various compilation helpers + + def fail(self, msg: str, lineno: int) -> "te.NoReturn": + """Fail with a :exc:`TemplateAssertionError`.""" + raise TemplateAssertionError(msg, lineno, self.name, self.filename) + + def temporary_identifier(self) -> str: + """Get a new unique identifier.""" + self._last_identifier += 1 + return f"t_{self._last_identifier}" + + def buffer(self, frame: Frame) -> None: + """Enable buffering for the frame from that point onwards.""" + frame.buffer = self.temporary_identifier() + self.writeline(f"{frame.buffer} = []") + + def return_buffer_contents( + self, frame: Frame, force_unescaped: bool = False + ) -> None: + """Return the buffer contents of the frame.""" + if not force_unescaped: + if frame.eval_ctx.volatile: + self.writeline("if context.eval_ctx.autoescape:") + self.indent() + self.writeline(f"return Markup(concat({frame.buffer}))") + self.outdent() + self.writeline("else:") + self.indent() + self.writeline(f"return concat({frame.buffer})") + self.outdent() + return + elif frame.eval_ctx.autoescape: + self.writeline(f"return Markup(concat({frame.buffer}))") + return + self.writeline(f"return concat({frame.buffer})") + + def indent(self) -> None: + """Indent by one.""" + self._indentation += 1 + + def outdent(self, step: int = 1) -> None: + """Outdent by step.""" + self._indentation -= step + + def start_write(self, frame: Frame, node: t.Optional[nodes.Node] = None) -> None: + """Yield or write into the frame buffer.""" + if frame.buffer is None: + self.writeline("yield ", node) + else: + self.writeline(f"{frame.buffer}.append(", node) + + def end_write(self, frame: Frame) -> None: + """End the writing process started by `start_write`.""" + if frame.buffer is not None: + self.write(")") + + def simple_write( + self, s: str, frame: Frame, node: t.Optional[nodes.Node] = None + ) -> None: + """Simple shortcut for start_write + write + end_write.""" + self.start_write(frame, node) + self.write(s) + self.end_write(frame) + + def blockvisit(self, nodes: t.Iterable[nodes.Node], frame: Frame) -> None: + """Visit a list of nodes as block in a frame. If the current frame + is no buffer a dummy ``if 0: yield None`` is written automatically. + """ + try: + self.writeline("pass") + for node in nodes: + self.visit(node, frame) + except CompilerExit: + pass + + def write(self, x: str) -> None: + """Write a string into the output stream.""" + if self._new_lines: + if not self._first_write: + self.stream.write("\n" * self._new_lines) + self.code_lineno += self._new_lines + if self._write_debug_info is not None: + self.debug_info.append((self._write_debug_info, self.code_lineno)) + self._write_debug_info = None + self._first_write = False + self.stream.write(" " * self._indentation) + self._new_lines = 0 + self.stream.write(x) + + def writeline( + self, x: str, node: t.Optional[nodes.Node] = None, extra: int = 0 + ) -> None: + """Combination of newline and write.""" + self.newline(node, extra) + self.write(x) + + def newline(self, node: t.Optional[nodes.Node] = None, extra: int = 0) -> None: + """Add one or more newlines before the next write.""" + self._new_lines = max(self._new_lines, 1 + extra) + if node is not None and node.lineno != self._last_line: + self._write_debug_info = node.lineno + self._last_line = node.lineno + + def signature( + self, + node: t.Union[nodes.Call, nodes.Filter, nodes.Test], + frame: Frame, + extra_kwargs: t.Optional[t.Mapping[str, t.Any]] = None, + ) -> None: + """Writes a function call to the stream for the current node. + A leading comma is added automatically. The extra keyword + arguments may not include python keywords otherwise a syntax + error could occur. The extra keyword arguments should be given + as python dict. + """ + # if any of the given keyword arguments is a python keyword + # we have to make sure that no invalid call is created. + kwarg_workaround = any( + is_python_keyword(t.cast(str, k)) + for k in chain((x.key for x in node.kwargs), extra_kwargs or ()) + ) + + for arg in node.args: + self.write(", ") + self.visit(arg, frame) + + if not kwarg_workaround: + for kwarg in node.kwargs: + self.write(", ") + self.visit(kwarg, frame) + if extra_kwargs is not None: + for key, value in extra_kwargs.items(): + self.write(f", {key}={value}") + if node.dyn_args: + self.write(", *") + self.visit(node.dyn_args, frame) + + if kwarg_workaround: + if node.dyn_kwargs is not None: + self.write(", **dict({") + else: + self.write(", **{") + for kwarg in node.kwargs: + self.write(f"{kwarg.key!r}: ") + self.visit(kwarg.value, frame) + self.write(", ") + if extra_kwargs is not None: + for key, value in extra_kwargs.items(): + self.write(f"{key!r}: {value}, ") + if node.dyn_kwargs is not None: + self.write("}, **") + self.visit(node.dyn_kwargs, frame) + self.write(")") + else: + self.write("}") + + elif node.dyn_kwargs is not None: + self.write(", **") + self.visit(node.dyn_kwargs, frame) + + def pull_dependencies(self, nodes: t.Iterable[nodes.Node]) -> None: + """Find all filter and test names used in the template and + assign them to variables in the compiled namespace. Checking + that the names are registered with the environment is done when + compiling the Filter and Test nodes. If the node is in an If or + CondExpr node, the check is done at runtime instead. + + .. versionchanged:: 3.0 + Filters and tests in If and CondExpr nodes are checked at + runtime instead of compile time. + """ + visitor = DependencyFinderVisitor() + + for node in nodes: + visitor.visit(node) + + for id_map, names, dependency in ( + (self.filters, visitor.filters, "filters"), + ( + self.tests, + visitor.tests, + "tests", + ), + ): + for name in sorted(names): + if name not in id_map: + id_map[name] = self.temporary_identifier() + + # add check during runtime that dependencies used inside of executed + # blocks are defined, as this step may be skipped during compile time + self.writeline("try:") + self.indent() + self.writeline(f"{id_map[name]} = environment.{dependency}[{name!r}]") + self.outdent() + self.writeline("except KeyError:") + self.indent() + self.writeline("@internalcode") + self.writeline(f"def {id_map[name]}(*unused):") + self.indent() + self.writeline( + f'raise TemplateRuntimeError("No {dependency[:-1]}' + f' named {name!r} found.")' + ) + self.outdent() + self.outdent() + + def enter_frame(self, frame: Frame) -> None: + undefs = [] + for target, (action, param) in frame.symbols.loads.items(): + if action == VAR_LOAD_PARAMETER: + pass + elif action == VAR_LOAD_RESOLVE: + self.writeline(f"{target} = {self.get_resolve_func()}({param!r})") + elif action == VAR_LOAD_ALIAS: + self.writeline(f"{target} = {param}") + elif action == VAR_LOAD_UNDEFINED: + undefs.append(target) + else: + raise NotImplementedError("unknown load instruction") + if undefs: + self.writeline(f"{' = '.join(undefs)} = missing") + + def leave_frame(self, frame: Frame, with_python_scope: bool = False) -> None: + if not with_python_scope: + undefs = [] + for target in frame.symbols.loads: + undefs.append(target) + if undefs: + self.writeline(f"{' = '.join(undefs)} = missing") + + def choose_async(self, async_value: str = "async ", sync_value: str = "") -> str: + return async_value if self.environment.is_async else sync_value + + def func(self, name: str) -> str: + return f"{self.choose_async()}def {name}" + + def macro_body( + self, node: t.Union[nodes.Macro, nodes.CallBlock], frame: Frame + ) -> t.Tuple[Frame, MacroRef]: + """Dump the function def of a macro or call block.""" + frame = frame.inner() + frame.symbols.analyze_node(node) + macro_ref = MacroRef(node) + + explicit_caller = None + skip_special_params = set() + args = [] + + for idx, arg in enumerate(node.args): + if arg.name == "caller": + explicit_caller = idx + if arg.name in ("kwargs", "varargs"): + skip_special_params.add(arg.name) + args.append(frame.symbols.ref(arg.name)) + + undeclared = find_undeclared(node.body, ("caller", "kwargs", "varargs")) + + if "caller" in undeclared: + # In older Jinja versions there was a bug that allowed caller + # to retain the special behavior even if it was mentioned in + # the argument list. However thankfully this was only really + # working if it was the last argument. So we are explicitly + # checking this now and error out if it is anywhere else in + # the argument list. + if explicit_caller is not None: + try: + node.defaults[explicit_caller - len(node.args)] + except IndexError: + self.fail( + "When defining macros or call blocks the " + 'special "caller" argument must be omitted ' + "or be given a default.", + node.lineno, + ) + else: + args.append(frame.symbols.declare_parameter("caller")) + macro_ref.accesses_caller = True + if "kwargs" in undeclared and "kwargs" not in skip_special_params: + args.append(frame.symbols.declare_parameter("kwargs")) + macro_ref.accesses_kwargs = True + if "varargs" in undeclared and "varargs" not in skip_special_params: + args.append(frame.symbols.declare_parameter("varargs")) + macro_ref.accesses_varargs = True + + # macros are delayed, they never require output checks + frame.require_output_check = False + frame.symbols.analyze_node(node) + self.writeline(f"{self.func('macro')}({', '.join(args)}):", node) + self.indent() + + self.buffer(frame) + self.enter_frame(frame) + + self.push_parameter_definitions(frame) + for idx, arg in enumerate(node.args): + ref = frame.symbols.ref(arg.name) + self.writeline(f"if {ref} is missing:") + self.indent() + try: + default = node.defaults[idx - len(node.args)] + except IndexError: + self.writeline( + f'{ref} = undefined("parameter {arg.name!r} was not provided",' + f" name={arg.name!r})" + ) + else: + self.writeline(f"{ref} = ") + self.visit(default, frame) + self.mark_parameter_stored(ref) + self.outdent() + self.pop_parameter_definitions() + + self.blockvisit(node.body, frame) + self.return_buffer_contents(frame, force_unescaped=True) + self.leave_frame(frame, with_python_scope=True) + self.outdent() + + return frame, macro_ref + + def macro_def(self, macro_ref: MacroRef, frame: Frame) -> None: + """Dump the macro definition for the def created by macro_body.""" + arg_tuple = ", ".join(repr(x.name) for x in macro_ref.node.args) + name = getattr(macro_ref.node, "name", None) + if len(macro_ref.node.args) == 1: + arg_tuple += "," + self.write( + f"Macro(environment, macro, {name!r}, ({arg_tuple})," + f" {macro_ref.accesses_kwargs!r}, {macro_ref.accesses_varargs!r}," + f" {macro_ref.accesses_caller!r}, context.eval_ctx.autoescape)" + ) + + def position(self, node: nodes.Node) -> str: + """Return a human readable position for the node.""" + rv = f"line {node.lineno}" + if self.name is not None: + rv = f"{rv} in {self.name!r}" + return rv + + def dump_local_context(self, frame: Frame) -> str: + items_kv = ", ".join( + f"{name!r}: {target}" + for name, target in frame.symbols.dump_stores().items() + ) + return f"{{{items_kv}}}" + + def write_commons(self) -> None: + """Writes a common preamble that is used by root and block functions. + Primarily this sets up common local helpers and enforces a generator + through a dead branch. + """ + self.writeline("resolve = context.resolve_or_missing") + self.writeline("undefined = environment.undefined") + self.writeline("concat = environment.concat") + # always use the standard Undefined class for the implicit else of + # conditional expressions + self.writeline("cond_expr_undefined = Undefined") + self.writeline("if 0: yield None") + + def push_parameter_definitions(self, frame: Frame) -> None: + """Pushes all parameter targets from the given frame into a local + stack that permits tracking of yet to be assigned parameters. In + particular this enables the optimization from `visit_Name` to skip + undefined expressions for parameters in macros as macros can reference + otherwise unbound parameters. + """ + self._param_def_block.append(frame.symbols.dump_param_targets()) + + def pop_parameter_definitions(self) -> None: + """Pops the current parameter definitions set.""" + self._param_def_block.pop() + + def mark_parameter_stored(self, target: str) -> None: + """Marks a parameter in the current parameter definitions as stored. + This will skip the enforced undefined checks. + """ + if self._param_def_block: + self._param_def_block[-1].discard(target) + + def push_context_reference(self, target: str) -> None: + self._context_reference_stack.append(target) + + def pop_context_reference(self) -> None: + self._context_reference_stack.pop() + + def get_context_ref(self) -> str: + return self._context_reference_stack[-1] + + def get_resolve_func(self) -> str: + target = self._context_reference_stack[-1] + if target == "context": + return "resolve" + return f"{target}.resolve" + + def derive_context(self, frame: Frame) -> str: + return f"{self.get_context_ref()}.derived({self.dump_local_context(frame)})" + + def parameter_is_undeclared(self, target: str) -> bool: + """Checks if a given target is an undeclared parameter.""" + if not self._param_def_block: + return False + return target in self._param_def_block[-1] + + def push_assign_tracking(self) -> None: + """Pushes a new layer for assignment tracking.""" + self._assign_stack.append(set()) + + def pop_assign_tracking(self, frame: Frame) -> None: + """Pops the topmost level for assignment tracking and updates the + context variables if necessary. + """ + vars = self._assign_stack.pop() + if ( + not frame.block_frame + and not frame.loop_frame + and not frame.toplevel + or not vars + ): + return + public_names = [x for x in vars if x[:1] != "_"] + if len(vars) == 1: + name = next(iter(vars)) + ref = frame.symbols.ref(name) + if frame.loop_frame: + self.writeline(f"_loop_vars[{name!r}] = {ref}") + return + if frame.block_frame: + self.writeline(f"_block_vars[{name!r}] = {ref}") + return + self.writeline(f"context.vars[{name!r}] = {ref}") + else: + if frame.loop_frame: + self.writeline("_loop_vars.update({") + elif frame.block_frame: + self.writeline("_block_vars.update({") + else: + self.writeline("context.vars.update({") + for idx, name in enumerate(sorted(vars)): + if idx: + self.write(", ") + ref = frame.symbols.ref(name) + self.write(f"{name!r}: {ref}") + self.write("})") + if not frame.block_frame and not frame.loop_frame and public_names: + if len(public_names) == 1: + self.writeline(f"context.exported_vars.add({public_names[0]!r})") + else: + names_str = ", ".join(map(repr, sorted(public_names))) + self.writeline(f"context.exported_vars.update(({names_str}))") + + # -- Statement Visitors + + def visit_Template( + self, node: nodes.Template, frame: t.Optional[Frame] = None + ) -> None: + assert frame is None, "no root frame allowed" + eval_ctx = EvalContext(self.environment, self.name) + + from .runtime import async_exported + from .runtime import exported + + if self.environment.is_async: + exported_names = sorted(exported + async_exported) + else: + exported_names = sorted(exported) + + self.writeline("from jinja2.runtime import " + ", ".join(exported_names)) + + # if we want a deferred initialization we cannot move the + # environment into a local name + envenv = "" if self.defer_init else ", environment=environment" + + # do we have an extends tag at all? If not, we can save some + # overhead by just not processing any inheritance code. + have_extends = node.find(nodes.Extends) is not None + + # find all blocks + for block in node.find_all(nodes.Block): + if block.name in self.blocks: + self.fail(f"block {block.name!r} defined twice", block.lineno) + self.blocks[block.name] = block + + # find all imports and import them + for import_ in node.find_all(nodes.ImportedName): + if import_.importname not in self.import_aliases: + imp = import_.importname + self.import_aliases[imp] = alias = self.temporary_identifier() + if "." in imp: + module, obj = imp.rsplit(".", 1) + self.writeline(f"from {module} import {obj} as {alias}") + else: + self.writeline(f"import {imp} as {alias}") + + # add the load name + self.writeline(f"name = {self.name!r}") + + # generate the root render function. + self.writeline( + f"{self.func('root')}(context, missing=missing{envenv}):", extra=1 + ) + self.indent() + self.write_commons() + + # process the root + frame = Frame(eval_ctx) + if "self" in find_undeclared(node.body, ("self",)): + ref = frame.symbols.declare_parameter("self") + self.writeline(f"{ref} = TemplateReference(context)") + frame.symbols.analyze_node(node) + frame.toplevel = frame.rootlevel = True + frame.require_output_check = have_extends and not self.has_known_extends + if have_extends: + self.writeline("parent_template = None") + self.enter_frame(frame) + self.pull_dependencies(node.body) + self.blockvisit(node.body, frame) + self.leave_frame(frame, with_python_scope=True) + self.outdent() + + # make sure that the parent root is called. + if have_extends: + if not self.has_known_extends: + self.indent() + self.writeline("if parent_template is not None:") + self.indent() + if not self.environment.is_async: + self.writeline("yield from parent_template.root_render_func(context)") + else: + self.writeline("agen = parent_template.root_render_func(context)") + self.writeline("try:") + self.indent() + self.writeline("async for event in agen:") + self.indent() + self.writeline("yield event") + self.outdent() + self.outdent() + self.writeline("finally: await agen.aclose()") + self.outdent(1 + (not self.has_known_extends)) + + # at this point we now have the blocks collected and can visit them too. + for name, block in self.blocks.items(): + self.writeline( + f"{self.func('block_' + name)}(context, missing=missing{envenv}):", + block, + 1, + ) + self.indent() + self.write_commons() + # It's important that we do not make this frame a child of the + # toplevel template. This would cause a variety of + # interesting issues with identifier tracking. + block_frame = Frame(eval_ctx) + block_frame.block_frame = True + undeclared = find_undeclared(block.body, ("self", "super")) + if "self" in undeclared: + ref = block_frame.symbols.declare_parameter("self") + self.writeline(f"{ref} = TemplateReference(context)") + if "super" in undeclared: + ref = block_frame.symbols.declare_parameter("super") + self.writeline(f"{ref} = context.super({name!r}, block_{name})") + block_frame.symbols.analyze_node(block) + block_frame.block = name + self.writeline("_block_vars = {}") + self.enter_frame(block_frame) + self.pull_dependencies(block.body) + self.blockvisit(block.body, block_frame) + self.leave_frame(block_frame, with_python_scope=True) + self.outdent() + + blocks_kv_str = ", ".join(f"{x!r}: block_{x}" for x in self.blocks) + self.writeline(f"blocks = {{{blocks_kv_str}}}", extra=1) + debug_kv_str = "&".join(f"{k}={v}" for k, v in self.debug_info) + self.writeline(f"debug_info = {debug_kv_str!r}") + + def visit_Block(self, node: nodes.Block, frame: Frame) -> None: + """Call a block and register it for the template.""" + level = 0 + if frame.toplevel: + # if we know that we are a child template, there is no need to + # check if we are one + if self.has_known_extends: + return + if self.extends_so_far > 0: + self.writeline("if parent_template is None:") + self.indent() + level += 1 + + if node.scoped: + context = self.derive_context(frame) + else: + context = self.get_context_ref() + + if node.required: + self.writeline(f"if len(context.blocks[{node.name!r}]) <= 1:", node) + self.indent() + self.writeline( + f'raise TemplateRuntimeError("Required block {node.name!r} not found")', + node, + ) + self.outdent() + + if not self.environment.is_async and frame.buffer is None: + self.writeline( + f"yield from context.blocks[{node.name!r}][0]({context})", node + ) + else: + self.writeline(f"gen = context.blocks[{node.name!r}][0]({context})") + self.writeline("try:") + self.indent() + self.writeline( + f"{self.choose_async()}for event in gen:", + node, + ) + self.indent() + self.simple_write("event", frame) + self.outdent() + self.outdent() + self.writeline( + f"finally: {self.choose_async('await gen.aclose()', 'gen.close()')}" + ) + + self.outdent(level) + + def visit_Extends(self, node: nodes.Extends, frame: Frame) -> None: + """Calls the extender.""" + if not frame.toplevel: + self.fail("cannot use extend from a non top-level scope", node.lineno) + + # if the number of extends statements in general is zero so + # far, we don't have to add a check if something extended + # the template before this one. + if self.extends_so_far > 0: + # if we have a known extends we just add a template runtime + # error into the generated code. We could catch that at compile + # time too, but i welcome it not to confuse users by throwing the + # same error at different times just "because we can". + if not self.has_known_extends: + self.writeline("if parent_template is not None:") + self.indent() + self.writeline('raise TemplateRuntimeError("extended multiple times")') + + # if we have a known extends already we don't need that code here + # as we know that the template execution will end here. + if self.has_known_extends: + raise CompilerExit() + else: + self.outdent() + + self.writeline("parent_template = environment.get_template(", node) + self.visit(node.template, frame) + self.write(f", {self.name!r})") + self.writeline("for name, parent_block in parent_template.blocks.items():") + self.indent() + self.writeline("context.blocks.setdefault(name, []).append(parent_block)") + self.outdent() + + # if this extends statement was in the root level we can take + # advantage of that information and simplify the generated code + # in the top level from this point onwards + if frame.rootlevel: + self.has_known_extends = True + + # and now we have one more + self.extends_so_far += 1 + + def visit_Include(self, node: nodes.Include, frame: Frame) -> None: + """Handles includes.""" + if node.ignore_missing: + self.writeline("try:") + self.indent() + + func_name = "get_or_select_template" + if isinstance(node.template, nodes.Const): + if isinstance(node.template.value, str): + func_name = "get_template" + elif isinstance(node.template.value, (tuple, list)): + func_name = "select_template" + elif isinstance(node.template, (nodes.Tuple, nodes.List)): + func_name = "select_template" + + self.writeline(f"template = environment.{func_name}(", node) + self.visit(node.template, frame) + self.write(f", {self.name!r})") + if node.ignore_missing: + self.outdent() + self.writeline("except TemplateNotFound:") + self.indent() + self.writeline("pass") + self.outdent() + self.writeline("else:") + self.indent() + + def loop_body() -> None: + self.indent() + self.simple_write("event", frame) + self.outdent() + + if node.with_context: + self.writeline( + f"gen = template.root_render_func(" + "template.new_context(context.get_all(), True," + f" {self.dump_local_context(frame)}))" + ) + self.writeline("try:") + self.indent() + self.writeline(f"{self.choose_async()}for event in gen:") + loop_body() + self.outdent() + self.writeline( + f"finally: {self.choose_async('await gen.aclose()', 'gen.close()')}" + ) + elif self.environment.is_async: + self.writeline( + "for event in (await template._get_default_module_async())" + "._body_stream:" + ) + loop_body() + else: + self.writeline("yield from template._get_default_module()._body_stream") + + if node.ignore_missing: + self.outdent() + + def _import_common( + self, node: t.Union[nodes.Import, nodes.FromImport], frame: Frame + ) -> None: + self.write(f"{self.choose_async('await ')}environment.get_template(") + self.visit(node.template, frame) + self.write(f", {self.name!r}).") + + if node.with_context: + f_name = f"make_module{self.choose_async('_async')}" + self.write( + f"{f_name}(context.get_all(), True, {self.dump_local_context(frame)})" + ) + else: + self.write(f"_get_default_module{self.choose_async('_async')}(context)") + + def visit_Import(self, node: nodes.Import, frame: Frame) -> None: + """Visit regular imports.""" + self.writeline(f"{frame.symbols.ref(node.target)} = ", node) + if frame.toplevel: + self.write(f"context.vars[{node.target!r}] = ") + + self._import_common(node, frame) + + if frame.toplevel and not node.target.startswith("_"): + self.writeline(f"context.exported_vars.discard({node.target!r})") + + def visit_FromImport(self, node: nodes.FromImport, frame: Frame) -> None: + """Visit named imports.""" + self.newline(node) + self.write("included_template = ") + self._import_common(node, frame) + var_names = [] + discarded_names = [] + for name in node.names: + if isinstance(name, tuple): + name, alias = name + else: + alias = name + self.writeline( + f"{frame.symbols.ref(alias)} =" + f" getattr(included_template, {name!r}, missing)" + ) + self.writeline(f"if {frame.symbols.ref(alias)} is missing:") + self.indent() + # The position will contain the template name, and will be formatted + # into a string that will be compiled into an f-string. Curly braces + # in the name must be replaced with escapes so that they will not be + # executed as part of the f-string. + position = self.position(node).replace("{", "{{").replace("}", "}}") + message = ( + "the template {included_template.__name__!r}" + f" (imported on {position})" + f" does not export the requested name {name!r}" + ) + self.writeline( + f"{frame.symbols.ref(alias)} = undefined(f{message!r}, name={name!r})" + ) + self.outdent() + if frame.toplevel: + var_names.append(alias) + if not alias.startswith("_"): + discarded_names.append(alias) + + if var_names: + if len(var_names) == 1: + name = var_names[0] + self.writeline(f"context.vars[{name!r}] = {frame.symbols.ref(name)}") + else: + names_kv = ", ".join( + f"{name!r}: {frame.symbols.ref(name)}" for name in var_names + ) + self.writeline(f"context.vars.update({{{names_kv}}})") + if discarded_names: + if len(discarded_names) == 1: + self.writeline(f"context.exported_vars.discard({discarded_names[0]!r})") + else: + names_str = ", ".join(map(repr, discarded_names)) + self.writeline( + f"context.exported_vars.difference_update(({names_str}))" + ) + + def visit_For(self, node: nodes.For, frame: Frame) -> None: + loop_frame = frame.inner() + loop_frame.loop_frame = True + test_frame = frame.inner() + else_frame = frame.inner() + + # try to figure out if we have an extended loop. An extended loop + # is necessary if the loop is in recursive mode if the special loop + # variable is accessed in the body if the body is a scoped block. + extended_loop = ( + node.recursive + or "loop" + in find_undeclared(node.iter_child_nodes(only=("body",)), ("loop",)) + or any(block.scoped for block in node.find_all(nodes.Block)) + ) + + loop_ref = None + if extended_loop: + loop_ref = loop_frame.symbols.declare_parameter("loop") + + loop_frame.symbols.analyze_node(node, for_branch="body") + if node.else_: + else_frame.symbols.analyze_node(node, for_branch="else") + + if node.test: + loop_filter_func = self.temporary_identifier() + test_frame.symbols.analyze_node(node, for_branch="test") + self.writeline(f"{self.func(loop_filter_func)}(fiter):", node.test) + self.indent() + self.enter_frame(test_frame) + self.writeline(self.choose_async("async for ", "for ")) + self.visit(node.target, loop_frame) + self.write(" in ") + self.write(self.choose_async("auto_aiter(fiter)", "fiter")) + self.write(":") + self.indent() + self.writeline("if ", node.test) + self.visit(node.test, test_frame) + self.write(":") + self.indent() + self.writeline("yield ") + self.visit(node.target, loop_frame) + self.outdent(3) + self.leave_frame(test_frame, with_python_scope=True) + + # if we don't have an recursive loop we have to find the shadowed + # variables at that point. Because loops can be nested but the loop + # variable is a special one we have to enforce aliasing for it. + if node.recursive: + self.writeline( + f"{self.func('loop')}(reciter, loop_render_func, depth=0):", node + ) + self.indent() + self.buffer(loop_frame) + + # Use the same buffer for the else frame + else_frame.buffer = loop_frame.buffer + + # make sure the loop variable is a special one and raise a template + # assertion error if a loop tries to write to loop + if extended_loop: + self.writeline(f"{loop_ref} = missing") + + for name in node.find_all(nodes.Name): + if name.ctx == "store" and name.name == "loop": + self.fail( + "Can't assign to special loop variable in for-loop target", + name.lineno, + ) + + if node.else_: + iteration_indicator = self.temporary_identifier() + self.writeline(f"{iteration_indicator} = 1") + + self.writeline(self.choose_async("async for ", "for "), node) + self.visit(node.target, loop_frame) + if extended_loop: + self.write(f", {loop_ref} in {self.choose_async('Async')}LoopContext(") + else: + self.write(" in ") + + if node.test: + self.write(f"{loop_filter_func}(") + if node.recursive: + self.write("reciter") + else: + if self.environment.is_async and not extended_loop: + self.write("auto_aiter(") + self.visit(node.iter, frame) + if self.environment.is_async and not extended_loop: + self.write(")") + if node.test: + self.write(")") + + if node.recursive: + self.write(", undefined, loop_render_func, depth):") + else: + self.write(", undefined):" if extended_loop else ":") + + self.indent() + self.enter_frame(loop_frame) + + self.writeline("_loop_vars = {}") + self.blockvisit(node.body, loop_frame) + if node.else_: + self.writeline(f"{iteration_indicator} = 0") + self.outdent() + self.leave_frame( + loop_frame, with_python_scope=node.recursive and not node.else_ + ) + + if node.else_: + self.writeline(f"if {iteration_indicator}:") + self.indent() + self.enter_frame(else_frame) + self.blockvisit(node.else_, else_frame) + self.leave_frame(else_frame) + self.outdent() + + # if the node was recursive we have to return the buffer contents + # and start the iteration code + if node.recursive: + self.return_buffer_contents(loop_frame) + self.outdent() + self.start_write(frame, node) + self.write(f"{self.choose_async('await ')}loop(") + if self.environment.is_async: + self.write("auto_aiter(") + self.visit(node.iter, frame) + if self.environment.is_async: + self.write(")") + self.write(", loop)") + self.end_write(frame) + + # at the end of the iteration, clear any assignments made in the + # loop from the top level + if self._assign_stack: + self._assign_stack[-1].difference_update(loop_frame.symbols.stores) + + def visit_If(self, node: nodes.If, frame: Frame) -> None: + if_frame = frame.soft() + self.writeline("if ", node) + self.visit(node.test, if_frame) + self.write(":") + self.indent() + self.blockvisit(node.body, if_frame) + self.outdent() + for elif_ in node.elif_: + self.writeline("elif ", elif_) + self.visit(elif_.test, if_frame) + self.write(":") + self.indent() + self.blockvisit(elif_.body, if_frame) + self.outdent() + if node.else_: + self.writeline("else:") + self.indent() + self.blockvisit(node.else_, if_frame) + self.outdent() + + def visit_Macro(self, node: nodes.Macro, frame: Frame) -> None: + macro_frame, macro_ref = self.macro_body(node, frame) + self.newline() + if frame.toplevel: + if not node.name.startswith("_"): + self.write(f"context.exported_vars.add({node.name!r})") + self.writeline(f"context.vars[{node.name!r}] = ") + self.write(f"{frame.symbols.ref(node.name)} = ") + self.macro_def(macro_ref, macro_frame) + + def visit_CallBlock(self, node: nodes.CallBlock, frame: Frame) -> None: + call_frame, macro_ref = self.macro_body(node, frame) + self.writeline("caller = ") + self.macro_def(macro_ref, call_frame) + self.start_write(frame, node) + self.visit_Call(node.call, frame, forward_caller=True) + self.end_write(frame) + + def visit_FilterBlock(self, node: nodes.FilterBlock, frame: Frame) -> None: + filter_frame = frame.inner() + filter_frame.symbols.analyze_node(node) + self.enter_frame(filter_frame) + self.buffer(filter_frame) + self.blockvisit(node.body, filter_frame) + self.start_write(frame, node) + self.visit_Filter(node.filter, filter_frame) + self.end_write(frame) + self.leave_frame(filter_frame) + + def visit_With(self, node: nodes.With, frame: Frame) -> None: + with_frame = frame.inner() + with_frame.symbols.analyze_node(node) + self.enter_frame(with_frame) + for target, expr in zip(node.targets, node.values): + self.newline() + self.visit(target, with_frame) + self.write(" = ") + self.visit(expr, frame) + self.blockvisit(node.body, with_frame) + self.leave_frame(with_frame) + + def visit_ExprStmt(self, node: nodes.ExprStmt, frame: Frame) -> None: + self.newline(node) + self.visit(node.node, frame) + + class _FinalizeInfo(t.NamedTuple): + const: t.Optional[t.Callable[..., str]] + src: t.Optional[str] + + @staticmethod + def _default_finalize(value: t.Any) -> t.Any: + """The default finalize function if the environment isn't + configured with one. Or, if the environment has one, this is + called on that function's output for constants. + """ + return str(value) + + _finalize: t.Optional[_FinalizeInfo] = None + + def _make_finalize(self) -> _FinalizeInfo: + """Build the finalize function to be used on constants and at + runtime. Cached so it's only created once for all output nodes. + + Returns a ``namedtuple`` with the following attributes: + + ``const`` + A function to finalize constant data at compile time. + + ``src`` + Source code to output around nodes to be evaluated at + runtime. + """ + if self._finalize is not None: + return self._finalize + + finalize: t.Optional[t.Callable[..., t.Any]] + finalize = default = self._default_finalize + src = None + + if self.environment.finalize: + src = "environment.finalize(" + env_finalize = self.environment.finalize + pass_arg = { + _PassArg.context: "context", + _PassArg.eval_context: "context.eval_ctx", + _PassArg.environment: "environment", + }.get( + _PassArg.from_obj(env_finalize) # type: ignore + ) + finalize = None + + if pass_arg is None: + + def finalize(value: t.Any) -> t.Any: # noqa: F811 + return default(env_finalize(value)) + + else: + src = f"{src}{pass_arg}, " + + if pass_arg == "environment": + + def finalize(value: t.Any) -> t.Any: # noqa: F811 + return default(env_finalize(self.environment, value)) + + self._finalize = self._FinalizeInfo(finalize, src) + return self._finalize + + def _output_const_repr(self, group: t.Iterable[t.Any]) -> str: + """Given a group of constant values converted from ``Output`` + child nodes, produce a string to write to the template module + source. + """ + return repr(concat(group)) + + def _output_child_to_const( + self, node: nodes.Expr, frame: Frame, finalize: _FinalizeInfo + ) -> str: + """Try to optimize a child of an ``Output`` node by trying to + convert it to constant, finalized data at compile time. + + If :exc:`Impossible` is raised, the node is not constant and + will be evaluated at runtime. Any other exception will also be + evaluated at runtime for easier debugging. + """ + const = node.as_const(frame.eval_ctx) + + if frame.eval_ctx.autoescape: + const = escape(const) + + # Template data doesn't go through finalize. + if isinstance(node, nodes.TemplateData): + return str(const) + + return finalize.const(const) # type: ignore + + def _output_child_pre( + self, node: nodes.Expr, frame: Frame, finalize: _FinalizeInfo + ) -> None: + """Output extra source code before visiting a child of an + ``Output`` node. + """ + if frame.eval_ctx.volatile: + self.write("(escape if context.eval_ctx.autoescape else str)(") + elif frame.eval_ctx.autoescape: + self.write("escape(") + else: + self.write("str(") + + if finalize.src is not None: + self.write(finalize.src) + + def _output_child_post( + self, node: nodes.Expr, frame: Frame, finalize: _FinalizeInfo + ) -> None: + """Output extra source code after visiting a child of an + ``Output`` node. + """ + self.write(")") + + if finalize.src is not None: + self.write(")") + + def visit_Output(self, node: nodes.Output, frame: Frame) -> None: + # If an extends is active, don't render outside a block. + if frame.require_output_check: + # A top-level extends is known to exist at compile time. + if self.has_known_extends: + return + + self.writeline("if parent_template is None:") + self.indent() + + finalize = self._make_finalize() + body: t.List[t.Union[t.List[t.Any], nodes.Expr]] = [] + + # Evaluate constants at compile time if possible. Each item in + # body will be either a list of static data or a node to be + # evaluated at runtime. + for child in node.nodes: + try: + if not ( + # If the finalize function requires runtime context, + # constants can't be evaluated at compile time. + finalize.const + # Unless it's basic template data that won't be + # finalized anyway. + or isinstance(child, nodes.TemplateData) + ): + raise nodes.Impossible() + + const = self._output_child_to_const(child, frame, finalize) + except (nodes.Impossible, Exception): + # The node was not constant and needs to be evaluated at + # runtime. Or another error was raised, which is easier + # to debug at runtime. + body.append(child) + continue + + if body and isinstance(body[-1], list): + body[-1].append(const) + else: + body.append([const]) + + if frame.buffer is not None: + if len(body) == 1: + self.writeline(f"{frame.buffer}.append(") + else: + self.writeline(f"{frame.buffer}.extend((") + + self.indent() + + for item in body: + if isinstance(item, list): + # A group of constant data to join and output. + val = self._output_const_repr(item) + + if frame.buffer is None: + self.writeline("yield " + val) + else: + self.writeline(val + ",") + else: + if frame.buffer is None: + self.writeline("yield ", item) + else: + self.newline(item) + + # A node to be evaluated at runtime. + self._output_child_pre(item, frame, finalize) + self.visit(item, frame) + self._output_child_post(item, frame, finalize) + + if frame.buffer is not None: + self.write(",") + + if frame.buffer is not None: + self.outdent() + self.writeline(")" if len(body) == 1 else "))") + + if frame.require_output_check: + self.outdent() + + def visit_Assign(self, node: nodes.Assign, frame: Frame) -> None: + self.push_assign_tracking() + + # ``a.b`` is allowed for assignment, and is parsed as an NSRef. However, + # it is only valid if it references a Namespace object. Emit a check for + # that for each ref here, before assignment code is emitted. This can't + # be done in visit_NSRef as the ref could be in the middle of a tuple. + seen_refs: t.Set[str] = set() + + for nsref in node.find_all(nodes.NSRef): + if nsref.name in seen_refs: + # Only emit the check for each reference once, in case the same + # ref is used multiple times in a tuple, `ns.a, ns.b = c, d`. + continue + + seen_refs.add(nsref.name) + ref = frame.symbols.ref(nsref.name) + self.writeline(f"if not isinstance({ref}, Namespace):") + self.indent() + self.writeline( + "raise TemplateRuntimeError" + '("cannot assign attribute on non-namespace object")' + ) + self.outdent() + + self.newline(node) + self.visit(node.target, frame) + self.write(" = ") + self.visit(node.node, frame) + self.pop_assign_tracking(frame) + + def visit_AssignBlock(self, node: nodes.AssignBlock, frame: Frame) -> None: + self.push_assign_tracking() + block_frame = frame.inner() + # This is a special case. Since a set block always captures we + # will disable output checks. This way one can use set blocks + # toplevel even in extended templates. + block_frame.require_output_check = False + block_frame.symbols.analyze_node(node) + self.enter_frame(block_frame) + self.buffer(block_frame) + self.blockvisit(node.body, block_frame) + self.newline(node) + self.visit(node.target, frame) + self.write(" = (Markup if context.eval_ctx.autoescape else identity)(") + if node.filter is not None: + self.visit_Filter(node.filter, block_frame) + else: + self.write(f"concat({block_frame.buffer})") + self.write(")") + self.pop_assign_tracking(frame) + self.leave_frame(block_frame) + + # -- Expression Visitors + + def visit_Name(self, node: nodes.Name, frame: Frame) -> None: + if node.ctx == "store" and ( + frame.toplevel or frame.loop_frame or frame.block_frame + ): + if self._assign_stack: + self._assign_stack[-1].add(node.name) + ref = frame.symbols.ref(node.name) + + # If we are looking up a variable we might have to deal with the + # case where it's undefined. We can skip that case if the load + # instruction indicates a parameter which are always defined. + if node.ctx == "load": + load = frame.symbols.find_load(ref) + if not ( + load is not None + and load[0] == VAR_LOAD_PARAMETER + and not self.parameter_is_undeclared(ref) + ): + self.write( + f"(undefined(name={node.name!r}) if {ref} is missing else {ref})" + ) + return + + self.write(ref) + + def visit_NSRef(self, node: nodes.NSRef, frame: Frame) -> None: + # NSRef is a dotted assignment target a.b=c, but uses a[b]=c internally. + # visit_Assign emits code to validate that each ref is to a Namespace + # object only. That can't be emitted here as the ref could be in the + # middle of a tuple assignment. + ref = frame.symbols.ref(node.name) + self.writeline(f"{ref}[{node.attr!r}]") + + def visit_Const(self, node: nodes.Const, frame: Frame) -> None: + val = node.as_const(frame.eval_ctx) + if isinstance(val, float): + self.write(str(val)) + else: + self.write(repr(val)) + + def visit_TemplateData(self, node: nodes.TemplateData, frame: Frame) -> None: + try: + self.write(repr(node.as_const(frame.eval_ctx))) + except nodes.Impossible: + self.write( + f"(Markup if context.eval_ctx.autoescape else identity)({node.data!r})" + ) + + def visit_Tuple(self, node: nodes.Tuple, frame: Frame) -> None: + self.write("(") + idx = -1 + for idx, item in enumerate(node.items): + if idx: + self.write(", ") + self.visit(item, frame) + self.write(",)" if idx == 0 else ")") + + def visit_List(self, node: nodes.List, frame: Frame) -> None: + self.write("[") + for idx, item in enumerate(node.items): + if idx: + self.write(", ") + self.visit(item, frame) + self.write("]") + + def visit_Dict(self, node: nodes.Dict, frame: Frame) -> None: + self.write("{") + for idx, item in enumerate(node.items): + if idx: + self.write(", ") + self.visit(item.key, frame) + self.write(": ") + self.visit(item.value, frame) + self.write("}") + + visit_Add = _make_binop("+") + visit_Sub = _make_binop("-") + visit_Mul = _make_binop("*") + visit_Div = _make_binop("/") + visit_FloorDiv = _make_binop("//") + visit_Pow = _make_binop("**") + visit_Mod = _make_binop("%") + visit_And = _make_binop("and") + visit_Or = _make_binop("or") + visit_Pos = _make_unop("+") + visit_Neg = _make_unop("-") + visit_Not = _make_unop("not ") + + @optimizeconst + def visit_Concat(self, node: nodes.Concat, frame: Frame) -> None: + if frame.eval_ctx.volatile: + func_name = "(markup_join if context.eval_ctx.volatile else str_join)" + elif frame.eval_ctx.autoescape: + func_name = "markup_join" + else: + func_name = "str_join" + self.write(f"{func_name}((") + for arg in node.nodes: + self.visit(arg, frame) + self.write(", ") + self.write("))") + + @optimizeconst + def visit_Compare(self, node: nodes.Compare, frame: Frame) -> None: + self.write("(") + self.visit(node.expr, frame) + for op in node.ops: + self.visit(op, frame) + self.write(")") + + def visit_Operand(self, node: nodes.Operand, frame: Frame) -> None: + self.write(f" {operators[node.op]} ") + self.visit(node.expr, frame) + + @optimizeconst + def visit_Getattr(self, node: nodes.Getattr, frame: Frame) -> None: + if self.environment.is_async: + self.write("(await auto_await(") + + self.write("environment.getattr(") + self.visit(node.node, frame) + self.write(f", {node.attr!r})") + + if self.environment.is_async: + self.write("))") + + @optimizeconst + def visit_Getitem(self, node: nodes.Getitem, frame: Frame) -> None: + # slices bypass the environment getitem method. + if isinstance(node.arg, nodes.Slice): + self.visit(node.node, frame) + self.write("[") + self.visit(node.arg, frame) + self.write("]") + else: + if self.environment.is_async: + self.write("(await auto_await(") + + self.write("environment.getitem(") + self.visit(node.node, frame) + self.write(", ") + self.visit(node.arg, frame) + self.write(")") + + if self.environment.is_async: + self.write("))") + + def visit_Slice(self, node: nodes.Slice, frame: Frame) -> None: + if node.start is not None: + self.visit(node.start, frame) + self.write(":") + if node.stop is not None: + self.visit(node.stop, frame) + if node.step is not None: + self.write(":") + self.visit(node.step, frame) + + @contextmanager + def _filter_test_common( + self, node: t.Union[nodes.Filter, nodes.Test], frame: Frame, is_filter: bool + ) -> t.Iterator[None]: + if self.environment.is_async: + self.write("(await auto_await(") + + if is_filter: + self.write(f"{self.filters[node.name]}(") + func = self.environment.filters.get(node.name) + else: + self.write(f"{self.tests[node.name]}(") + func = self.environment.tests.get(node.name) + + # When inside an If or CondExpr frame, allow the filter to be + # undefined at compile time and only raise an error if it's + # actually called at runtime. See pull_dependencies. + if func is None and not frame.soft_frame: + type_name = "filter" if is_filter else "test" + self.fail(f"No {type_name} named {node.name!r}.", node.lineno) + + pass_arg = { + _PassArg.context: "context", + _PassArg.eval_context: "context.eval_ctx", + _PassArg.environment: "environment", + }.get( + _PassArg.from_obj(func) # type: ignore + ) + + if pass_arg is not None: + self.write(f"{pass_arg}, ") + + # Back to the visitor function to handle visiting the target of + # the filter or test. + yield + + self.signature(node, frame) + self.write(")") + + if self.environment.is_async: + self.write("))") + + @optimizeconst + def visit_Filter(self, node: nodes.Filter, frame: Frame) -> None: + with self._filter_test_common(node, frame, True): + # if the filter node is None we are inside a filter block + # and want to write to the current buffer + if node.node is not None: + self.visit(node.node, frame) + elif frame.eval_ctx.volatile: + self.write( + f"(Markup(concat({frame.buffer}))" + f" if context.eval_ctx.autoescape else concat({frame.buffer}))" + ) + elif frame.eval_ctx.autoescape: + self.write(f"Markup(concat({frame.buffer}))") + else: + self.write(f"concat({frame.buffer})") + + @optimizeconst + def visit_Test(self, node: nodes.Test, frame: Frame) -> None: + with self._filter_test_common(node, frame, False): + self.visit(node.node, frame) + + @optimizeconst + def visit_CondExpr(self, node: nodes.CondExpr, frame: Frame) -> None: + frame = frame.soft() + + def write_expr2() -> None: + if node.expr2 is not None: + self.visit(node.expr2, frame) + return + + self.write( + f'cond_expr_undefined("the inline if-expression on' + f" {self.position(node)} evaluated to false and no else" + f' section was defined.")' + ) + + self.write("(") + self.visit(node.expr1, frame) + self.write(" if ") + self.visit(node.test, frame) + self.write(" else ") + write_expr2() + self.write(")") + + @optimizeconst + def visit_Call( + self, node: nodes.Call, frame: Frame, forward_caller: bool = False + ) -> None: + if self.environment.is_async: + self.write("(await auto_await(") + if self.environment.sandboxed: + self.write("environment.call(context, ") + else: + self.write("context.call(") + self.visit(node.node, frame) + extra_kwargs = {"caller": "caller"} if forward_caller else None + loop_kwargs = {"_loop_vars": "_loop_vars"} if frame.loop_frame else {} + block_kwargs = {"_block_vars": "_block_vars"} if frame.block_frame else {} + if extra_kwargs: + extra_kwargs.update(loop_kwargs, **block_kwargs) + elif loop_kwargs or block_kwargs: + extra_kwargs = dict(loop_kwargs, **block_kwargs) + self.signature(node, frame, extra_kwargs) + self.write(")") + if self.environment.is_async: + self.write("))") + + def visit_Keyword(self, node: nodes.Keyword, frame: Frame) -> None: + self.write(node.key + "=") + self.visit(node.value, frame) + + # -- Unused nodes for extensions + + def visit_MarkSafe(self, node: nodes.MarkSafe, frame: Frame) -> None: + self.write("Markup(") + self.visit(node.expr, frame) + self.write(")") + + def visit_MarkSafeIfAutoescape( + self, node: nodes.MarkSafeIfAutoescape, frame: Frame + ) -> None: + self.write("(Markup if context.eval_ctx.autoescape else identity)(") + self.visit(node.expr, frame) + self.write(")") + + def visit_EnvironmentAttribute( + self, node: nodes.EnvironmentAttribute, frame: Frame + ) -> None: + self.write("environment." + node.name) + + def visit_ExtensionAttribute( + self, node: nodes.ExtensionAttribute, frame: Frame + ) -> None: + self.write(f"environment.extensions[{node.identifier!r}].{node.name}") + + def visit_ImportedName(self, node: nodes.ImportedName, frame: Frame) -> None: + self.write(self.import_aliases[node.importname]) + + def visit_InternalName(self, node: nodes.InternalName, frame: Frame) -> None: + self.write(node.name) + + def visit_ContextReference( + self, node: nodes.ContextReference, frame: Frame + ) -> None: + self.write("context") + + def visit_DerivedContextReference( + self, node: nodes.DerivedContextReference, frame: Frame + ) -> None: + self.write(self.derive_context(frame)) + + def visit_Continue(self, node: nodes.Continue, frame: Frame) -> None: + self.writeline("continue", node) + + def visit_Break(self, node: nodes.Break, frame: Frame) -> None: + self.writeline("break", node) + + def visit_Scope(self, node: nodes.Scope, frame: Frame) -> None: + scope_frame = frame.inner() + scope_frame.symbols.analyze_node(node) + self.enter_frame(scope_frame) + self.blockvisit(node.body, scope_frame) + self.leave_frame(scope_frame) + + def visit_OverlayScope(self, node: nodes.OverlayScope, frame: Frame) -> None: + ctx = self.temporary_identifier() + self.writeline(f"{ctx} = {self.derive_context(frame)}") + self.writeline(f"{ctx}.vars = ") + self.visit(node.context, frame) + self.push_context_reference(ctx) + + scope_frame = frame.inner(isolated=True) + scope_frame.symbols.analyze_node(node) + self.enter_frame(scope_frame) + self.blockvisit(node.body, scope_frame) + self.leave_frame(scope_frame) + self.pop_context_reference() + + def visit_EvalContextModifier( + self, node: nodes.EvalContextModifier, frame: Frame + ) -> None: + for keyword in node.options: + self.writeline(f"context.eval_ctx.{keyword.key} = ") + self.visit(keyword.value, frame) + try: + val = keyword.value.as_const(frame.eval_ctx) + except nodes.Impossible: + frame.eval_ctx.volatile = True + else: + setattr(frame.eval_ctx, keyword.key, val) + + def visit_ScopedEvalContextModifier( + self, node: nodes.ScopedEvalContextModifier, frame: Frame + ) -> None: + old_ctx_name = self.temporary_identifier() + saved_ctx = frame.eval_ctx.save() + self.writeline(f"{old_ctx_name} = context.eval_ctx.save()") + self.visit_EvalContextModifier(node, frame) + for child in node.body: + self.visit(child, frame) + frame.eval_ctx.revert(saved_ctx) + self.writeline(f"context.eval_ctx.revert({old_ctx_name})") diff --git a/backend/venv/Lib/site-packages/jinja2/constants.py b/backend/venv/Lib/site-packages/jinja2/constants.py new file mode 100644 index 0000000..41a1c23 --- /dev/null +++ b/backend/venv/Lib/site-packages/jinja2/constants.py @@ -0,0 +1,20 @@ +#: list of lorem ipsum words used by the lipsum() helper function +LOREM_IPSUM_WORDS = """\ +a ac accumsan ad adipiscing aenean aliquam aliquet amet ante aptent arcu at +auctor augue bibendum blandit class commodo condimentum congue consectetuer +consequat conubia convallis cras cubilia cum curabitur curae cursus dapibus +diam dictum dictumst dignissim dis dolor donec dui duis egestas eget eleifend +elementum elit enim erat eros est et etiam eu euismod facilisi facilisis fames +faucibus felis fermentum feugiat fringilla fusce gravida habitant habitasse hac +hendrerit hymenaeos iaculis id imperdiet in inceptos integer interdum ipsum +justo lacinia lacus laoreet lectus leo libero ligula litora lobortis lorem +luctus maecenas magna magnis malesuada massa mattis mauris metus mi molestie +mollis montes morbi mus nam nascetur natoque nec neque netus nibh nisi nisl non +nonummy nostra nulla nullam nunc odio orci ornare parturient pede pellentesque +penatibus per pharetra phasellus placerat platea porta porttitor posuere +potenti praesent pretium primis proin pulvinar purus quam quis quisque rhoncus +ridiculus risus rutrum sagittis sapien scelerisque sed sem semper senectus sit +sociis sociosqu sodales sollicitudin suscipit suspendisse taciti tellus tempor +tempus tincidunt torquent tortor tristique turpis ullamcorper ultrices +ultricies urna ut varius vehicula vel velit venenatis vestibulum vitae vivamus +viverra volutpat vulputate""" diff --git a/backend/venv/Lib/site-packages/jinja2/debug.py b/backend/venv/Lib/site-packages/jinja2/debug.py new file mode 100644 index 0000000..eeeeee7 --- /dev/null +++ b/backend/venv/Lib/site-packages/jinja2/debug.py @@ -0,0 +1,191 @@ +import sys +import typing as t +from types import CodeType +from types import TracebackType + +from .exceptions import TemplateSyntaxError +from .utils import internal_code +from .utils import missing + +if t.TYPE_CHECKING: + from .runtime import Context + + +def rewrite_traceback_stack(source: t.Optional[str] = None) -> BaseException: + """Rewrite the current exception to replace any tracebacks from + within compiled template code with tracebacks that look like they + came from the template source. + + This must be called within an ``except`` block. + + :param source: For ``TemplateSyntaxError``, the original source if + known. + :return: The original exception with the rewritten traceback. + """ + _, exc_value, tb = sys.exc_info() + exc_value = t.cast(BaseException, exc_value) + tb = t.cast(TracebackType, tb) + + if isinstance(exc_value, TemplateSyntaxError) and not exc_value.translated: + exc_value.translated = True + exc_value.source = source + # Remove the old traceback, otherwise the frames from the + # compiler still show up. + exc_value.with_traceback(None) + # Outside of runtime, so the frame isn't executing template + # code, but it still needs to point at the template. + tb = fake_traceback( + exc_value, None, exc_value.filename or "", exc_value.lineno + ) + else: + # Skip the frame for the render function. + tb = tb.tb_next + + stack = [] + + # Build the stack of traceback object, replacing any in template + # code with the source file and line information. + while tb is not None: + # Skip frames decorated with @internalcode. These are internal + # calls that aren't useful in template debugging output. + if tb.tb_frame.f_code in internal_code: + tb = tb.tb_next + continue + + template = tb.tb_frame.f_globals.get("__jinja_template__") + + if template is not None: + lineno = template.get_corresponding_lineno(tb.tb_lineno) + fake_tb = fake_traceback(exc_value, tb, template.filename, lineno) + stack.append(fake_tb) + else: + stack.append(tb) + + tb = tb.tb_next + + tb_next = None + + # Assign tb_next in reverse to avoid circular references. + for tb in reversed(stack): + tb.tb_next = tb_next + tb_next = tb + + return exc_value.with_traceback(tb_next) + + +def fake_traceback( # type: ignore + exc_value: BaseException, tb: t.Optional[TracebackType], filename: str, lineno: int +) -> TracebackType: + """Produce a new traceback object that looks like it came from the + template source instead of the compiled code. The filename, line + number, and location name will point to the template, and the local + variables will be the current template context. + + :param exc_value: The original exception to be re-raised to create + the new traceback. + :param tb: The original traceback to get the local variables and + code info from. + :param filename: The template filename. + :param lineno: The line number in the template source. + """ + if tb is not None: + # Replace the real locals with the context that would be + # available at that point in the template. + locals = get_template_locals(tb.tb_frame.f_locals) + locals.pop("__jinja_exception__", None) + else: + locals = {} + + globals = { + "__name__": filename, + "__file__": filename, + "__jinja_exception__": exc_value, + } + # Raise an exception at the correct line number. + code: CodeType = compile( + "\n" * (lineno - 1) + "raise __jinja_exception__", filename, "exec" + ) + + # Build a new code object that points to the template file and + # replaces the location with a block name. + location = "template" + + if tb is not None: + function = tb.tb_frame.f_code.co_name + + if function == "root": + location = "top-level template code" + elif function.startswith("block_"): + location = f"block {function[6:]!r}" + + if sys.version_info >= (3, 8): + code = code.replace(co_name=location) + else: + code = CodeType( + code.co_argcount, + code.co_kwonlyargcount, + code.co_nlocals, + code.co_stacksize, + code.co_flags, + code.co_code, + code.co_consts, + code.co_names, + code.co_varnames, + code.co_filename, + location, + code.co_firstlineno, + code.co_lnotab, + code.co_freevars, + code.co_cellvars, + ) + + # Execute the new code, which is guaranteed to raise, and return + # the new traceback without this frame. + try: + exec(code, globals, locals) + except BaseException: + return sys.exc_info()[2].tb_next # type: ignore + + +def get_template_locals(real_locals: t.Mapping[str, t.Any]) -> t.Dict[str, t.Any]: + """Based on the runtime locals, get the context that would be + available at that point in the template. + """ + # Start with the current template context. + ctx: t.Optional[Context] = real_locals.get("context") + + if ctx is not None: + data: t.Dict[str, t.Any] = ctx.get_all().copy() + else: + data = {} + + # Might be in a derived context that only sets local variables + # rather than pushing a context. Local variables follow the scheme + # l_depth_name. Find the highest-depth local that has a value for + # each name. + local_overrides: t.Dict[str, t.Tuple[int, t.Any]] = {} + + for name, value in real_locals.items(): + if not name.startswith("l_") or value is missing: + # Not a template variable, or no longer relevant. + continue + + try: + _, depth_str, name = name.split("_", 2) + depth = int(depth_str) + except ValueError: + continue + + cur_depth = local_overrides.get(name, (-1,))[0] + + if cur_depth < depth: + local_overrides[name] = (depth, value) + + # Modify the context with any derived context. + for name, (_, value) in local_overrides.items(): + if value is missing: + data.pop(name, None) + else: + data[name] = value + + return data diff --git a/backend/venv/Lib/site-packages/jinja2/defaults.py b/backend/venv/Lib/site-packages/jinja2/defaults.py new file mode 100644 index 0000000..638cad3 --- /dev/null +++ b/backend/venv/Lib/site-packages/jinja2/defaults.py @@ -0,0 +1,48 @@ +import typing as t + +from .filters import FILTERS as DEFAULT_FILTERS # noqa: F401 +from .tests import TESTS as DEFAULT_TESTS # noqa: F401 +from .utils import Cycler +from .utils import generate_lorem_ipsum +from .utils import Joiner +from .utils import Namespace + +if t.TYPE_CHECKING: + import typing_extensions as te + +# defaults for the parser / lexer +BLOCK_START_STRING = "{%" +BLOCK_END_STRING = "%}" +VARIABLE_START_STRING = "{{" +VARIABLE_END_STRING = "}}" +COMMENT_START_STRING = "{#" +COMMENT_END_STRING = "#}" +LINE_STATEMENT_PREFIX: t.Optional[str] = None +LINE_COMMENT_PREFIX: t.Optional[str] = None +TRIM_BLOCKS = False +LSTRIP_BLOCKS = False +NEWLINE_SEQUENCE: "te.Literal['\\n', '\\r\\n', '\\r']" = "\n" +KEEP_TRAILING_NEWLINE = False + +# default filters, tests and namespace + +DEFAULT_NAMESPACE = { + "range": range, + "dict": dict, + "lipsum": generate_lorem_ipsum, + "cycler": Cycler, + "joiner": Joiner, + "namespace": Namespace, +} + +# default policies +DEFAULT_POLICIES: t.Dict[str, t.Any] = { + "compiler.ascii_str": True, + "urlize.rel": "noopener", + "urlize.target": None, + "urlize.extra_schemes": None, + "truncate.leeway": 5, + "json.dumps_function": None, + "json.dumps_kwargs": {"sort_keys": True}, + "ext.i18n.trimmed": False, +} diff --git a/backend/venv/Lib/site-packages/jinja2/environment.py b/backend/venv/Lib/site-packages/jinja2/environment.py new file mode 100644 index 0000000..0fc6e5b --- /dev/null +++ b/backend/venv/Lib/site-packages/jinja2/environment.py @@ -0,0 +1,1672 @@ +"""Classes for managing templates and their runtime and compile time +options. +""" + +import os +import typing +import typing as t +import weakref +from collections import ChainMap +from functools import lru_cache +from functools import partial +from functools import reduce +from types import CodeType + +from markupsafe import Markup + +from . import nodes +from .compiler import CodeGenerator +from .compiler import generate +from .defaults import BLOCK_END_STRING +from .defaults import BLOCK_START_STRING +from .defaults import COMMENT_END_STRING +from .defaults import COMMENT_START_STRING +from .defaults import DEFAULT_FILTERS # type: ignore[attr-defined] +from .defaults import DEFAULT_NAMESPACE +from .defaults import DEFAULT_POLICIES +from .defaults import DEFAULT_TESTS # type: ignore[attr-defined] +from .defaults import KEEP_TRAILING_NEWLINE +from .defaults import LINE_COMMENT_PREFIX +from .defaults import LINE_STATEMENT_PREFIX +from .defaults import LSTRIP_BLOCKS +from .defaults import NEWLINE_SEQUENCE +from .defaults import TRIM_BLOCKS +from .defaults import VARIABLE_END_STRING +from .defaults import VARIABLE_START_STRING +from .exceptions import TemplateNotFound +from .exceptions import TemplateRuntimeError +from .exceptions import TemplatesNotFound +from .exceptions import TemplateSyntaxError +from .exceptions import UndefinedError +from .lexer import get_lexer +from .lexer import Lexer +from .lexer import TokenStream +from .nodes import EvalContext +from .parser import Parser +from .runtime import Context +from .runtime import new_context +from .runtime import Undefined +from .utils import _PassArg +from .utils import concat +from .utils import consume +from .utils import import_string +from .utils import internalcode +from .utils import LRUCache +from .utils import missing + +if t.TYPE_CHECKING: + import typing_extensions as te + + from .bccache import BytecodeCache + from .ext import Extension + from .loaders import BaseLoader + +_env_bound = t.TypeVar("_env_bound", bound="Environment") + + +# for direct template usage we have up to ten living environments +@lru_cache(maxsize=10) +def get_spontaneous_environment(cls: t.Type[_env_bound], *args: t.Any) -> _env_bound: + """Return a new spontaneous environment. A spontaneous environment + is used for templates created directly rather than through an + existing environment. + + :param cls: Environment class to create. + :param args: Positional arguments passed to environment. + """ + env = cls(*args) + env.shared = True + return env + + +def create_cache( + size: int, +) -> t.Optional[t.MutableMapping[t.Tuple["weakref.ref[t.Any]", str], "Template"]]: + """Return the cache class for the given size.""" + if size == 0: + return None + + if size < 0: + return {} + + return LRUCache(size) # type: ignore + + +def copy_cache( + cache: t.Optional[t.MutableMapping[t.Any, t.Any]], +) -> t.Optional[t.MutableMapping[t.Tuple["weakref.ref[t.Any]", str], "Template"]]: + """Create an empty copy of the given cache.""" + if cache is None: + return None + + if type(cache) is dict: # noqa E721 + return {} + + return LRUCache(cache.capacity) # type: ignore + + +def load_extensions( + environment: "Environment", + extensions: t.Sequence[t.Union[str, t.Type["Extension"]]], +) -> t.Dict[str, "Extension"]: + """Load the extensions from the list and bind it to the environment. + Returns a dict of instantiated extensions. + """ + result = {} + + for extension in extensions: + if isinstance(extension, str): + extension = t.cast(t.Type["Extension"], import_string(extension)) + + result[extension.identifier] = extension(environment) + + return result + + +def _environment_config_check(environment: _env_bound) -> _env_bound: + """Perform a sanity check on the environment.""" + assert issubclass( + environment.undefined, Undefined + ), "'undefined' must be a subclass of 'jinja2.Undefined'." + assert ( + environment.block_start_string + != environment.variable_start_string + != environment.comment_start_string + ), "block, variable and comment start strings must be different." + assert environment.newline_sequence in { + "\r", + "\r\n", + "\n", + }, "'newline_sequence' must be one of '\\n', '\\r\\n', or '\\r'." + return environment + + +class Environment: + r"""The core component of Jinja is the `Environment`. It contains + important shared variables like configuration, filters, tests, + globals and others. Instances of this class may be modified if + they are not shared and if no template was loaded so far. + Modifications on environments after the first template was loaded + will lead to surprising effects and undefined behavior. + + Here are the possible initialization parameters: + + `block_start_string` + The string marking the beginning of a block. Defaults to ``'{%'``. + + `block_end_string` + The string marking the end of a block. Defaults to ``'%}'``. + + `variable_start_string` + The string marking the beginning of a print statement. + Defaults to ``'{{'``. + + `variable_end_string` + The string marking the end of a print statement. Defaults to + ``'}}'``. + + `comment_start_string` + The string marking the beginning of a comment. Defaults to ``'{#'``. + + `comment_end_string` + The string marking the end of a comment. Defaults to ``'#}'``. + + `line_statement_prefix` + If given and a string, this will be used as prefix for line based + statements. See also :ref:`line-statements`. + + `line_comment_prefix` + If given and a string, this will be used as prefix for line based + comments. See also :ref:`line-statements`. + + .. versionadded:: 2.2 + + `trim_blocks` + If this is set to ``True`` the first newline after a block is + removed (block, not variable tag!). Defaults to `False`. + + `lstrip_blocks` + If this is set to ``True`` leading spaces and tabs are stripped + from the start of a line to a block. Defaults to `False`. + + `newline_sequence` + The sequence that starts a newline. Must be one of ``'\r'``, + ``'\n'`` or ``'\r\n'``. The default is ``'\n'`` which is a + useful default for Linux and OS X systems as well as web + applications. + + `keep_trailing_newline` + Preserve the trailing newline when rendering templates. + The default is ``False``, which causes a single newline, + if present, to be stripped from the end of the template. + + .. versionadded:: 2.7 + + `extensions` + List of Jinja extensions to use. This can either be import paths + as strings or extension classes. For more information have a + look at :ref:`the extensions documentation `. + + `optimized` + should the optimizer be enabled? Default is ``True``. + + `undefined` + :class:`Undefined` or a subclass of it that is used to represent + undefined values in the template. + + `finalize` + A callable that can be used to process the result of a variable + expression before it is output. For example one can convert + ``None`` implicitly into an empty string here. + + `autoescape` + If set to ``True`` the XML/HTML autoescaping feature is enabled by + default. For more details about autoescaping see + :class:`~markupsafe.Markup`. As of Jinja 2.4 this can also + be a callable that is passed the template name and has to + return ``True`` or ``False`` depending on autoescape should be + enabled by default. + + .. versionchanged:: 2.4 + `autoescape` can now be a function + + `loader` + The template loader for this environment. + + `cache_size` + The size of the cache. Per default this is ``400`` which means + that if more than 400 templates are loaded the loader will clean + out the least recently used template. If the cache size is set to + ``0`` templates are recompiled all the time, if the cache size is + ``-1`` the cache will not be cleaned. + + .. versionchanged:: 2.8 + The cache size was increased to 400 from a low 50. + + `auto_reload` + Some loaders load templates from locations where the template + sources may change (ie: file system or database). If + ``auto_reload`` is set to ``True`` (default) every time a template is + requested the loader checks if the source changed and if yes, it + will reload the template. For higher performance it's possible to + disable that. + + `bytecode_cache` + If set to a bytecode cache object, this object will provide a + cache for the internal Jinja bytecode so that templates don't + have to be parsed if they were not changed. + + See :ref:`bytecode-cache` for more information. + + `enable_async` + If set to true this enables async template execution which + allows using async functions and generators. + """ + + #: if this environment is sandboxed. Modifying this variable won't make + #: the environment sandboxed though. For a real sandboxed environment + #: have a look at jinja2.sandbox. This flag alone controls the code + #: generation by the compiler. + sandboxed = False + + #: True if the environment is just an overlay + overlayed = False + + #: the environment this environment is linked to if it is an overlay + linked_to: t.Optional["Environment"] = None + + #: shared environments have this set to `True`. A shared environment + #: must not be modified + shared = False + + #: the class that is used for code generation. See + #: :class:`~jinja2.compiler.CodeGenerator` for more information. + code_generator_class: t.Type["CodeGenerator"] = CodeGenerator + + concat = "".join + + #: the context class that is used for templates. See + #: :class:`~jinja2.runtime.Context` for more information. + context_class: t.Type[Context] = Context + + template_class: t.Type["Template"] + + def __init__( + self, + block_start_string: str = BLOCK_START_STRING, + block_end_string: str = BLOCK_END_STRING, + variable_start_string: str = VARIABLE_START_STRING, + variable_end_string: str = VARIABLE_END_STRING, + comment_start_string: str = COMMENT_START_STRING, + comment_end_string: str = COMMENT_END_STRING, + line_statement_prefix: t.Optional[str] = LINE_STATEMENT_PREFIX, + line_comment_prefix: t.Optional[str] = LINE_COMMENT_PREFIX, + trim_blocks: bool = TRIM_BLOCKS, + lstrip_blocks: bool = LSTRIP_BLOCKS, + newline_sequence: "te.Literal['\\n', '\\r\\n', '\\r']" = NEWLINE_SEQUENCE, + keep_trailing_newline: bool = KEEP_TRAILING_NEWLINE, + extensions: t.Sequence[t.Union[str, t.Type["Extension"]]] = (), + optimized: bool = True, + undefined: t.Type[Undefined] = Undefined, + finalize: t.Optional[t.Callable[..., t.Any]] = None, + autoescape: t.Union[bool, t.Callable[[t.Optional[str]], bool]] = False, + loader: t.Optional["BaseLoader"] = None, + cache_size: int = 400, + auto_reload: bool = True, + bytecode_cache: t.Optional["BytecodeCache"] = None, + enable_async: bool = False, + ): + # !!Important notice!! + # The constructor accepts quite a few arguments that should be + # passed by keyword rather than position. However it's important to + # not change the order of arguments because it's used at least + # internally in those cases: + # - spontaneous environments (i18n extension and Template) + # - unittests + # If parameter changes are required only add parameters at the end + # and don't change the arguments (or the defaults!) of the arguments + # existing already. + + # lexer / parser information + self.block_start_string = block_start_string + self.block_end_string = block_end_string + self.variable_start_string = variable_start_string + self.variable_end_string = variable_end_string + self.comment_start_string = comment_start_string + self.comment_end_string = comment_end_string + self.line_statement_prefix = line_statement_prefix + self.line_comment_prefix = line_comment_prefix + self.trim_blocks = trim_blocks + self.lstrip_blocks = lstrip_blocks + self.newline_sequence = newline_sequence + self.keep_trailing_newline = keep_trailing_newline + + # runtime information + self.undefined: t.Type[Undefined] = undefined + self.optimized = optimized + self.finalize = finalize + self.autoescape = autoescape + + # defaults + self.filters = DEFAULT_FILTERS.copy() + self.tests = DEFAULT_TESTS.copy() + self.globals = DEFAULT_NAMESPACE.copy() + + # set the loader provided + self.loader = loader + self.cache = create_cache(cache_size) + self.bytecode_cache = bytecode_cache + self.auto_reload = auto_reload + + # configurable policies + self.policies = DEFAULT_POLICIES.copy() + + # load extensions + self.extensions = load_extensions(self, extensions) + + self.is_async = enable_async + _environment_config_check(self) + + def add_extension(self, extension: t.Union[str, t.Type["Extension"]]) -> None: + """Adds an extension after the environment was created. + + .. versionadded:: 2.5 + """ + self.extensions.update(load_extensions(self, [extension])) + + def extend(self, **attributes: t.Any) -> None: + """Add the items to the instance of the environment if they do not exist + yet. This is used by :ref:`extensions ` to register + callbacks and configuration values without breaking inheritance. + """ + for key, value in attributes.items(): + if not hasattr(self, key): + setattr(self, key, value) + + def overlay( + self, + block_start_string: str = missing, + block_end_string: str = missing, + variable_start_string: str = missing, + variable_end_string: str = missing, + comment_start_string: str = missing, + comment_end_string: str = missing, + line_statement_prefix: t.Optional[str] = missing, + line_comment_prefix: t.Optional[str] = missing, + trim_blocks: bool = missing, + lstrip_blocks: bool = missing, + newline_sequence: "te.Literal['\\n', '\\r\\n', '\\r']" = missing, + keep_trailing_newline: bool = missing, + extensions: t.Sequence[t.Union[str, t.Type["Extension"]]] = missing, + optimized: bool = missing, + undefined: t.Type[Undefined] = missing, + finalize: t.Optional[t.Callable[..., t.Any]] = missing, + autoescape: t.Union[bool, t.Callable[[t.Optional[str]], bool]] = missing, + loader: t.Optional["BaseLoader"] = missing, + cache_size: int = missing, + auto_reload: bool = missing, + bytecode_cache: t.Optional["BytecodeCache"] = missing, + enable_async: bool = missing, + ) -> "te.Self": + """Create a new overlay environment that shares all the data with the + current environment except for cache and the overridden attributes. + Extensions cannot be removed for an overlayed environment. An overlayed + environment automatically gets all the extensions of the environment it + is linked to plus optional extra extensions. + + Creating overlays should happen after the initial environment was set + up completely. Not all attributes are truly linked, some are just + copied over so modifications on the original environment may not shine + through. + + .. versionchanged:: 3.1.5 + ``enable_async`` is applied correctly. + + .. versionchanged:: 3.1.2 + Added the ``newline_sequence``, ``keep_trailing_newline``, + and ``enable_async`` parameters to match ``__init__``. + """ + args = dict(locals()) + del args["self"], args["cache_size"], args["extensions"], args["enable_async"] + + rv = object.__new__(self.__class__) + rv.__dict__.update(self.__dict__) + rv.overlayed = True + rv.linked_to = self + + for key, value in args.items(): + if value is not missing: + setattr(rv, key, value) + + if cache_size is not missing: + rv.cache = create_cache(cache_size) + else: + rv.cache = copy_cache(self.cache) + + rv.extensions = {} + for key, value in self.extensions.items(): + rv.extensions[key] = value.bind(rv) + if extensions is not missing: + rv.extensions.update(load_extensions(rv, extensions)) + + if enable_async is not missing: + rv.is_async = enable_async + + return _environment_config_check(rv) + + @property + def lexer(self) -> Lexer: + """The lexer for this environment.""" + return get_lexer(self) + + def iter_extensions(self) -> t.Iterator["Extension"]: + """Iterates over the extensions by priority.""" + return iter(sorted(self.extensions.values(), key=lambda x: x.priority)) + + def getitem( + self, obj: t.Any, argument: t.Union[str, t.Any] + ) -> t.Union[t.Any, Undefined]: + """Get an item or attribute of an object but prefer the item.""" + try: + return obj[argument] + except (AttributeError, TypeError, LookupError): + if isinstance(argument, str): + try: + attr = str(argument) + except Exception: + pass + else: + try: + return getattr(obj, attr) + except AttributeError: + pass + return self.undefined(obj=obj, name=argument) + + def getattr(self, obj: t.Any, attribute: str) -> t.Any: + """Get an item or attribute of an object but prefer the attribute. + Unlike :meth:`getitem` the attribute *must* be a string. + """ + try: + return getattr(obj, attribute) + except AttributeError: + pass + try: + return obj[attribute] + except (TypeError, LookupError, AttributeError): + return self.undefined(obj=obj, name=attribute) + + def _filter_test_common( + self, + name: t.Union[str, Undefined], + value: t.Any, + args: t.Optional[t.Sequence[t.Any]], + kwargs: t.Optional[t.Mapping[str, t.Any]], + context: t.Optional[Context], + eval_ctx: t.Optional[EvalContext], + is_filter: bool, + ) -> t.Any: + if is_filter: + env_map = self.filters + type_name = "filter" + else: + env_map = self.tests + type_name = "test" + + func = env_map.get(name) # type: ignore + + if func is None: + msg = f"No {type_name} named {name!r}." + + if isinstance(name, Undefined): + try: + name._fail_with_undefined_error() + except Exception as e: + msg = f"{msg} ({e}; did you forget to quote the callable name?)" + + raise TemplateRuntimeError(msg) + + args = [value, *(args if args is not None else ())] + kwargs = kwargs if kwargs is not None else {} + pass_arg = _PassArg.from_obj(func) + + if pass_arg is _PassArg.context: + if context is None: + raise TemplateRuntimeError( + f"Attempted to invoke a context {type_name} without context." + ) + + args.insert(0, context) + elif pass_arg is _PassArg.eval_context: + if eval_ctx is None: + if context is not None: + eval_ctx = context.eval_ctx + else: + eval_ctx = EvalContext(self) + + args.insert(0, eval_ctx) + elif pass_arg is _PassArg.environment: + args.insert(0, self) + + return func(*args, **kwargs) + + def call_filter( + self, + name: str, + value: t.Any, + args: t.Optional[t.Sequence[t.Any]] = None, + kwargs: t.Optional[t.Mapping[str, t.Any]] = None, + context: t.Optional[Context] = None, + eval_ctx: t.Optional[EvalContext] = None, + ) -> t.Any: + """Invoke a filter on a value the same way the compiler does. + + This might return a coroutine if the filter is running from an + environment in async mode and the filter supports async + execution. It's your responsibility to await this if needed. + + .. versionadded:: 2.7 + """ + return self._filter_test_common( + name, value, args, kwargs, context, eval_ctx, True + ) + + def call_test( + self, + name: str, + value: t.Any, + args: t.Optional[t.Sequence[t.Any]] = None, + kwargs: t.Optional[t.Mapping[str, t.Any]] = None, + context: t.Optional[Context] = None, + eval_ctx: t.Optional[EvalContext] = None, + ) -> t.Any: + """Invoke a test on a value the same way the compiler does. + + This might return a coroutine if the test is running from an + environment in async mode and the test supports async execution. + It's your responsibility to await this if needed. + + .. versionchanged:: 3.0 + Tests support ``@pass_context``, etc. decorators. Added + the ``context`` and ``eval_ctx`` parameters. + + .. versionadded:: 2.7 + """ + return self._filter_test_common( + name, value, args, kwargs, context, eval_ctx, False + ) + + @internalcode + def parse( + self, + source: str, + name: t.Optional[str] = None, + filename: t.Optional[str] = None, + ) -> nodes.Template: + """Parse the sourcecode and return the abstract syntax tree. This + tree of nodes is used by the compiler to convert the template into + executable source- or bytecode. This is useful for debugging or to + extract information from templates. + + If you are :ref:`developing Jinja extensions ` + this gives you a good overview of the node tree generated. + """ + try: + return self._parse(source, name, filename) + except TemplateSyntaxError: + self.handle_exception(source=source) + + def _parse( + self, source: str, name: t.Optional[str], filename: t.Optional[str] + ) -> nodes.Template: + """Internal parsing function used by `parse` and `compile`.""" + return Parser(self, source, name, filename).parse() + + def lex( + self, + source: str, + name: t.Optional[str] = None, + filename: t.Optional[str] = None, + ) -> t.Iterator[t.Tuple[int, str, str]]: + """Lex the given sourcecode and return a generator that yields + tokens as tuples in the form ``(lineno, token_type, value)``. + This can be useful for :ref:`extension development ` + and debugging templates. + + This does not perform preprocessing. If you want the preprocessing + of the extensions to be applied you have to filter source through + the :meth:`preprocess` method. + """ + source = str(source) + try: + return self.lexer.tokeniter(source, name, filename) + except TemplateSyntaxError: + self.handle_exception(source=source) + + def preprocess( + self, + source: str, + name: t.Optional[str] = None, + filename: t.Optional[str] = None, + ) -> str: + """Preprocesses the source with all extensions. This is automatically + called for all parsing and compiling methods but *not* for :meth:`lex` + because there you usually only want the actual source tokenized. + """ + return reduce( + lambda s, e: e.preprocess(s, name, filename), + self.iter_extensions(), + str(source), + ) + + def _tokenize( + self, + source: str, + name: t.Optional[str], + filename: t.Optional[str] = None, + state: t.Optional[str] = None, + ) -> TokenStream: + """Called by the parser to do the preprocessing and filtering + for all the extensions. Returns a :class:`~jinja2.lexer.TokenStream`. + """ + source = self.preprocess(source, name, filename) + stream = self.lexer.tokenize(source, name, filename, state) + + for ext in self.iter_extensions(): + stream = ext.filter_stream(stream) # type: ignore + + if not isinstance(stream, TokenStream): + stream = TokenStream(stream, name, filename) + + return stream + + def _generate( + self, + source: nodes.Template, + name: t.Optional[str], + filename: t.Optional[str], + defer_init: bool = False, + ) -> str: + """Internal hook that can be overridden to hook a different generate + method in. + + .. versionadded:: 2.5 + """ + return generate( # type: ignore + source, + self, + name, + filename, + defer_init=defer_init, + optimized=self.optimized, + ) + + def _compile(self, source: str, filename: str) -> CodeType: + """Internal hook that can be overridden to hook a different compile + method in. + + .. versionadded:: 2.5 + """ + return compile(source, filename, "exec") + + @typing.overload + def compile( + self, + source: t.Union[str, nodes.Template], + name: t.Optional[str] = None, + filename: t.Optional[str] = None, + raw: "te.Literal[False]" = False, + defer_init: bool = False, + ) -> CodeType: ... + + @typing.overload + def compile( + self, + source: t.Union[str, nodes.Template], + name: t.Optional[str] = None, + filename: t.Optional[str] = None, + raw: "te.Literal[True]" = ..., + defer_init: bool = False, + ) -> str: ... + + @internalcode + def compile( + self, + source: t.Union[str, nodes.Template], + name: t.Optional[str] = None, + filename: t.Optional[str] = None, + raw: bool = False, + defer_init: bool = False, + ) -> t.Union[str, CodeType]: + """Compile a node or template source code. The `name` parameter is + the load name of the template after it was joined using + :meth:`join_path` if necessary, not the filename on the file system. + the `filename` parameter is the estimated filename of the template on + the file system. If the template came from a database or memory this + can be omitted. + + The return value of this method is a python code object. If the `raw` + parameter is `True` the return value will be a string with python + code equivalent to the bytecode returned otherwise. This method is + mainly used internally. + + `defer_init` is use internally to aid the module code generator. This + causes the generated code to be able to import without the global + environment variable to be set. + + .. versionadded:: 2.4 + `defer_init` parameter added. + """ + source_hint = None + try: + if isinstance(source, str): + source_hint = source + source = self._parse(source, name, filename) + source = self._generate(source, name, filename, defer_init=defer_init) + if raw: + return source + if filename is None: + filename = "